emacs-diffs
[Top][All Lists]
Advanced

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

scratch/correct-warning-pos d87a34597c: Merge branch 'master' into scrat


From: Alan Mackenzie
Subject: scratch/correct-warning-pos d87a34597c: Merge branch 'master' into scratch/correct-warning-pos
Date: Fri, 14 Jan 2022 14:31:44 -0500 (EST)

branch: scratch/correct-warning-pos
commit d87a34597c9f0be967f75ff8cfd0ace4392da63f
Merge: 57b698f159 d29291d665
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    Merge branch 'master' into scratch/correct-warning-pos
    
    Merge branch:
    commit d29291d665e808307126bf52c3e748fef78f0f9c (HEAD -> master,
    origin/master, origin/HEAD)
    Author: Stefan Monnier <monnier@iro.umontreal.ca>
    Date:   Fri Jan 14 12:26:30 2022 -0500
    
        (macroexp--expand-all): Fix bug#53227 and bug#46636
---
 INSTALL                                   |   27 +
 Makefile.in                               |    3 +
 admin/grammars/Makefile.in                |    4 +-
 admin/unidata/Makefile.in                 |    3 +
 doc/emacs/frames.texi                     |   10 +
 doc/emacs/maintaining.texi                |   27 +-
 doc/emacs/search.texi                     |   25 +-
 doc/lispref/functions.texi                |   16 +
 doc/lispref/modes.texi                    |    3 +
 doc/lispref/windows.texi                  |    7 -
 doc/misc/Makefile.in                      |    4 +
 doc/misc/eshell.texi                      |  120 ++
 doc/misc/gnus.texi                        |    3 -
 doc/misc/tramp.texi                       |    4 +-
 etc/NEWS                                  |   40 +-
 leim/Makefile.in                          |    5 +-
 lib-src/Makefile.in                       |    3 +
 lisp/Makefile.in                          |    5 +-
 lisp/auth-source.el                       |    2 +-
 lisp/battery.el                           |    2 +
 lisp/cedet/ede/project-am.el              |    3 +-
 lisp/emacs-lisp/easy-mmode.el             |    6 +-
 lisp/emacs-lisp/ert.el                    |   17 +-
 lisp/emacs-lisp/inline.el                 |    2 +-
 lisp/emacs-lisp/macroexp.el               |    8 +-
 lisp/emacs-lisp/shortdoc.el               |    3 +
 lisp/eshell/esh-opt.el                    |   90 +-
 lisp/ffap.el                              |   11 +-
 lisp/files.el                             |   14 +-
 lisp/frame.el                             |   75 ++
 lisp/gnus/gnus-art.el                     |    6 +-
 lisp/gnus/gnus-registry.el                |   25 +-
 lisp/gnus/nnimap.el                       |    2 +-
 lisp/gnus/nntp.el                         |    8 +-
 lisp/help-fns.el                          |    6 +-
 lisp/hi-lock.el                           |   20 +
 lisp/image-dired.el                       |    4 +-
 lisp/isearch.el                           |   21 +
 lisp/jsonrpc.el                           |    6 +-
 lisp/ldefs-boot.el                        |  203 ++-
 lisp/leim/quail/emoji.el                  | 2003 +++++++++++++++++++++++++++++
 lisp/man.el                               |   24 +
 lisp/menu-bar.el                          |   10 +
 lisp/mouse.el                             |   33 +
 lisp/net/mailcap.el                       |    7 +-
 lisp/net/tramp-crypt.el                   |    2 +-
 lisp/progmodes/gud.el                     |    8 +-
 lisp/progmodes/python.el                  |   12 +-
 lisp/progmodes/xref.el                    |   33 +-
 lisp/subr.el                              |   24 +-
 lisp/vc/pcvs-info.el                      |    8 +-
 src/buffer.c                              |    2 +-
 src/data.c                                |   16 +-
 src/font.c                                |   43 +-
 src/frame.c                               |    5 +-
 src/ftfont.c                              |   21 +
 src/gtkutil.c                             |   11 +-
 src/haiku_draw_support.cc                 |    2 +-
 src/haiku_support.cc                      |   30 +-
 src/haikuterm.c                           |    7 +-
 src/window.c                              |    3 +-
 src/xdisp.c                               |   14 +
 src/xfns.c                                |    4 +
 src/xterm.c                               |  157 ++-
 src/xwidget.c                             |    4 +-
 test/Makefile.in                          |    8 +-
 test/lisp/emacs-lisp/edebug-tests.el      |   10 +
 test/lisp/emacs-lisp/ert-tests.el         |    3 +
 test/lisp/eshell/esh-opt-tests.el         |  151 ++-
 test/lisp/ffap-tests.el                   |   17 +
 test/lisp/help-fns-tests.el               |    9 +
 test/lisp/so-long-tests/spelling-tests.el |   16 +-
 test/lisp/subr-tests.el                   |   17 +
 73 files changed, 3247 insertions(+), 310 deletions(-)

diff --git a/INSTALL b/INSTALL
index 02d5a09d63..7cb7e0526a 100644
--- a/INSTALL
+++ b/INSTALL
@@ -226,6 +226,33 @@ e.g. 'emacs25').  On Red Hat-based systems, the 
corresponding command is
 
 On FreeBSD, the command is 'pkg install -y `pkg rquery %dn emacs-devel`'.
 
+* Alternative window systems
+
+If you want to use Emacs on one of the alternative window systems
+available on GNU/Linux and some Unix systems, such as Wayland or
+Broadway, you can build the PGTK ("Pure GTK") port of Emacs, which
+utilizes the GTK+ toolkit to support those window systems.  To this
+end, invoke the configure script with the '--with-pgtk' option, like
+this:
+
+       ./configure --with-pgtk
+
+This build is only supported with GTK+ version 3, and it is an error
+to specify any other X-specific configuration option when PGTK is
+enabled.
+
+With the PGTK build, you will be able to switch between running Emacs
+on X, Wayland and Broadway using the 'GDK_BACKEND' environment
+variable.  GTK+ should automatically detect and use the correct value
+for your system, but you can also specify it manually.  For example,
+to force GTK+ to run under Broadway, start Emacs like this:
+
+       GDK_BACKEND=broadway emacs ...
+
+(where '...' denotes any further options you may want to pass to Emacs).
+
+The GNUstep build also supports the Wayland window system.  If that is
+what you want, see nextstep/INSTALL.
 
 DETAILED BUILDING AND INSTALLATION:
 
diff --git a/Makefile.in b/Makefile.in
index b72127dde6..8ac6f52746 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -319,6 +319,9 @@ GLIB_COMPILE_SCHEMAS = glib-compile-schemas
 # Program name transformation.
 TRANSFORM = @program_transform_name@
 
+# Prevent any settings in the user environment causing problems.
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
+
 # What emacs should be called when installed.
 EMACS_NAME = `echo emacs | sed '$(TRANSFORM)'`
 EMACS = ${EMACS_NAME}${EXEEXT}
diff --git a/admin/grammars/Makefile.in b/admin/grammars/Makefile.in
index 83ac2ef46e..6f69943089 100644
--- a/admin/grammars/Makefile.in
+++ b/admin/grammars/Makefile.in
@@ -31,10 +31,10 @@ top_builddir = @top_builddir@
 -include ${top_builddir}/src/verbose.mk
 
 # Prevent any settings in the user environment causing problems.
-unexport EMACSDATA EMACSDOC EMACSPATH
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
 
 EMACS = ${top_builddir}/src/emacs
-emacs = EMACSLOADPATH= "${EMACS}" -batch --no-site-file --no-site-lisp --eval 
'(setq load-prefer-newer t)'
+emacs = "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq 
load-prefer-newer t)'
 
 make_bovine = ${emacs} -l semantic/bovine/grammar -f bovine-batch-make-parser
 make_wisent = ${emacs} -l semantic/wisent/grammar -f wisent-batch-make-parser
diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in
index 45bba85213..e75010dc2b 100644
--- a/admin/unidata/Makefile.in
+++ b/admin/unidata/Makefile.in
@@ -29,6 +29,9 @@ srcdir = @srcdir@
 top_srcdir = @top_srcdir@
 top_builddir = @top_builddir@
 
+# Prevent any settings in the user environment causing problems.
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
+
 EMACS = ${top_builddir}/src/emacs
 unidir = ${top_srcdir}/lisp/international
 emacs = "${EMACS}" -batch --no-site-file --no-site-lisp
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi
index ce43408101..c641b8ccb1 100644
--- a/doc/emacs/frames.texi
+++ b/doc/emacs/frames.texi
@@ -512,6 +512,16 @@ frames by specifying @dfn{frame parameters}.  @xref{Frame 
Parameters}.
 Delete the selected frame (@code{delete-frame}).  This signals an
 error if there is only one frame.
 
+@item C-x 5 u
+@kindex C-x 5 u
+@findex undelete-frame
+@findex undelete-frame-mode
+When @code{undelete-frame-mode} is enabled, undelete one of the 16
+most recently deleted frames.  Without a prefix argument, undelete the
+most recently deleted frame.  With a numerical prefix argument between
+1 and 16, where 1 is the most recently deleted frame, undelete the
+corresponding deleted frame.
+
 @item C-z
 @kindex C-z @r{(X windows)}
 Minimize (or iconify) the selected Emacs frame
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 9a23f23e0e..edcc6075f7 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -2317,10 +2317,15 @@ them.
 @item M-?
 Find all the references for the identifier at point.
 
-@item M-x xref-query-replace-in-results @key{RET} @var{regexp} @key{RET} 
@var{replacement} @key{RET}
+@item M-x xref-query-replace-in-results @key{RET} @var{replacement} @key{RET}
+@itemx C-u M-x xref-query-replace-in-results @key{RET} @var{regexp} @key{RET} 
@var{replacement} @key{RET}
 Interactively replace @var{regexp} with @var{replacement} in the names
 of all the identifiers shown in the @file{*xref*} buffer.
 
+@item M-x xref-find-references-and-replace @key{RET} @var{from} @key{RET} 
@var{to} @key{RET}
+Interactively rename all instances of the identifier @var{from} to the
+new name @var{to}.
+
 @item M-x tags-search @key{RET} @var{regexp} @key{RET}
 Search for @var{regexp} through the files in the selected tags
 table.
@@ -2358,13 +2363,21 @@ shown.  The default value is @code{nil}, which just 
shows the results
 in the @file{*xref*} buffer, but doesn't select any of them.
 
 @findex xref-query-replace-in-results
-  @kbd{M-x xref-query-replace-in-results} reads a regexp to match identifier
-names and a replacement string, just like ordinary @kbd{M-x
-query-replace-regexp}.  It then performs the specified replacement in
-the names of the matching identifiers in all the places in all the
-files where these identifiers are referenced.  This is useful when you
+  @kbd{M-x xref-query-replace-in-results} reads a @var{replacement}
+string, just like ordinary @kbd{M-x query-replace-regexp}.  It then
+renames the identifiers shown in the @file{*xref*} buffer in all the
+places in all the files where these identifiers are referenced, such
+that their new name is @var{replacement}.  This is useful when you
 rename your identifiers as part of refactoring.  This command should
-be invoked in the @file{*xref*} buffer generated by @kbd{M-?}.
+be invoked in the @file{*xref*} buffer generated by @kbd{M-?}.  With a
+prefix argument, the command also prompts for a regexp to match
+identifier names, and renames that regexp in the names of the matching
+identifiers with @var{replacement}.
+
+@findex xref-find-references-and-replace
+  @kbd{M-x xref-find-references-and-replace} works similarly to
+@code{xref-query-replace-in-results}, but is more convenient when you
+want to rename a single identifier specified by its name @var{from}.
 
 @findex tags-search
   @kbd{M-x tags-search} reads a regexp using the minibuffer, then
diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi
index c12992c239..fa1b0eee7c 100644
--- a/doc/emacs/search.texi
+++ b/doc/emacs/search.texi
@@ -435,14 +435,6 @@ search string, similar to inserting into a buffer using 
@kbd{C-q}
 incremental search adds the @samp{control-S} character to the search
 string.
 
-@item
-@findex isearch-char-by-name
-@kindex C-x 8 RET @r{(Incremental Search)}
-Type @kbd{C-x 8 @key{RET}} (@code{isearch-char-by-name}), followed by
-a Unicode name or code-point in hex.  This adds the specified
-character into the search string, similar to the usual
-@code{insert-char} command (@pxref{Inserting Text}).
-
 @item
 @kindex C-^ @r{(Incremental Search)}
 @findex isearch-toggle-input-method
@@ -473,6 +465,23 @@ character to the search string using an input method, and
 automatically disable the input method afterwards.
 @end itemize
 
+@findex isearch-char-by-name
+@kindex C-x 8 RET @r{(Incremental Search)}
+Type @kbd{C-x 8 @key{RET}} (@code{isearch-char-by-name}), followed by
+a Unicode name or code-point in hex.  This adds the specified
+character into the search string, similar to the usual
+@code{insert-char} command (@pxref{Inserting Text}).
+
+@findex isearch-emoji-by-name
+@kindex C-x 8 e RET @r{(Incremental Search)}
+  You can also include Emoji sequences in the search string.  Type
+@w{@kbd{C-x 8 e @key{RET}}} (@code{isearch-emoji-by-name}), followed
+by the Unicode name of an Emoji (for example, @kbd{smiling face} or
+@kbd{heart with arrow}).  This adds the specified Emoji to the search
+string.  If you don't know the name of the Emoji you want to search
+for, you can use @kbd{C-x 8 e l} (@code{emoji-list}) and @kbd{C-x 8 e
+d} (@code{emoji-describe}) (@pxref{Input Methods}).
+
 @kindex M-s o @r{(Incremental Search)}
 @findex isearch-occur
   Typing @kbd{M-s o} in incremental search invokes
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 96fecc8c89..2378e9efd7 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -667,6 +667,22 @@ which file defined the function, just like @code{defun}
 By contrast, in programs that manipulate function definitions for other
 purposes, it is better to use @code{fset}, which does not keep such
 records.  @xref{Function Cells}.
+@end defun
+
+@defun function-alias-p object &optional noerror
+Checks whether @var{object} is a function alias.  If it is, it returns
+a list of symbols representing the function alias chain, else
+@code{nil}.  For instance, if @code{a} is an alias for @code{b}, and
+@code{b} is an alias for @code{c}:
+
+@example
+(function-alias-p 'a)
+    @result{} (b c)
+@end example
+
+If there's a loop in the definitions, an error will be signalled.  If
+@var{noerror} is non-@code{nil}, the non-looping parts of the chain is
+returned instead.
 @end defun
 
   You cannot create a new primitive function with @code{defun} or
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 5fc831536e..e2b39836e6 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -762,6 +762,9 @@ uncompression packages: an entry of the form 
@code{("\\.gz\\'"
 @var{function} t)} can uncompress the file and then put the uncompressed
 file in the proper mode according to the name sans @samp{.gz}.
 
+If @code{auto-mode-alist} has more than one element whose @var{regexp}
+matches the file name, Emacs will use the first match.
+
 Here is an example of how to prepend several pattern pairs to
 @code{auto-mode-alist}.  (You might use this sort of expression in your
 init file.)
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 56b4bc5183..bbf8988e5c 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -5281,13 +5281,6 @@ other window is selected.  When it is non-@code{nil} and 
the
 minibuffer is selected, it takes precedence over
 @code{other-window-scroll-buffer}.  @xref{Definition of
 minibuffer-scroll-window}.
-
-When the minibuffer is active, it is the next window if the selected
-window is the one at the bottom right corner.  In this case,
-@code{scroll-other-window} attempts to scroll the minibuffer.  If the
-minibuffer contains just one line, it has nowhere to scroll to, so the
-line reappears after the echo area momentarily displays the message
-@samp{End of buffer}.
 @end deffn
 
 @deffn Command scroll-other-window-down &optional count
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index 6c1e9cbc91..d348dbc194 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -234,6 +234,10 @@ ${buildinfodir}/tramp.info tramp.html: 
${srcdir}/trampver.texi
 
 
 abs_top_builddir = @abs_top_builddir@
+
+# Prevent any settings in the user environment causing problems.
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
+
 EMACS = ${abs_top_builddir}/src/emacs
 emacs = "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq 
load-prefer-newer t)'
 
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 83d324c7e1..f1d7c63805 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -694,6 +694,126 @@ Print the current user.  This Eshell version of 
@command{whoami}
 supports Tramp.
 @end table
 
+@subsection Defining new built-in commands
+While Eshell can run Lisp functions directly as commands, it may be
+more convenient to provide a special built-in command for
+Eshell.  Built-in commands are just ordinary Lisp functions designed
+to be called from Eshell.  When defining an Eshell-specific version of
+an existing function, you can give that function a name starting with
+@code{eshell/} so that Eshell knows to use it.
+
+@defmac eshell-eval-using-options name macro-args options body@dots{}
+This macro processes a list of @var{macro-args} for the command
+@var{name} using a set of command line @var{options}.  If the
+arguments are parsed successfully, it will store the resulting values
+in local symbols and execute @var{body}; any remaining arguments will
+be available in the locally let-bound variable @code{args}.  The
+return value is the value of the last form in @var{body}.
+
+If an unknown option was passed in @var{macro-args} and an external
+command was specified (see below), this macro will start a process for
+that command and throw the tag @code{eshell-external} with the new
+process as its value.
+
+@var{options} should be a list beginning with one or more elements of
+the following form, with each element representing a particular
+command-line switch:
+
+@example
+(@var{short} @var{long} @var{value} @var{symbol} @var{help-string})
+@end example
+
+@table @var
+@item short
+This element, if non-nil, should be a character to be used as a short
+switch, like @code{-@var{short}}.  At least one of this element and
+@var{long} must be non-nil.
+
+@item long
+This element, if non-nil, should be a string to be used as a long
+switch, like @code{--@var{long}}.
+
+@item value
+This element is the value associated with the option.  It can be
+either:
+
+@table @asis
+@item @code{t}
+The option needs a value to be specified after the switch.
+
+@item @code{nil}
+The option is given the value @code{t}.
+
+@item anything else
+The option is given the specified value.
+@end table
+
+@item symbol
+This element is the Lisp symbol that will be bound to @var{value}.  If
+@var{symbol} is @code{nil}, specifying this switch will instead call
+@code{eshell-show-usage}, and so is appropriate for an option like
+@code{--help}.
+
+@item help-string
+This element is a documentation string for the option, which will be
+displayed when @code{eshell-show-usage} is invoked.
+@end table
+
+After the list of command-line switch elements, @var{options} can
+include additional keyword arguments to control how
+@code{eshell-eval-using-options} behaves.  Some of these take
+arguments, while others don't.  The recognized keywords are:
+
+@table @code
+@item :external @var{string}
+Specify @var{string} as an external command to run if there are
+unknown switches in @var{macro-args}.
+
+@item :usage @var{string}
+Set @var{string} as the initial part of the command's documentation
+string.  It appears before the options are listed.
+
+@item :post-usage @var{string}
+Set @var{string} to be the (optional) trailing part of the command's
+documentation string.  It appears after the list of options, but
+before the final part of the documentation about the associated
+external command, if there is one.
+
+@item :show-usage
+If present, then show the usage message if the command is called with
+no arguments.
+
+@item :preserve-args
+Normally, @code{eshell-eval-using-options} flattens the list of
+arguments in @var{macro-args} and converts each to a string.  If this
+keyword is present, avoid doing that, instead preserving the original
+arguments.  This is useful for commands which want to accept arbitrary
+Lisp objects.
+
+@item :parse-leading-options-only
+If present, do not parse dash or switch arguments after the first
+positional argument.  Instead, treat them as positional arguments
+themselves.
+@end table
+
+For example, you could handle a subset of the options for the
+@code{ls} command like this:
+
+@example
+(eshell-eval-using-options
+ "ls" macro-args
+ '((?a  nil      nil show-all       "show all files")
+   (?I  "ignore" t   ignore-pattern "ignore files matching pattern")
+   (nil "help"   nil nil            "show this help message")
+ :external "ls"
+ :usage "[OPTION]... [FILE]...
+  List information about FILEs (the current directory by default).")
+ ;; List the files in ARGS somehow...
+ )
+@end example
+
+@end defmac
+
 @subsection Built-in variables
 Eshell knows a few built-in variables:
 
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 61870311ed..b3efdfbacb 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -12223,7 +12223,6 @@ controlling variable is a predicate list, as described 
above.
 @vindex gnus-treat-highlight-citation
 @vindex gnus-treat-highlight-headers
 @vindex gnus-treat-highlight-signature
-@vindex gnus-treat-play-sounds
 @vindex gnus-treat-x-pgp-sig
 @vindex gnus-treat-unfold-headers
 @vindex gnus-treat-fold-headers
@@ -12359,8 +12358,6 @@ is controlled by @code{gnus-body-boundary-delimiter}.
 
 @xref{Article Highlighting}.
 
-@vindex gnus-treat-play-sounds
-@item gnus-treat-play-sounds
 @item gnus-treat-ansi-sequences (t)
 @vindex gnus-treat-x-pgp-sig
 @item gnus-treat-x-pgp-sig (head)
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 3c15955860..6a198e9bfb 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -2857,7 +2857,7 @@ similar user option as auto-save files, called
 original file.
 
 If you change @code{lock-file-name-transforms} in order to keep file
-locks for remote files somewhere else, you will loose Emacs' feature
+locks for remote files somewhere else, you will lose Emacs's feature
 to warn you, if a file is changed in parallel from different Emacs
 sessions, or via different remote connections.  Be careful with such
 settings.
@@ -2926,7 +2926,7 @@ you, for example, mark the remote directory
 @file{@trampfn{nextcloud,user@@host,/path/to/dir}} for encryption, the
 configuration file is saved as
 @file{tramp-%2Fnextcloud%3Auser%40host%3A%2Fpath%2Fto%2Fdir%2F.encfs6.xml}
-in @code{user-emacs-directory}.  Do not loose this file and the
+in @code{user-emacs-directory}.  Do not lose this file and the
 corresponding password; otherwise there is no way to decrypt your
 encrypted files.
 
diff --git a/etc/NEWS b/etc/NEWS
index d7281467c6..ea9ba49892 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -223,6 +223,8 @@ inserted.
 This command will tell you the name of the Emoji at point.  (This
 command also works for non-Emoji characters.)
 
+*** New input method 'emoji'.
+
 ** Help
 
 ---
@@ -271,10 +273,15 @@ height use 'window-height' in combination with 
'body-lines'.
 
 *** 'other-window-scroll-default' can define the other window to scroll.
 
-** Rcirc
+** Frames
 
 +++
-*** New command 'rcirc-when'.
+*** Deleted frames can now be undeleted.
+The 16 most recently deleted frames can be undeleted with 'C-x 5 u' when
+'undelete-frame-mode' is enabled.  Without a prefix argument, undelete
+the most recently deleted frame.  With a numerical prefix argument
+between 1 and 16, where 1 is the most recently deleted frame, undelete
+the corresponding deleted frame.
 
 ** Tab Bars and Tab Lines
 
@@ -307,6 +314,11 @@ The Emacs server will be automatically stopped when 
certain conditions
 are met.  The conditions are given by the argument, which can be
 'empty', 'delete-frame' or 'kill-terminal'.
 
+** Rcirc
+
++++
+*** New command 'rcirc-when'.
+
 * Editing Changes in Emacs 29.1
 
 ---
@@ -392,6 +404,13 @@ the *Completions* buffer.
 +++
 *** New user option 'char-fold-override' disables default character 
equivalences.
 
++++
+*** New command 'isearch-emoji-by-name'.
+It is bound to 'C-x 8 e RET' during an incremental search.  The
+command accepts the Unicode name of an Emoji (for example, "smiling
+face" or "heart with arrow"), like 'C-x 8 e e', with minibuffer
+completion, and adds the Emoji into the search string.
+
 ** New minor mode 'glyphless-display-mode'.
 This allows an easy way to toggle seeing all glyphless characters in
 the current buffer.
@@ -575,6 +594,12 @@ to enable the display of the buffer list.
 It is bound to 'C-M-,' and jumps to the location where 'xref-go-back'
 ('M-,', also known as 'xref-pop-marker-stack') was invoked previously.
 
+*** 'xref-query-replace-in-results' does not prompt for FROM when
+called without prefix argument, to make the most common case faster:
+replacing entire matches.
+
+*** New command 'xref-find-references-and-replace' to rename one identifier.
+
 ** File notifications
 
 +++
@@ -916,6 +941,11 @@ The input must be encoded text.
 
 * Lisp Changes in Emacs 29.1
 
++++
+** New function 'function-alias-p'.
+This predicate says whether an object is a function alias, and if it
+is, the alias chain is returned.
+
 +++
 ** New variable 'lisp-directory' holds the directory of Emacs's own Lisp files.
 
@@ -1090,6 +1120,12 @@ dimensions.
 Specifying a cons as the from argument allows to start measuring text
 from a specified amount of pixels above or below a position.
 
+---
+** 'eshell-eval-using-options' now follows POSIX/GNU argument syntax 
conventions.
+Built-in commands in Eshell now accept command-line options with
+values passed as a single token, such as '-oVALUE' or
+'--option=VALUE'.
+
 ** XDG support
 
 *** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment 
variable.
diff --git a/leim/Makefile.in b/leim/Makefile.in
index a574a10845..2a477d868b 100644
--- a/leim/Makefile.in
+++ b/leim/Makefile.in
@@ -35,15 +35,14 @@ EXEEXT = @EXEEXT@
 -include ${top_builddir}/src/verbose.mk
 
 # Prevent any settings in the user environment causing problems.
-unexport EMACSDATA EMACSDOC EMACSPATH
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
 
 # Which Emacs to use to convert TIT files to Emacs Lisp files,
 # and generate the file leim-list.el.
 EMACS = ../src/emacs${EXEEXT}
 
 # How to run Emacs.
-# Prevent any setting of EMACSLOADPATH in user environment causing problems.
-RUN_EMACS = EMACSLOADPATH= '$(EMACS)' -batch --no-site-file --no-site-lisp
+RUN_EMACS = '$(EMACS)' -batch --no-site-file --no-site-lisp
 
 MKDIR_P = @MKDIR_P@
 
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index c25ba5c974..0453b93506 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -20,6 +20,9 @@
 
 SHELL = @SHELL@
 
+# Prevent any settings in the user environment causing problems.
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
+
 # Following ../lisp/Makefile.in.
 EMACS = ../src/emacs${EXEEXT}
 EMACSOPT = -batch --no-site-file --no-site-lisp
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index d29dec08a5..3a72034463 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -101,11 +101,10 @@ MAIN_FIRST = ./emacs-lisp/eieio.el 
./emacs-lisp/eieio-base.el \
   ./cedet/semantic/db.el ./emacs-lisp/cconv.el
 
 # Prevent any settings in the user environment causing problems.
-unexport EMACSDATA EMACSDOC EMACSPATH
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
 
 # The actual Emacs command run in the targets below.
-# Prevent any setting of EMACSLOADPATH in user environment causing problems.
-emacs = EMACSLOADPATH= '$(EMACS)' $(EMACSOPT)
+emacs = '$(EMACS)' $(EMACSOPT)
 
 ## Subdirectories, relative to builddir.
 SUBDIRS = $(sort $(shell find ${srcdir} -type d -print))
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 046a685d74..8a425cf9bc 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -861,7 +861,7 @@ while \(:host t) would find all host entries."
       secret)))
 
 (defun auth-source-pick-first-password (&rest spec)
-  "Pick the first secret found from applying SPEC to `auth-source-search'."
+  "Pick the first secret found by applying 'auth-source-search' to SPEC."
   (auth-info-password (car (apply #'auth-source-search (plist-put spec :max 
1)))))
 
 (defun auth-source-format-prompt (prompt alist)
diff --git a/lisp/battery.el b/lisp/battery.el
index 45334163fa..b7b81a11a1 100644
--- a/lisp/battery.el
+++ b/lisp/battery.el
@@ -96,12 +96,14 @@ Value does not include \".\" or \"..\"."
   (cond ((member battery-upower-service (dbus-list-activatable-names))
          #'battery-upower)
         ((and (eq system-type 'gnu/linux)
+              (file-readable-p "/sys/")
               (battery--find-linux-sysfs-batteries))
          #'battery-linux-sysfs)
        ((and (eq system-type 'gnu/linux)
              (file-directory-p "/proc/acpi/battery"))
         #'battery-linux-proc-acpi)
        ((and (eq system-type 'gnu/linux)
+              (file-readable-p "/proc/")
               (file-readable-p "/proc/apm"))
          #'battery-linux-proc-apm)
        ((and (eq system-type 'berkeley-unix)
diff --git a/lisp/cedet/ede/project-am.el b/lisp/cedet/ede/project-am.el
index 2803e1c307..544e39b872 100644
--- a/lisp/cedet/ede/project-am.el
+++ b/lisp/cedet/ede/project-am.el
@@ -191,8 +191,9 @@ other meta-variable based on this name.")
   "Encode one makefile.")
 
 ;;; Code:
-(cl-defmethod project-add-file ((ot project-am-target))
+(cl-defmethod project-add-file ((ot project-am-target) &optional _file)
   "Add the current buffer into a project.
+_FILE is ignored.
 OT is the object target.  DIR is the directory to start in."
   (let* ((target (if ede-object (error "Already associated w/ a target")
                   (let ((amf (project-am-load default-directory)))
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 56e84ab339..7bcb2f2936 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -697,7 +697,11 @@ Valid keywords and arguments are:
 (defmacro easy-mmode-defmap (m bs doc &rest args)
   "Define a constant M whose value is the result of `easy-mmode-define-keymap'.
 The M, BS, and ARGS arguments are as per that function.  DOC is
-the constant's documentation."
+the constant's documentation.
+
+This macro is deprecated; use `defvar-keymap' instead."
+  ;; FIXME: Declare obsolete in favor of `defvar-keymap'.  It is still
+  ;; used for `gud-menu-map' and `gud-minor-mode-map', so fix that first.
   (declare (doc-string 3) (indent 1))
   `(defconst ,m
      (easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args))
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index e31ebf5f7b..9c6b0e15bb 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -335,15 +335,20 @@ It should only be stopped when ran from inside 
`ert--run-test-internal'."
                                  (unless (eql ,value ',default-value)
                                    (list :value ,value))
                                  (unless (eql ,value ',default-value)
-                                   (let ((-explainer-
-                                          (and (symbolp ',fn-name)
-                                               (get ',fn-name 
'ert-explainer))))
-                                     (when -explainer-
-                                       (list :explanation
-                                             (apply -explainer- ,args))))))
+                                   (when-let ((-explainer-
+                                               (ert--get-explainer ',fn-name)))
+                                     (list :explanation
+                                           (apply -explainer- ,args)))))
                          value)
                ,value))))))))
 
+(defun ert--get-explainer (fn-name)
+  (when (symbolp fn-name)
+    (cl-loop for fn in (cons fn-name (function-alias-p fn-name))
+             for explainer = (get fn 'ert-explainer)
+             when explainer
+             return explainer)))
+
 (defun ert--expand-should (whole form inner-expander)
   "Helper function for the `should' macro and its variants.
 
diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el
index 963e117ff3..de0112db63 100644
--- a/lisp/emacs-lisp/inline.el
+++ b/lisp/emacs-lisp/inline.el
@@ -71,7 +71,7 @@
 
 (defmacro inline-quote (_exp)
   "Similar to backquote, but quotes code and only accepts , and not ,@."
-  (declare (debug backquote-form))
+  (declare (debug (backquote-form)))
   (error "inline-quote can only be used within define-inline"))
 
 (defmacro inline-const-p (_exp)
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index faf0b1619e..27a7a8f8cf 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -382,14 +382,17 @@ Assumes the caller has bound 
`macroexpand-all-environment'."
                                  (macroexp--all-forms args)
                                  form)
               (macroexp--expand-all newform))))
-          (`(funcall . ,(or `(,exp . ,args) pcase--dontcare))
+          (`(funcall ,exp . ,args)
            (let ((eexp (macroexp--expand-all exp))
                  (eargs (macroexp--all-forms args)))
              ;; Rewrite (funcall #'foo bar) to (foo bar), in case `foo'
              ;; has a compiler-macro, or to unfold it.
              (pcase eexp
-               (`#',f (macroexp--expand-all `(,f . ,eargs)))
+               ((and `#',f
+                     (guard (not (or (special-form-p f) (macrop f))))) ;; 
bug#46636
+                (macroexp--expand-all `(,f . ,eargs)))
                (_ `(funcall ,eexp . ,eargs)))))
+          (`(funcall . ,_) form)            ;bug#53227
           (`(,func . ,_)
            (let ((handler (function-get func 'compiler-macro))
                  (funargs (function-get func 'funarg-positions)))
@@ -430,7 +433,6 @@ Assumes the caller has bound `macroexpand-all-environment'."
                            newform
                          (macroexp--expand-all newform)))
                    (macroexp--expand-all newform))))))
-
           (_ form)))
     (pop byte-compile-form-stack)))
 
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 870d34527b..658edd6752 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1299,6 +1299,9 @@ If FUNCTION is non-nil, place point on the entry for 
FUNCTION (if any)."
     (text-property-search-forward 'shortdoc-function function t)
     (beginning-of-line)))
 
+;;;###autoload
+(defalias 'shortdoc #'shortdoc-display-group)
+
 (defun shortdoc--display-function (data)
   (let ((function (pop data))
         (start-section (point))
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index d96b77ddd3..bba1c4ad25 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -187,49 +187,82 @@ passed to this command, the external version `%s'
 will be called instead." extcmd)))))
     (throw 'eshell-usage usage)))
 
-(defun eshell--set-option (name ai opt options opt-vals)
+(defun eshell--split-switch (switch kind)
+  "Split SWITCH into its option name and potential value, if any.
+KIND should be the integer 0 if SWITCH is a short option, or 1 if it's
+a long option."
+  (if (eq kind 0)
+      ;; Short option
+      (cons (aref switch 0)
+            (and (> (length switch) 1) (substring switch 1)))
+    ;; Long option
+    (save-match-data
+      (string-match "\\([^=]*\\)\\(?:=\\(.*\\)\\)?" switch)
+      (cons (match-string 1 switch) (match-string 2 switch)))))
+
+(defun eshell--set-option (name ai opt value options opt-vals)
   "Using NAME's remaining args (index AI), set the OPT within OPTIONS.
-If the option consumes an argument for its value, the argument list
-will be modified."
+VALUE is the potential value of the OPT, coming from args like
+\"-fVALUE\" or \"--foo=VALUE\", or nil if no value was supplied.  If
+OPT doesn't consume a value, return VALUE unchanged so that it can be
+processed later; otherwsie, return nil.
+
+If the OPT consumes an argument for its value and VALUE is nil, the
+argument list will be modified."
   (if (not (nth 3 opt))
       (eshell-show-usage name options)
-    (setcdr (assq (nth 3 opt) opt-vals)
-            (if (eq (nth 2 opt) t)
-                (if (> ai (length eshell--args))
-                    (error "%s: missing option argument" name)
-                  (pop (nthcdr ai eshell--args)))
-              (or (nth 2 opt) t)))))
+    (if (eq (nth 2 opt) t)
+        (progn
+          (setcdr (assq (nth 3 opt) opt-vals)
+                  (or value
+                      (if (> ai (length eshell--args))
+                          (error "%s: missing option argument" name)
+                        (pop (nthcdr ai eshell--args)))))
+          nil)
+      (setcdr (assq (nth 3 opt) opt-vals)
+              (or (nth 2 opt) t))
+      value)))
 
 (defun eshell--process-option (name switch kind ai options opt-vals)
   "For NAME, process SWITCH (of type KIND), from args at index AI.
 The SWITCH will be looked up in the set of OPTIONS.
 
-SWITCH should be either a string or character.  KIND should be the
-integer 0 if it's a character, or 1 if it's a string.
-
-The SWITCH is then be matched against OPTIONS.  If no matching handler
-is found, and an :external command is defined (and available), it will
-be called; otherwise, an error will be triggered to say that the
-switch is unrecognized."
-  (let* ((opts options)
-        found)
+SWITCH should be a string starting with the option to process,
+possibly followed by its value, e.g. \"u\" or \"uUSER\".  KIND should
+be the integer 0 if it's a short option, or 1 if it's a long option.
+
+The SWITCH is then be matched against OPTIONS.  If KIND is 0 and the
+SWITCH matches an option that doesn't take a value, return the
+remaining characters in SWITCH to be processed later as further short
+options.
+
+If no matching handler is found, and an :external command is defined
+(and available), it will be called; otherwise, an error will be
+triggered to say that the switch is unrecognized."
+  (let ((switch (eshell--split-switch switch kind))
+        (opts options)
+       found remaining)
     (while opts
       (if (and (listp (car opts))
-               (nth kind (car opts))
-               (equal switch (nth kind (car opts))))
+               (equal (car switch) (nth kind (car opts))))
          (progn
-           (eshell--set-option name ai (car opts) options opt-vals)
+           (setq remaining (eshell--set-option name ai (car opts)
+                                                (cdr switch) options opt-vals))
+            (when (and remaining (eq kind 1))
+              (error "%s: option --%s doesn't allow an argument"
+                     name (car switch)))
            (setq found t opts nil))
        (setq opts (cdr opts))))
-    (unless found
+    (if found
+        remaining
       (let ((extcmd (memq ':external options)))
        (when extcmd
          (setq extcmd (eshell-search-path (cadr extcmd)))
          (if extcmd
              (throw 'eshell-ext-command extcmd)
-            (error (if (characterp switch) "%s: unrecognized option -%c"
+            (error (if (characterp (car switch)) "%s: unrecognized option -%c"
                      "%s: unrecognized option --%s")
-                   name switch)))))))
+                   name (car switch))))))))
 
 (defun eshell--process-args (name args options)
   "Process the given ARGS using OPTIONS."
@@ -262,12 +295,9 @@ switch is unrecognized."
              (if (> (length switch) 0)
                  (eshell--process-option name switch 1 ai options opt-vals)
                (setq ai (length eshell--args)))
-           (let ((len (length switch))
-                 (index 0))
-             (while (< index len)
-               (eshell--process-option name (aref switch index)
-                                        0 ai options opt-vals)
-               (setq index (1+ index))))))))
+             (while (> (length switch) 0)
+               (setq switch (eshell--process-option name switch 0
+                                                     ai options opt-vals)))))))
     (nconc (mapcar #'cdr opt-vals) eshell--args)))
 
 (provide 'esh-opt)
diff --git a/lisp/ffap.el b/lisp/ffap.el
index f9220817a7..b5d2a02cd1 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1449,10 +1449,13 @@ which may actually result in an URL rather than a 
filename."
               (ffap-file-exists-string (substring name 0 (match-beginning 
0)))))
         ;; If it contains a colon, get rid of it (and return if exists)
         ((and (string-match path-separator name)
-              (setq name (ffap-string-at-point 'nocolon))
-              (> (length name) 0)
-              (ffap-file-exists-string name)))
-        ;; File does not exist, try the alist:
+              (let ((this-name (ffap-string-at-point 'nocolon)))
+                 ;; But don't interpret the first part if ":/bin" as
+                 ;; the empty string.
+                (when (> (length this-name) 0)
+                   (setq name this-name)
+                  (ffap-file-exists-string name)))))
+         ;; File does not exist, try the alist:
         ((let ((alist ffap-alist) tem try case-fold-search)
            (while (and alist (not try))
              (setq tem (car alist) alist (cdr alist))
diff --git a/lisp/files.el b/lisp/files.el
index 48e0252e06..1d9d450e4d 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -483,12 +483,16 @@ If `silently', don't ask the user before saving."
 
 (defcustom lock-file-name-transforms nil
   "Transforms to apply to buffer file name before making a lock file name.
-This has the same syntax as
-`auto-save-file-name-transforms' (which see), but instead of
-applying to auto-save file names, it's applied to lock file names.
+This has the same syntax as `auto-save-file-name-transforms',
+but applies to lock file names instead of auto-save file names.
 
-By default, a lock file is put into the same directory as the
-file it's locking, and it has the same name, but with \".#\" prepended."
+By default, Emacs puts each lock file into the same directory as the
+file it locks, prepending \".#\" to the base file name.
+
+Note that changing this could break lock file functionality, e.g.:
+if different users access the same file, using different lock file settings;
+if accessing files on a shared file system from different hosts,
+using a transform that puts the lock files on a local file system."
   :group 'files
   :type '(repeat (list (regexp :tag "Regexp")
                        (string :tag "Replacement")
diff --git a/lisp/frame.el b/lisp/frame.el
index 62b73f3157..599ffe591a 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -2529,6 +2529,80 @@ deleting them."
         (if iconify (iconify-frame this) (delete-frame this)))
       (setq this next))))
 
+(eval-when-compile (require 'frameset))
+
+(defvar undelete-frame--deleted-frames nil
+  "Internal variable used by `undelete-frame--handle-delete-frame'.")
+
+(defun undelete-frame--handle-delete-frame (frame)
+  "Save the configuration of frames deleted with `delete-frame'.
+Only the 16 most recently deleted frames are saved."
+  (when (frame-live-p frame)
+    (setq undelete-frame--deleted-frames
+          (cons
+           (cons
+            (display-graphic-p)
+            (frameset-save
+             (list frame)
+             ;; When the daemon is started from a graphical
+             ;; environment, TTY frames have a 'display' parameter set
+             ;; to the value of $DISPLAY (see the note in
+             ;; `server--on-display-p').  Do not store that parameter
+             ;; in the frameset, otherwise `frameset-restore' attempts
+             ;; to restore a graphical frame.
+             :filters (if (display-graphic-p)
+                          frameset-filter-alist
+                        (cons '(display . :never)
+                              frameset-filter-alist))))
+           undelete-frame--deleted-frames))
+    (if (> (length undelete-frame--deleted-frames) 16)
+        (setq undelete-frame--deleted-frames
+              (butlast undelete-frame--deleted-frames)))))
+
+(define-minor-mode undelete-frame-mode
+  "Enable the `undelete-frame' command."
+  :group 'frames
+  :global t
+  (if undelete-frame-mode
+      (add-hook 'delete-frame-functions
+                #'undelete-frame--handle-delete-frame -75)
+    (remove-hook 'delete-frame-functions
+                 #'undelete-frame--handle-delete-frame)
+    (setq undelete-frame--deleted-frames nil)))
+
+(defun undelete-frame (&optional arg)
+  "Undelete a frame deleted with `delete-frame'.
+Without a prefix argument, undelete the most recently deleted
+frame.
+With a numerical prefix argument ARG between 1 and 16, where 1 is
+most recently deleted frame, undelete the ARGth deleted frame.
+When called from Lisp, returns the new frame."
+  (interactive "P")
+  (if (not undelete-frame-mode)
+      (user-error "Undelete-Frame mode is disabled")
+    (if (consp arg)
+        (user-error "Missing deleted frame number argument")
+      (let* ((number (pcase arg ('nil 1) ('- -1) (_ arg)))
+             (frames (frame-list))
+             (frameset (nth (1- number) undelete-frame--deleted-frames))
+             (graphic (display-graphic-p)))
+        (if (not (<= 1 number 16))
+            (user-error "%d is not a valid deleted frame number argument"
+                        number)
+          (if (not frameset)
+              (user-error "No deleted frame with number %d" number)
+            (if (not (eq graphic (car frameset)))
+                (user-error
+                 "Cannot undelete a %s display frame on a %s display"
+                 (if graphic "non-graphic" "graphic")
+                 (if graphic "graphic" "non-graphic"))
+              (setq undelete-frame--deleted-frames
+                    (delq frameset undelete-frame--deleted-frames))
+              (frameset-restore (cdr frameset))
+              (let ((frame (car (seq-difference (frame-list) frames))))
+                (when frame
+                  (select-frame-set-input-focus frame)
+                  frame)))))))))
 
 ;;; Window dividers.
 (defgroup window-divider nil
@@ -2873,6 +2947,7 @@ See also `toggle-frame-maximized'."
 (define-key ctl-x-5-map "o" #'other-frame)
 (define-key ctl-x-5-map "5" #'other-frame-prefix)
 (define-key ctl-x-5-map "c" #'clone-frame)
+(define-key ctl-x-5-map "u" #'undelete-frame)
 (define-key global-map [f11] #'toggle-frame-fullscreen)
 (define-key global-map [(meta f10)] #'toggle-frame-maximized)
 (define-key esc-map    [f10]        #'toggle-frame-maximized)
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index f26ab6ab4c..a286c44672 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -1159,13 +1159,15 @@ predicate.  See Info node `(gnus)Customizing Articles'."
   :link '(custom-manual "(gnus)Customizing Articles")
   :type gnus-article-treat-head-custom)
 
-(defcustom gnus-treat-emphasize 50000
+(defcustom gnus-treat-emphasize '(and 50000
+                                      (not (typep "text/html")))
   "Emphasize text.
 Valid values are nil, t, `head', `first', `last', an integer or a
 predicate.  See Info node `(gnus)Customizing Articles'."
   :group 'gnus-article-treat
   :link '(custom-manual "(gnus)Customizing Articles")
-  :type gnus-article-treat-custom)
+  :type gnus-article-treat-custom
+  :version "29.1")
 (put 'gnus-treat-emphasize 'highlight t)
 
 (defcustom gnus-treat-strip-cr nil
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index 0c281a997f..edeacbc919 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -355,8 +355,13 @@ This is not required after changing 
`gnus-registry-cache-file'."
   "Load the registry from the cache file."
   (interactive)
   (let ((file gnus-registry-cache-file))
+    (gnus-message 5 "Initializing the registry")
     (condition-case nil
-        (gnus-registry-read file)
+        (progn
+          (gnus-registry-read file)
+          (gnus-registry-install-hooks)
+          (gnus-registry-install-shortcuts)
+          (setq gnus-registry-enabled t))
       (file-error
        ;; Fix previous mis-naming of the registry file.
        (let ((old-file-name
@@ -846,9 +851,9 @@ Overrides existing keywords with FORCE set non-nil."
 
 (defun gnus-registry-register-message-ids ()
   "Register the Message-ID of every article in the group."
-  (unless (or (gnus-parameter-registry-ignore gnus-newsgroup-name)
-             (null gnus-registry-register-all)
-              (null (eieio-object-p gnus-registry-db)))
+  (unless (or (null gnus-registry-enabled)
+              (null gnus-registry-register-all)
+             (gnus-parameter-registry-ignore gnus-newsgroup-name))
     (dolist (article gnus-newsgroup-articles)
       (let* ((id (gnus-registry-fetch-message-id-fast article))
              (groups (gnus-registry-get-id-key id 'group)))
@@ -1175,7 +1180,8 @@ non-nil."
 (defun gnus-registry-clear ()
   "Clear the registry."
   (gnus-registry-unload-hook)
-  (setq gnus-registry-db nil))
+  (setq gnus-registry-db nil
+        gnus-registry-enabled nil))
 
 (gnus-add-shutdown 'gnus-registry-clear 'gnus)
 
@@ -1183,16 +1189,12 @@ non-nil."
 (defun gnus-registry-initialize ()
   "Initialize the Gnus registry."
   (interactive)
-  (gnus-message 5 "Initializing the registry")
-  (gnus-registry-install-hooks)
-  (gnus-registry-install-shortcuts)
   (if (gnus-alive-p)
       (gnus-registry-load)
     (add-hook 'gnus-read-newsrc-el-hook #'gnus-registry-load)))
 
 (defun gnus-registry-install-hooks ()
   "Install the registry hooks."
-  (setq gnus-registry-enabled t)
   (add-hook 'gnus-summary-article-move-hook #'gnus-registry-action)
   (add-hook 'gnus-summary-article-delete-hook #'gnus-registry-action)
   (add-hook 'gnus-summary-article-expire-hook #'gnus-registry-action)
@@ -1212,10 +1214,9 @@ non-nil."
   (remove-hook 'gnus-save-newsrc-hook #'gnus-registry-save)
   (remove-hook 'gnus-read-newsrc-el-hook #'gnus-registry-load)
 
-  (remove-hook 'gnus-summary-prepare-hook #'gnus-registry-register-message-ids)
-  (setq gnus-registry-enabled nil))
+  (remove-hook 'gnus-summary-prepare-hook 
#'gnus-registry-register-message-ids))
 
-(add-hook 'gnus-registry-unload-hook #'gnus-registry-unload-hook)
+(add-hook 'gnus-registry-unload-hook #'gnus-registry-clear)
 
 (defun gnus-registry-install-p ()
   "Return non-nil if the registry is enabled (and maybe enable it first).
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index 090cb9b245..cff628061e 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -246,7 +246,7 @@ during splitting, which may be slow."
          (nnimap-header-parameters))
         t)
        (unless (process-live-p (get-buffer-process (current-buffer)))
-         (error "Server closed connection"))
+         (error "IMAP server %S closed connection" nnimap-address))
        (nnimap-transform-headers)
        (nnheader-remove-cr-followed-by-lf))
       (insert-buffer-substring
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index 624c64d4d7..0dcff9743a 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -306,7 +306,7 @@ backend doesn't catch this error.")
     (nntp-record-command string))
   (process-send-string process (concat string nntp-end-of-line))
   (or (memq (process-status process) '(open run))
-      (nntp-report "Server closed connection")))
+      (nntp-report "NNTP server %S closed connection" nntp-address)))
 
 (defun nntp-record-command (string)
   "Record the command STRING."
@@ -369,7 +369,7 @@ retried once before actually displaying the error report."
            (nntp-snarf-error-message)
            nil))
         ((not (memq (process-status process) '(open run)))
-         (nntp-report "Server closed connection"))
+         (nntp-report "NNTP server %S closed connection" nntp-address))
         (t
          (goto-char (point-max))
          (let ((limit (point-min))
@@ -1431,7 +1431,7 @@ If SEND-IF-FORCE, only send authinfo to the server if the
       ;; be the process's former output buffer (i.e. now killed)
       (or (and process
               (memq (process-status process) '(open run)))
-          (nntp-report "Server closed connection")))))
+          (nntp-report "NNTP server %S closed connection" nntp-address)))))
 
 (defun nntp-accept-response ()
   "Wait for output from the process that outputs to BUFFER."
@@ -1450,7 +1450,7 @@ If SEND-IF-FORCE, only send authinfo to the server if the
   (when group
     (let ((entry (nntp-find-connection-entry nntp-server-buffer)))
       (cond ((not entry)
-             (nntp-report "Server closed connection"))
+             (nntp-report "NNTP server %S closed connection" nntp-address))
             ((not (equal group (caddr entry)))
              (with-current-buffer (process-buffer (car entry))
                (erase-buffer)
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index d408efeeb9..e000a68a82 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -829,11 +829,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED 
REAL-DEF)."
                                               (symbol-name function)))))))
         (real-def (cond
                     ((and aliased (not (subrp def)))
-                     (let ((f real-function))
-                       (while (and (fboundp f)
-                                   (symbolp (symbol-function f)))
-                         (setq f (symbol-function f)))
-                       f))
+                     (car (function-alias-p real-function t)))
                    ((subrp def) (intern (subr-name def)))
                     (t def))))
 
diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el
index fbd698e234..b70d4a7569 100644
--- a/lisp/hi-lock.el
+++ b/lisp/hi-lock.el
@@ -854,6 +854,26 @@ SPACES-REGEXP is a regexp to substitute spaces in 
font-lock search."
   ;; continue standard unloading
   nil)
 
+;;; Mouse support
+(defun hi-lock-symbol-at-mouse (event)
+  "Highlight symbol at mouse click EVENT."
+  (interactive "e")
+  (save-excursion
+    (mouse-set-point event)
+    (highlight-symbol-at-point)))
+
+;;;###autoload
+(defun hi-lock-context-menu (menu click)
+  "Populate MENU with a menu item to highlight symbol at CLICK."
+  (save-excursion
+    (mouse-set-point click)
+    (when (symbol-at-point)
+      (define-key-after menu [highlight-search-separator] menu-bar-separator)
+      (define-key-after menu [highlight-search-mouse]
+        '(menu-item "Highlight Symbol" highlight-symbol-at-mouse
+                    :help "Highlight symbol at point"))))
+  menu)
+
 (provide 'hi-lock)
 
 ;;; hi-lock.el ends here
diff --git a/lisp/image-dired.el b/lisp/image-dired.el
index 536f29441a..b81df8567b 100644
--- a/lisp/image-dired.el
+++ b/lisp/image-dired.el
@@ -609,9 +609,7 @@ See also `image-dired-thumbnail-storage'."
         ((eq 'use-image-dired-dir image-dired-thumbnail-storage)
          (let* ((f (expand-file-name file))
                 (hash
-                 ;; SHA1 is slightly faster than MD5, so let's use it.
-                 ;; (We don't need anything crytographically strong.)
-                 (sha1 (file-name-as-directory (file-name-directory f)))))
+                 (md5 (file-name-as-directory (file-name-directory f)))))
            (format "%s%s%s.thumb.%s"
                    (file-name-as-directory (expand-file-name 
(image-dired-dir)))
                    (file-name-base f)
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 7593a0ec98..833d031c56 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -668,6 +668,7 @@ 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 "\C-x8e\r" 'isearch-emoji-by-name)
     map)
   "Keymap for `isearch-mode'.")
 
@@ -758,6 +759,8 @@ This is like `describe-bindings', but displays only Isearch 
keys."
      :help "Search for literal char"]
     ["Search for char by name" isearch-char-by-name
      :help "Search for character by name"]
+    ["Search for Emoji by name" isearch-emoji-by-name
+     :help "Search for Emoji by its Unicode name"]
     "---"
     ["Toggle input method" isearch-toggle-input-method
      :help "Toggle input method for search"]
@@ -2747,6 +2750,24 @@ With argument, add COUNT copies of the character."
                                           (mapconcat 
'isearch-text-char-description
                                                      string ""))))))))
 
+(defun isearch-emoji-by-name (&optional count)
+  "Read an Emoji name and add it to the search string COUNT times.
+COUNT (interactively, the prefix argument) defaults to 1.
+The command accepts Unicode names like \"smiling face\" or
+\"heart with arrow\", and completion is available."
+  (interactive "p")
+  (with-isearch-suspended
+   (let ((emoji (with-temp-buffer
+                  (emoji-search)
+                  (if (and (integerp count) (> count 1))
+                      (apply 'concat (make-list count (buffer-string)))
+                    (buffer-string)))))
+     (when emoji
+       (setq isearch-new-string (concat isearch-string emoji)
+             isearch-new-message (concat isearch-message
+                                          (mapconcat 
'isearch-text-char-description
+                                                     emoji "")))))))
+
 (defun isearch-search-and-update ()
   "Do the search and update the display."
   (when (or isearch-success
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index 84d0ef9179..b84e9b74b1 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -4,7 +4,7 @@
 
 ;; Author: João Távora <joaotavora@gmail.com>
 ;; Keywords: processes, languages, extensions
-;; Version: 1.0.14
+;; Version: 1.0.15
 ;; Package-Requires: ((emacs "25.2"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
@@ -698,7 +698,9 @@ TIMEOUT is nil)."
 (defun jsonrpc--debug (server format &rest args)
   "Debug message for SERVER with FORMAT and ARGS."
   (jsonrpc--log-event
-   server (if (stringp format)`(:message ,(format format args)) format)))
+   server (if (stringp format)
+              `(:message ,(apply #'format format args))
+            format)))
 
 (defun jsonrpc--warn (format &rest args)
   "Warning message with FORMAT and ARGS."
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index 6d5b0d84e6..05d461e41e 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -8861,8 +8861,12 @@ Define a constant M whose value is the result of 
`easy-mmode-define-keymap'.
 The M, BS, and ARGS arguments are as per that function.  DOC is
 the constant's documentation.
 
+This macro is deprecated; use `defvar-keymap' instead.
+
 \(fn M BS DOC &rest ARGS)" nil t)
 
+(function-put 'easy-mmode-defmap 'doc-string-elt '3)
+
 (function-put 'easy-mmode-defmap 'lisp-indent-function '1)
 
 (autoload 'easy-mmode-defsyntax "easy-mmode" "\
@@ -8871,6 +8875,8 @@ CSS contains a list of syntax specifications of the form 
(CHAR . SYNTAX).
 
 \(fn ST CSS DOC &rest ARGS)" nil t)
 
+(function-put 'easy-mmode-defsyntax 'doc-string-elt '3)
+
 (function-put 'easy-mmode-defsyntax 'lisp-indent-function '1)
 
 (register-definition-prefixes "easy-mmode" '("easy-mmode-"))
@@ -10291,6 +10297,31 @@ disabled.
 ;;;### (autoloads nil "elide-head" "elide-head.el" (0 0 0 0))
 ;;; Generated autoloads from elide-head.el
 
+(autoload 'elide-head-mode "elide-head" "\
+Toggle eliding (hiding) header material in the current buffer.
+
+This is a minor mode.  If called interactively, toggle the `Elide-Head
+mode' mode.  If the prefix argument is positive, enable the mode, and
+if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable the
+mode if ARG is nil, omitted, or is a positive number.  Disable the
+mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `elide-head-mode'.
+
+The mode's hook is called both when the mode is enabled and when it is
+disabled.
+
+When Elide Header mode is enabled, headers are hidden according
+to `elide-head-headers-to-hide'.
+
+This is suitable as an entry on `find-file-hook' or appropriate
+mode hooks.
+
+\(fn &optional ARG)" t nil)
+
 (autoload 'elide-head "elide-head" "\
 Hide header material in buffer according to `elide-head-headers-to-hide'.
 
@@ -10301,6 +10332,8 @@ This is suitable as an entry on `find-file-hook' or 
appropriate mode hooks.
 
 \(fn &optional ARG)" t nil)
 
+(make-obsolete 'elide-head 'elide-head-mode '"29.1")
+
 (register-definition-prefixes "elide-head" '("elide-head-"))
 
 ;;;***
@@ -16764,6 +16797,11 @@ be found in variable `hi-lock-interactive-patterns'." 
t nil)
 (autoload 'hi-lock-find-patterns "hi-lock" "\
 Add patterns from the current buffer to the list of hi-lock patterns." t nil)
 
+(autoload 'hi-lock-context-menu "hi-lock" "\
+Populate MENU with a menu item to highlight symbol at CLICK.
+
+\(fn MENU CLICK)" nil nil)
+
 (register-definition-prefixes "hi-lock" '("hi-lock-" 
"turn-on-hi-lock-if-enabled"))
 
 ;;;***
@@ -19155,25 +19193,37 @@ system." t nil)
  (put 'info-lookup-symbol 'info-file "emacs")
 
 (autoload 'info-lookup-symbol "info-look" "\
-Display the definition of SYMBOL, as found in the relevant manual.
-When this command is called interactively, it reads SYMBOL from the
-minibuffer.  In the minibuffer, use 
\\<minibuffer-local-completion-map>\\[next-history-element] to yank the default 
argument
-value into the minibuffer so you can edit it.  The default symbol is the
-one found at point.
+Look up and display documentation of SYMBOL in the relevant Info manual.
+SYMBOL should be an identifier: a function or method, a macro, a variable,
+a data type, a class, etc.
 
-With prefix arg MODE a query for the symbol help mode is offered.
+Interactively, prompt for SYMBOL; you can use 
\\<minibuffer-local-completion-map>\\[next-history-element] in the minibuffer
+to yank the default argument value into the minibuffer so you can edit it.
+The default symbol is the one found at point.
+
+MODE is the major mode whose Info manuals to search for the documentation
+of SYMBOL.  It defaults to the current buffer's `major-mode'; if that
+mode doesn't have any Info manuals known to Emacs, the command will
+prompt for MODE to use, with completion.  With prefix arg, the command
+always prompts for MODE.
 
 \(fn SYMBOL &optional MODE)" t nil)
  (put 'info-lookup-file 'info-file "emacs")
 
 (autoload 'info-lookup-file "info-look" "\
-Display the documentation of a file.
-When this command is called interactively, it reads FILE from the minibuffer.
-In the minibuffer, use 
\\<minibuffer-local-completion-map>\\[next-history-element] to yank the default 
file name
-into the minibuffer so you can edit it.
+Look up and display documentation of FILE in the relevant Info manual.
+FILE should be the name of a file; a notable example is a standard header
+file that is part of the C or C++ standard library.
+
+Interactively, prompt for FILE; you can use 
\\<minibuffer-local-completion-map>\\[next-history-element] in the minibuffer
+to yank the default argument value into the minibuffer so you can edit it.
 The default file name is the one found at point.
 
-With prefix arg MODE a query for the file help mode is offered.
+MODE is the major mode whose Info manuals to search for the documentation
+of FILE.  It defaults to the current buffer's `major-mode'; if that
+mode doesn't have any Info manuals known to Emacs, the command will
+prompt for MODE to use, with completion.  With prefix arg, the command
+always prompts for MODE.
 
 \(fn FILE &optional MODE)" t nil)
 
@@ -19859,7 +19909,7 @@ one of the aforementioned options instead of using this 
mode.
 
 ;;;### (autoloads nil "jsonrpc" "jsonrpc.el" (0 0 0 0))
 ;;; Generated autoloads from jsonrpc.el
-(push (purecopy '(jsonrpc 1 0 14)) package--builtin-versions)
+(push (purecopy '(jsonrpc 1 0 15)) package--builtin-versions)
 
 (register-definition-prefixes "jsonrpc" '("jsonrpc-"))
 
@@ -21311,6 +21361,11 @@ Default bookmark handler for Man buffers.
 
 \(fn BOOKMARK)" nil nil)
 
+(autoload 'Man-context-menu "man" "\
+Populate MENU with commands that open a man page at point.
+
+\(fn MENU CLICK)" nil nil)
+
 (register-definition-prefixes "man" '("Man-" "man"))
 
 ;;;***
@@ -31067,6 +31122,8 @@ If FUNCTION is non-nil, place point on the entry for 
FUNCTION (if any).
 
 \(fn GROUP &optional FUNCTION)" t nil)
 
+(defalias 'shortdoc #'shortdoc-display-group)
+
 (register-definition-prefixes "shortdoc" '("alist" "buffer" 
"define-short-documentation-group" "file" "hash-table" "keymaps" "list" 
"number" "overlay" "process" "regexp" "sequence" "shortdoc-" "string" 
"text-properties" "vector"))
 
 ;;;***
@@ -39394,6 +39451,32 @@ unless `windmove-create-window' is non-nil and a new 
window is created.
 
 \(fn &optional ARG)" t nil)
 
+(defvar windmove-mode t "\
+Non-nil if Windmove mode is enabled.
+See the `windmove-mode' command
+for a description of this minor mode.")
+
+(custom-autoload 'windmove-mode "windmove" nil)
+
+(autoload 'windmove-mode "windmove" "\
+Global minor mode for default windmove commands.
+
+This is a minor mode.  If called interactively, toggle the `Windmove
+mode' mode.  If the prefix argument is positive, enable the mode, and
+if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable the
+mode if ARG is nil, omitted, or is a positive number.  Disable the
+mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='windmove-mode)'.
+
+The mode's hook is called both when the mode is enabled and when it is
+disabled.
+
+\(fn &optional ARG)" t nil)
+
 (autoload 'windmove-default-keybindings "windmove" "\
 Set up keybindings for `windmove'.
 Keybindings are of the form MODIFIERS-{left,right,up,down},
@@ -39969,24 +40052,23 @@ Zone out, completely." t nil)
 
 ;;;### (autoloads nil nil ("abbrev.el" "bindings.el" "buff-menu.el"
 ;;;;;;  "button.el" "calc/calc-aent.el" "calc/calc-embed.el" 
"calc/calc-misc.el"
-;;;;;;  "calc/calc-yank.el" "case-table.el" "cedet/ede/base.el" 
"cedet/ede/config.el"
-;;;;;;  "cedet/ede/cpp-root.el" "cedet/ede/custom.el" "cedet/ede/dired.el"
-;;;;;;  "cedet/ede/emacs.el" "cedet/ede/files.el" "cedet/ede/generic.el"
-;;;;;;  "cedet/ede/linux.el" "cedet/ede/locate.el" "cedet/ede/make.el"
-;;;;;;  "cedet/ede/shell.el" "cedet/ede/speedbar.el" "cedet/ede/system.el"
-;;;;;;  "cedet/ede/util.el" "cedet/semantic/analyze.el" 
"cedet/semantic/analyze/complete.el"
-;;;;;;  "cedet/semantic/analyze/refs.el" "cedet/semantic/bovine.el"
-;;;;;;  "cedet/semantic/bovine/c-by.el" "cedet/semantic/bovine/c.el"
-;;;;;;  "cedet/semantic/bovine/el.el" "cedet/semantic/bovine/gcc.el"
-;;;;;;  "cedet/semantic/bovine/make-by.el" "cedet/semantic/bovine/make.el"
-;;;;;;  "cedet/semantic/bovine/scm-by.el" "cedet/semantic/bovine/scm.el"
-;;;;;;  "cedet/semantic/complete.el" "cedet/semantic/ctxt.el" 
"cedet/semantic/db-file.el"
-;;;;;;  "cedet/semantic/db-find.el" "cedet/semantic/db-global.el"
-;;;;;;  "cedet/semantic/db-mode.el" "cedet/semantic/db-typecache.el"
-;;;;;;  "cedet/semantic/db.el" "cedet/semantic/debug.el" 
"cedet/semantic/decorate/include.el"
-;;;;;;  "cedet/semantic/decorate/mode.el" "cedet/semantic/dep.el"
-;;;;;;  "cedet/semantic/doc.el" "cedet/semantic/edit.el" 
"cedet/semantic/find.el"
-;;;;;;  "cedet/semantic/format.el" "cedet/semantic/grammar-wy.el"
+;;;;;;  "calc/calc-yank.el" "case-table.el" "cedet/ede/cpp-root.el"
+;;;;;;  "cedet/ede/custom.el" "cedet/ede/dired.el" "cedet/ede/emacs.el"
+;;;;;;  "cedet/ede/files.el" "cedet/ede/generic.el" "cedet/ede/linux.el"
+;;;;;;  "cedet/ede/locate.el" "cedet/ede/make.el" "cedet/ede/speedbar.el"
+;;;;;;  "cedet/ede/system.el" "cedet/ede/util.el" "cedet/semantic/analyze.el"
+;;;;;;  "cedet/semantic/analyze/complete.el" "cedet/semantic/analyze/refs.el"
+;;;;;;  "cedet/semantic/bovine.el" "cedet/semantic/bovine/c-by.el"
+;;;;;;  "cedet/semantic/bovine/c.el" "cedet/semantic/bovine/el.el"
+;;;;;;  "cedet/semantic/bovine/gcc.el" "cedet/semantic/bovine/make-by.el"
+;;;;;;  "cedet/semantic/bovine/make.el" "cedet/semantic/bovine/scm-by.el"
+;;;;;;  "cedet/semantic/bovine/scm.el" "cedet/semantic/complete.el"
+;;;;;;  "cedet/semantic/ctxt.el" "cedet/semantic/db-file.el" 
"cedet/semantic/db-find.el"
+;;;;;;  "cedet/semantic/db-global.el" "cedet/semantic/db-mode.el"
+;;;;;;  "cedet/semantic/db-typecache.el" "cedet/semantic/db.el" 
"cedet/semantic/debug.el"
+;;;;;;  "cedet/semantic/decorate/include.el" "cedet/semantic/decorate/mode.el"
+;;;;;;  "cedet/semantic/dep.el" "cedet/semantic/doc.el" 
"cedet/semantic/edit.el"
+;;;;;;  "cedet/semantic/find.el" "cedet/semantic/format.el" 
"cedet/semantic/grammar-wy.el"
 ;;;;;;  "cedet/semantic/grm-wy-boot.el" "cedet/semantic/html.el"
 ;;;;;;  "cedet/semantic/ia-sb.el" "cedet/semantic/ia.el" 
"cedet/semantic/idle.el"
 ;;;;;;  "cedet/semantic/imenu.el" "cedet/semantic/lex-spp.el" 
"cedet/semantic/lex.el"
@@ -40005,8 +40087,8 @@ Zone out, completely." t nil)
 ;;;;;;  "cedet/srecode/insert.el" "cedet/srecode/java.el" 
"cedet/srecode/map.el"
 ;;;;;;  "cedet/srecode/mode.el" "cedet/srecode/srt-wy.el" 
"cedet/srecode/srt.el"
 ;;;;;;  "cedet/srecode/template.el" "cedet/srecode/texi.el" "composite.el"
-;;;;;;  "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"
+;;;;;;  "cus-face.el" "cus-load.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/easymenu.el" 
"emacs-lisp/eieio-custom.el"
 ;;;;;;  "emacs-lisp/eieio-opt.el" "emacs-lisp/float-sup.el" 
"emacs-lisp/lisp-mode.el"
@@ -40028,30 +40110,41 @@ Zone out, completely." t nil)
 ;;;;;;  "eshell/em-pred.el" "eshell/em-prompt.el" "eshell/em-rebind.el"
 ;;;;;;  "eshell/em-script.el" "eshell/em-smart.el" "eshell/em-term.el"
 ;;;;;;  "eshell/em-tramp.el" "eshell/em-unix.el" "eshell/em-xtra.el"
-;;;;;;  "faces.el" "files.el" "font-core.el" "font-lock.el" "format.el"
-;;;;;;  "frame.el" "help.el" "hfy-cmap.el" "ibuf-ext.el" "indent.el"
-;;;;;;  "international/characters.el" "international/charscript.el"
-;;;;;;  "international/cp51932.el" "international/emoji-zwj.el" 
"international/eucjp-ms.el"
+;;;;;;  "eshell/esh-groups.el" "faces.el" "files.el" "finder-inf.el"
+;;;;;;  "font-core.el" "font-lock.el" "format.el" "frame.el" "help.el"
+;;;;;;  "hfy-cmap.el" "ibuf-ext.el" "indent.el" "international/characters.el"
+;;;;;;  "international/charprop.el" "international/charscript.el"
+;;;;;;  "international/cp51932.el" "international/emoji-labels.el"
+;;;;;;  "international/emoji-zwj.el" "international/eucjp-ms.el"
 ;;;;;;  "international/iso-transl.el" "international/mule-cmds.el"
-;;;;;;  "international/mule-conf.el" "international/mule.el" "isearch.el"
-;;;;;;  "jit-lock.el" "jka-cmpr-hook.el" "keymap.el" "language/burmese.el"
-;;;;;;  "language/cham.el" "language/chinese.el" "language/cyrillic.el"
-;;;;;;  "language/czech.el" "language/english.el" "language/ethiopic.el"
-;;;;;;  "language/european.el" "language/georgian.el" "language/greek.el"
-;;;;;;  "language/hebrew.el" "language/indian.el" "language/japanese.el"
-;;;;;;  "language/khmer.el" "language/korean.el" "language/lao.el"
-;;;;;;  "language/misc-lang.el" "language/romanian.el" "language/sinhala.el"
-;;;;;;  "language/slovak.el" "language/tai-viet.el" "language/thai.el"
-;;;;;;  "language/tibetan.el" "language/utf-8-lang.el" "language/vietnamese.el"
-;;;;;;  "ldefs-boot.el" "leim/ja-dic/ja-dic.el" "leim/leim-list.el"
-;;;;;;  "leim/quail/4Corner.el" "leim/quail/ARRAY30.el" "leim/quail/CCDOSPY.el"
-;;;;;;  "leim/quail/CTLau-b5.el" "leim/quail/CTLau.el" "leim/quail/ECDICT.el"
-;;;;;;  "leim/quail/ETZY.el" "leim/quail/PY-b5.el" "leim/quail/PY.el"
-;;;;;;  "leim/quail/Punct-b5.el" "leim/quail/Punct.el" "leim/quail/QJ-b5.el"
-;;;;;;  "leim/quail/QJ.el" "leim/quail/SW.el" "leim/quail/TONEPY.el"
-;;;;;;  "leim/quail/ZIRANMA.el" "leim/quail/ZOZY.el" "leim/quail/arabic.el"
-;;;;;;  "leim/quail/cham.el" "leim/quail/compose.el" "leim/quail/croatian.el"
-;;;;;;  "leim/quail/cyril-jis.el" "leim/quail/cyrillic.el" 
"leim/quail/czech.el"
+;;;;;;  "international/mule-conf.el" "international/mule.el" 
"international/uni-bidi.el"
+;;;;;;  "international/uni-brackets.el" "international/uni-category.el"
+;;;;;;  "international/uni-combining.el" "international/uni-comment.el"
+;;;;;;  "international/uni-decimal.el" "international/uni-decomposition.el"
+;;;;;;  "international/uni-digit.el" "international/uni-lowercase.el"
+;;;;;;  "international/uni-mirrored.el" "international/uni-name.el"
+;;;;;;  "international/uni-numeric.el" "international/uni-old-name.el"
+;;;;;;  "international/uni-special-lowercase.el" 
"international/uni-special-titlecase.el"
+;;;;;;  "international/uni-special-uppercase.el" 
"international/uni-titlecase.el"
+;;;;;;  "international/uni-uppercase.el" "isearch.el" "jit-lock.el"
+;;;;;;  "jka-cmpr-hook.el" "keymap.el" "language/burmese.el" "language/cham.el"
+;;;;;;  "language/chinese.el" "language/cyrillic.el" "language/czech.el"
+;;;;;;  "language/english.el" "language/ethiopic.el" "language/european.el"
+;;;;;;  "language/georgian.el" "language/greek.el" "language/hebrew.el"
+;;;;;;  "language/indian.el" "language/japanese.el" "language/khmer.el"
+;;;;;;  "language/korean.el" "language/lao.el" "language/misc-lang.el"
+;;;;;;  "language/romanian.el" "language/sinhala.el" "language/slovak.el"
+;;;;;;  "language/tai-viet.el" "language/thai.el" "language/tibetan.el"
+;;;;;;  "language/utf-8-lang.el" "language/vietnamese.el" "ldefs-boot.el"
+;;;;;;  "leim/ja-dic/ja-dic.el" "leim/leim-list.el" "leim/quail/4Corner.el"
+;;;;;;  "leim/quail/ARRAY30.el" "leim/quail/CCDOSPY.el" 
"leim/quail/CTLau-b5.el"
+;;;;;;  "leim/quail/CTLau.el" "leim/quail/ECDICT.el" "leim/quail/ETZY.el"
+;;;;;;  "leim/quail/PY-b5.el" "leim/quail/PY.el" "leim/quail/Punct-b5.el"
+;;;;;;  "leim/quail/Punct.el" "leim/quail/QJ-b5.el" "leim/quail/QJ.el"
+;;;;;;  "leim/quail/SW.el" "leim/quail/TONEPY.el" "leim/quail/ZIRANMA.el"
+;;;;;;  "leim/quail/ZOZY.el" "leim/quail/arabic.el" "leim/quail/cham.el"
+;;;;;;  "leim/quail/compose.el" "leim/quail/croatian.el" 
"leim/quail/cyril-jis.el"
+;;;;;;  "leim/quail/cyrillic.el" "leim/quail/czech.el" "leim/quail/emoji.el"
 ;;;;;;  "leim/quail/georgian.el" "leim/quail/greek.el" 
"leim/quail/hanja-jis.el"
 ;;;;;;  "leim/quail/hanja.el" "leim/quail/hanja3.el" "leim/quail/hebrew.el"
 ;;;;;;  "leim/quail/ipa-praat.el" "leim/quail/latin-alt.el" 
"leim/quail/latin-ltx.el"
diff --git a/lisp/leim/quail/emoji.el b/lisp/leim/quail/emoji.el
new file mode 100644
index 0000000000..f9d3e170be
--- /dev/null
+++ b/lisp/leim/quail/emoji.el
@@ -0,0 +1,2003 @@
+;;; emoji.el --- Quail package for emoji character composition -*- 
lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Juri Linkov <juri@linkov.net>
+;; Keywords: multilingual, input method, i18n
+
+;; 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 input method supports the same key sequences as the names
+;; defined by the `C-x 8 e s' completions in emoji.el.  Also it adds
+;; more emoji that enclosed in double colons.
+
+;; You can enable this input method transiently with `C-u C-x \ emoji RET'.
+;; Then typing `C-x \' will enable this input method temporarily, and
+;; after typing a key sequence it will be disabled.  So typing
+;; e.g. `C-x \ : )' will insert the smiling character, and disable
+;; this input method automatically afterwards.
+
+;;; Code:
+
+(require 'quail)
+
+(quail-define-package
+ "emoji" "UTF-8" "🙂" t
+ "Emoji input method for inserting emoji characters.
+Examples:
+ slightly smiling face -> 🙂
+ :slightly_smiling_face: -> 🙂
+ :-) -> 🙂"
+ '(("\t" . quail-completion))
+ t nil nil nil nil nil nil nil nil t)
+
+(eval-when-compile
+  (require 'emoji)
+  (emoji--init)
+  (defmacro emoji--define-rules ()
+    `(quail-define-rules
+      ,@(let ((rules nil))
+          (maphash (lambda (from to)
+                     (push (list from (if (stringp to)
+                                          (vector to)
+                                        to))
+                           rules))
+                   emoji--all-bases)
+          (append
+           rules
+           '((":hash:" ["#️⃣"])
+             (":keycap_star:" ["*️⃣"])
+             (":zero:" ["0️⃣"])
+             (":one:" ["1️⃣"])
+             (":two:" ["2️⃣"])
+             (":three:" ["3️⃣"])
+             (":four:" ["4️⃣"])
+             (":five:" ["5️⃣"])
+             (":six:" ["6️⃣"])
+             (":seven:" ["7️⃣"])
+             (":eight:" ["8️⃣"])
+             (":nine:" ["9️⃣"])
+             (":copyright:" ["©️"])
+             (":registered:" ["®️"])
+             (":mahjong:" ["🀄"])
+             (":black_joker:" ["🃏"])
+             (":a:" ["🅰️"])
+             (":b:" ["🅱️"])
+             (":o2:" ["🅾️"])
+             (":parking:" ["🅿️"])
+             (":ab:" ["🆎"])
+             (":cl:" ["🆑"])
+             (":cool:" ["🆒"])
+             (":free:" ["🆓"])
+             (":id:" ["🆔"])
+             (":new:" ["🆕"])
+             (":ng:" ["🆖"])
+             (":ok:" ["🆗"])
+             (":sos:" ["🆘"])
+             (":up:" ["🆙"])
+             (":vs:" ["🆚"])
+             (":flag-ac:" ["🇦🇨"])
+             (":flag-ad:" ["🇦🇩"])
+             (":flag-ae:" ["🇦🇪"])
+             (":flag-af:" ["🇦🇫"])
+             (":flag-ag:" ["🇦🇬"])
+             (":flag-ai:" ["🇦🇮"])
+             (":flag-al:" ["🇦🇱"])
+             (":flag-am:" ["🇦🇲"])
+             (":flag-ao:" ["🇦🇴"])
+             (":flag-aq:" ["🇦🇶"])
+             (":flag-ar:" ["🇦🇷"])
+             (":flag-as:" ["🇦🇸"])
+             (":flag-at:" ["🇦🇹"])
+             (":flag-au:" ["🇦🇺"])
+             (":flag-aw:" ["🇦🇼"])
+             (":flag-ax:" ["🇦🇽"])
+             (":flag-az:" ["🇦🇿"])
+             (":flag-ba:" ["🇧🇦"])
+             (":flag-bb:" ["🇧🇧"])
+             (":flag-bd:" ["🇧🇩"])
+             (":flag-be:" ["🇧🇪"])
+             (":flag-bf:" ["🇧🇫"])
+             (":flag-bg:" ["🇧🇬"])
+             (":flag-bh:" ["🇧🇭"])
+             (":flag-bi:" ["🇧🇮"])
+             (":flag-bj:" ["🇧🇯"])
+             (":flag-bl:" ["🇧🇱"])
+             (":flag-bm:" ["🇧🇲"])
+             (":flag-bn:" ["🇧🇳"])
+             (":flag-bo:" ["🇧🇴"])
+             (":flag-bq:" ["🇧🇶"])
+             (":flag-br:" ["🇧🇷"])
+             (":flag-bs:" ["🇧🇸"])
+             (":flag-bt:" ["🇧🇹"])
+             (":flag-bv:" ["🇧🇻"])
+             (":flag-bw:" ["🇧🇼"])
+             (":flag-by:" ["🇧🇾"])
+             (":flag-bz:" ["🇧🇿"])
+             (":flag-ca:" ["🇨🇦"])
+             (":flag-cc:" ["🇨🇨"])
+             (":flag-cd:" ["🇨🇩"])
+             (":flag-cf:" ["🇨🇫"])
+             (":flag-cg:" ["🇨🇬"])
+             (":flag-ch:" ["🇨🇭"])
+             (":flag-ci:" ["🇨🇮"])
+             (":flag-ck:" ["🇨🇰"])
+             (":flag-cl:" ["🇨🇱"])
+             (":flag-cm:" ["🇨🇲"])
+             (":cn:" ["🇨🇳"])
+             (":flag-cn:" ["🇨🇳"])
+             (":flag-co:" ["🇨🇴"])
+             (":flag-cp:" ["🇨🇵"])
+             (":flag-cr:" ["🇨🇷"])
+             (":flag-cu:" ["🇨🇺"])
+             (":flag-cv:" ["🇨🇻"])
+             (":flag-cw:" ["🇨🇼"])
+             (":flag-cx:" ["🇨🇽"])
+             (":flag-cy:" ["🇨🇾"])
+             (":flag-cz:" ["🇨🇿"])
+             (":de:" ["🇩🇪"])
+             (":flag-de:" ["🇩🇪"])
+             (":flag-dg:" ["🇩🇬"])
+             (":flag-dj:" ["🇩🇯"])
+             (":flag-dk:" ["🇩🇰"])
+             (":flag-dm:" ["🇩🇲"])
+             (":flag-do:" ["🇩🇴"])
+             (":flag-dz:" ["🇩🇿"])
+             (":flag-ea:" ["🇪🇦"])
+             (":flag-ec:" ["🇪🇨"])
+             (":flag-ee:" ["🇪🇪"])
+             (":flag-eg:" ["🇪🇬"])
+             (":flag-eh:" ["🇪🇭"])
+             (":flag-er:" ["🇪🇷"])
+             (":es:" ["🇪🇸"])
+             (":flag-es:" ["🇪🇸"])
+             (":flag-et:" ["🇪🇹"])
+             (":flag-eu:" ["🇪🇺"])
+             (":flag-fi:" ["🇫🇮"])
+             (":flag-fj:" ["🇫🇯"])
+             (":flag-fk:" ["🇫🇰"])
+             (":flag-fm:" ["🇫🇲"])
+             (":flag-fo:" ["🇫🇴"])
+             (":fr:" ["🇫🇷"])
+             (":flag-fr:" ["🇫🇷"])
+             (":flag-ga:" ["🇬🇦"])
+             (":gb:" ["🇬🇧"])
+             (":uk:" ["🇬🇧"])
+             (":flag-gb:" ["🇬🇧"])
+             (":flag-gd:" ["🇬🇩"])
+             (":flag-ge:" ["🇬🇪"])
+             (":flag-gf:" ["🇬🇫"])
+             (":flag-gg:" ["🇬🇬"])
+             (":flag-gh:" ["🇬🇭"])
+             (":flag-gi:" ["🇬🇮"])
+             (":flag-gl:" ["🇬🇱"])
+             (":flag-gm:" ["🇬🇲"])
+             (":flag-gn:" ["🇬🇳"])
+             (":flag-gp:" ["🇬🇵"])
+             (":flag-gq:" ["🇬🇶"])
+             (":flag-gr:" ["🇬🇷"])
+             (":flag-gs:" ["🇬🇸"])
+             (":flag-gt:" ["🇬🇹"])
+             (":flag-gu:" ["🇬🇺"])
+             (":flag-gw:" ["🇬🇼"])
+             (":flag-gy:" ["🇬🇾"])
+             (":flag-hk:" ["🇭🇰"])
+             (":flag-hm:" ["🇭🇲"])
+             (":flag-hn:" ["🇭🇳"])
+             (":flag-hr:" ["🇭🇷"])
+             (":flag-ht:" ["🇭🇹"])
+             (":flag-hu:" ["🇭🇺"])
+             (":flag-ic:" ["🇮🇨"])
+             (":flag-id:" ["🇮🇩"])
+             (":flag-ie:" ["🇮🇪"])
+             (":flag-il:" ["🇮🇱"])
+             (":flag-im:" ["🇮🇲"])
+             (":flag-in:" ["🇮🇳"])
+             (":flag-io:" ["🇮🇴"])
+             (":flag-iq:" ["🇮🇶"])
+             (":flag-ir:" ["🇮🇷"])
+             (":flag-is:" ["🇮🇸"])
+             (":it:" ["🇮🇹"])
+             (":flag-it:" ["🇮🇹"])
+             (":flag-je:" ["🇯🇪"])
+             (":flag-jm:" ["🇯🇲"])
+             (":flag-jo:" ["🇯🇴"])
+             (":jp:" ["🇯🇵"])
+             (":flag-jp:" ["🇯🇵"])
+             (":flag-ke:" ["🇰🇪"])
+             (":flag-kg:" ["🇰🇬"])
+             (":flag-kh:" ["🇰🇭"])
+             (":flag-ki:" ["🇰🇮"])
+             (":flag-km:" ["🇰🇲"])
+             (":flag-kn:" ["🇰🇳"])
+             (":flag-kp:" ["🇰🇵"])
+             (":kr:" ["🇰🇷"])
+             (":flag-kr:" ["🇰🇷"])
+             (":flag-kw:" ["🇰🇼"])
+             (":flag-ky:" ["🇰🇾"])
+             (":flag-kz:" ["🇰🇿"])
+             (":flag-la:" ["🇱🇦"])
+             (":flag-lb:" ["🇱🇧"])
+             (":flag-lc:" ["🇱🇨"])
+             (":flag-li:" ["🇱🇮"])
+             (":flag-lk:" ["🇱🇰"])
+             (":flag-lr:" ["🇱🇷"])
+             (":flag-ls:" ["🇱🇸"])
+             (":flag-lt:" ["🇱🇹"])
+             (":flag-lu:" ["🇱🇺"])
+             (":flag-lv:" ["🇱🇻"])
+             (":flag-ly:" ["🇱🇾"])
+             (":flag-ma:" ["🇲🇦"])
+             (":flag-mc:" ["🇲🇨"])
+             (":flag-md:" ["🇲🇩"])
+             (":flag-me:" ["🇲🇪"])
+             (":flag-mf:" ["🇲🇫"])
+             (":flag-mg:" ["🇲🇬"])
+             (":flag-mh:" ["🇲🇭"])
+             (":flag-mk:" ["🇲🇰"])
+             (":flag-ml:" ["🇲🇱"])
+             (":flag-mm:" ["🇲🇲"])
+             (":flag-mn:" ["🇲🇳"])
+             (":flag-mo:" ["🇲🇴"])
+             (":flag-mp:" ["🇲🇵"])
+             (":flag-mq:" ["🇲🇶"])
+             (":flag-mr:" ["🇲🇷"])
+             (":flag-ms:" ["🇲🇸"])
+             (":flag-mt:" ["🇲🇹"])
+             (":flag-mu:" ["🇲🇺"])
+             (":flag-mv:" ["🇲🇻"])
+             (":flag-mw:" ["🇲🇼"])
+             (":flag-mx:" ["🇲🇽"])
+             (":flag-my:" ["🇲🇾"])
+             (":flag-mz:" ["🇲🇿"])
+             (":flag-na:" ["🇳🇦"])
+             (":flag-nc:" ["🇳🇨"])
+             (":flag-ne:" ["🇳🇪"])
+             (":flag-nf:" ["🇳🇫"])
+             (":flag-ng:" ["🇳🇬"])
+             (":flag-ni:" ["🇳🇮"])
+             (":flag-nl:" ["🇳🇱"])
+             (":flag-no:" ["🇳🇴"])
+             (":flag-np:" ["🇳🇵"])
+             (":flag-nr:" ["🇳🇷"])
+             (":flag-nu:" ["🇳🇺"])
+             (":flag-nz:" ["🇳🇿"])
+             (":flag-om:" ["🇴🇲"])
+             (":flag-pa:" ["🇵🇦"])
+             (":flag-pe:" ["🇵🇪"])
+             (":flag-pf:" ["🇵🇫"])
+             (":flag-pg:" ["🇵🇬"])
+             (":flag-ph:" ["🇵🇭"])
+             (":flag-pk:" ["🇵🇰"])
+             (":flag-pl:" ["🇵🇱"])
+             (":flag-pm:" ["🇵🇲"])
+             (":flag-pn:" ["🇵🇳"])
+             (":flag-pr:" ["🇵🇷"])
+             (":flag-ps:" ["🇵🇸"])
+             (":flag-pt:" ["🇵🇹"])
+             (":flag-pw:" ["🇵🇼"])
+             (":flag-py:" ["🇵🇾"])
+             (":flag-qa:" ["🇶🇦"])
+             (":flag-re:" ["🇷🇪"])
+             (":flag-ro:" ["🇷🇴"])
+             (":flag-rs:" ["🇷🇸"])
+             (":ru:" ["🇷🇺"])
+             (":flag-ru:" ["🇷🇺"])
+             (":flag-rw:" ["🇷🇼"])
+             (":flag-sa:" ["🇸🇦"])
+             (":flag-sb:" ["🇸🇧"])
+             (":flag-sc:" ["🇸🇨"])
+             (":flag-sd:" ["🇸🇩"])
+             (":flag-se:" ["🇸🇪"])
+             (":flag-sg:" ["🇸🇬"])
+             (":flag-sh:" ["🇸🇭"])
+             (":flag-si:" ["🇸🇮"])
+             (":flag-sj:" ["🇸🇯"])
+             (":flag-sk:" ["🇸🇰"])
+             (":flag-sl:" ["🇸🇱"])
+             (":flag-sm:" ["🇸🇲"])
+             (":flag-sn:" ["🇸🇳"])
+             (":flag-so:" ["🇸🇴"])
+             (":flag-sr:" ["🇸🇷"])
+             (":flag-ss:" ["🇸🇸"])
+             (":flag-st:" ["🇸🇹"])
+             (":flag-sv:" ["🇸🇻"])
+             (":flag-sx:" ["🇸🇽"])
+             (":flag-sy:" ["🇸🇾"])
+             (":flag-sz:" ["🇸🇿"])
+             (":flag-ta:" ["🇹🇦"])
+             (":flag-tc:" ["🇹🇨"])
+             (":flag-td:" ["🇹🇩"])
+             (":flag-tf:" ["🇹🇫"])
+             (":flag-tg:" ["🇹🇬"])
+             (":flag-th:" ["🇹🇭"])
+             (":flag-tj:" ["🇹🇯"])
+             (":flag-tk:" ["🇹🇰"])
+             (":flag-tl:" ["🇹🇱"])
+             (":flag-tm:" ["🇹🇲"])
+             (":flag-tn:" ["🇹🇳"])
+             (":flag-to:" ["🇹🇴"])
+             (":flag-tr:" ["🇹🇷"])
+             (":flag-tt:" ["🇹🇹"])
+             (":flag-tv:" ["🇹🇻"])
+             (":flag-tw:" ["🇹🇼"])
+             (":flag-tz:" ["🇹🇿"])
+             (":flag-ua:" ["🇺🇦"])
+             (":flag-ug:" ["🇺🇬"])
+             (":flag-um:" ["🇺🇲"])
+             (":flag-un:" ["🇺🇳"])
+             (":us:" ["🇺🇸"])
+             (":flag-us:" ["🇺🇸"])
+             (":flag-uy:" ["🇺🇾"])
+             (":flag-uz:" ["🇺🇿"])
+             (":flag-va:" ["🇻🇦"])
+             (":flag-vc:" ["🇻🇨"])
+             (":flag-ve:" ["🇻🇪"])
+             (":flag-vg:" ["🇻🇬"])
+             (":flag-vi:" ["🇻🇮"])
+             (":flag-vn:" ["🇻🇳"])
+             (":flag-vu:" ["🇻🇺"])
+             (":flag-wf:" ["🇼🇫"])
+             (":flag-ws:" ["🇼🇸"])
+             (":flag-xk:" ["🇽🇰"])
+             (":flag-ye:" ["🇾🇪"])
+             (":flag-yt:" ["🇾🇹"])
+             (":flag-za:" ["🇿🇦"])
+             (":flag-zm:" ["🇿🇲"])
+             (":flag-zw:" ["🇿🇼"])
+             (":koko:" ["🈁"])
+             (":sa:" ["🈂️"])
+             (":u7121:" ["🈚"])
+             (":u6307:" ["🈯"])
+             (":u7981:" ["🈲"])
+             (":u7a7a:" ["🈳"])
+             (":u5408:" ["🈴"])
+             (":u6e80:" ["🈵"])
+             (":u6709:" ["🈶"])
+             (":u6708:" ["🈷️"])
+             (":u7533:" ["🈸"])
+             (":u5272:" ["🈹"])
+             (":u55b6:" ["🈺"])
+             (":ideograph_advantage:" ["🉐"])
+             (":accept:" ["🉑"])
+             (":cyclone:" ["🌀"])
+             (":foggy:" ["🌁"])
+             (":closed_umbrella:" ["🌂"])
+             (":night_with_stars:" ["🌃"])
+             (":sunrise_over_mountains:" ["🌄"])
+             (":sunrise:" ["🌅"])
+             (":city_sunset:" ["🌆"])
+             (":city_sunrise:" ["🌇"])
+             (":rainbow:" ["🌈"])
+             (":bridge_at_night:" ["🌉"])
+             (":ocean:" ["🌊"])
+             (":volcano:" ["🌋"])
+             (":milky_way:" ["🌌"])
+             (":earth_africa:" ["🌍"])
+             (":earth_americas:" ["🌎"])
+             (":earth_asia:" ["🌏"])
+             (":globe_with_meridians:" ["🌐"])
+             (":new_moon:" ["🌑"])
+             (":waxing_crescent_moon:" ["🌒"])
+             (":first_quarter_moon:" ["🌓"])
+             (":moon:" ["🌔"])
+             (":waxing_gibbous_moon:" ["🌔"])
+             (":full_moon:" ["🌕"])
+             (":waning_gibbous_moon:" ["🌖"])
+             (":last_quarter_moon:" ["🌗"])
+             (":waning_crescent_moon:" ["🌘"])
+             (":crescent_moon:" ["🌙"])
+             (":new_moon_with_face:" ["🌚"])
+             (":first_quarter_moon_with_face:" ["🌛"])
+             (":last_quarter_moon_with_face:" ["🌜"])
+             (":full_moon_with_face:" ["🌝"])
+             (":sun_with_face:" ["🌞"])
+             (":star2:" ["🌟"])
+             (":stars:" ["🌠"])
+             (":thermometer:" ["🌡️"])
+             (":mostly_sunny:" ["🌤️"])
+             (":sun_small_cloud:" ["🌤️"])
+             (":barely_sunny:" ["🌥️"])
+             (":sun_behind_cloud:" ["🌥️"])
+             (":partly_sunny_rain:" ["🌦️"])
+             (":sun_behind_rain_cloud:" ["🌦️"])
+             (":rain_cloud:" ["🌧️"])
+             (":snow_cloud:" ["🌨️"])
+             (":lightning:" ["🌩️"])
+             (":lightning_cloud:" ["🌩️"])
+             (":tornado:" ["🌪️"])
+             (":tornado_cloud:" ["🌪️"])
+             (":fog:" ["🌫️"])
+             (":wind_blowing_face:" ["🌬️"])
+             (":hotdog:" ["🌭"])
+             (":taco:" ["🌮"])
+             (":burrito:" ["🌯"])
+             (":chestnut:" ["🌰"])
+             (":seedling:" ["🌱"])
+             (":evergreen_tree:" ["🌲"])
+             (":deciduous_tree:" ["🌳"])
+             (":palm_tree:" ["🌴"])
+             (":cactus:" ["🌵"])
+             (":hot_pepper:" ["🌶️"])
+             (":tulip:" ["🌷"])
+             (":cherry_blossom:" ["🌸"])
+             (":rose:" ["🌹"])
+             (":hibiscus:" ["🌺"])
+             (":sunflower:" ["🌻"])
+             (":blossom:" ["🌼"])
+             (":corn:" ["🌽"])
+             (":ear_of_rice:" ["🌾"])
+             (":herb:" ["🌿"])
+             (":four_leaf_clover:" ["🍀"])
+             (":maple_leaf:" ["🍁"])
+             (":fallen_leaf:" ["🍂"])
+             (":leaves:" ["🍃"])
+             (":mushroom:" ["🍄"])
+             (":tomato:" ["🍅"])
+             (":eggplant:" ["🍆"])
+             (":grapes:" ["🍇"])
+             (":melon:" ["🍈"])
+             (":watermelon:" ["🍉"])
+             (":tangerine:" ["🍊"])
+             (":lemon:" ["🍋"])
+             (":banana:" ["🍌"])
+             (":pineapple:" ["🍍"])
+             (":apple:" ["🍎"])
+             (":green_apple:" ["🍏"])
+             (":pear:" ["🍐"])
+             (":peach:" ["🍑"])
+             (":cherries:" ["🍒"])
+             (":strawberry:" ["🍓"])
+             (":hamburger:" ["🍔"])
+             (":pizza:" ["🍕"])
+             (":meat_on_bone:" ["🍖"])
+             (":poultry_leg:" ["🍗"])
+             (":rice_cracker:" ["🍘"])
+             (":rice_ball:" ["🍙"])
+             (":rice:" ["🍚"])
+             (":curry:" ["🍛"])
+             (":ramen:" ["🍜"])
+             (":spaghetti:" ["🍝"])
+             (":bread:" ["🍞"])
+             (":fries:" ["🍟"])
+             (":sweet_potato:" ["🍠"])
+             (":dango:" ["🍡"])
+             (":oden:" ["🍢"])
+             (":sushi:" ["🍣"])
+             (":fried_shrimp:" ["🍤"])
+             (":fish_cake:" ["🍥"])
+             (":icecream:" ["🍦"])
+             (":shaved_ice:" ["🍧"])
+             (":ice_cream:" ["🍨"])
+             (":doughnut:" ["🍩"])
+             (":cookie:" ["🍪"])
+             (":chocolate_bar:" ["🍫"])
+             (":candy:" ["🍬"])
+             (":lollipop:" ["🍭"])
+             (":custard:" ["🍮"])
+             (":honey_pot:" ["🍯"])
+             (":cake:" ["🍰"])
+             (":bento:" ["🍱"])
+             (":stew:" ["🍲"])
+             (":fried_egg:" ["🍳"])
+             (":cooking:" ["🍳"])
+             (":fork_and_knife:" ["🍴"])
+             (":tea:" ["🍵"])
+             (":sake:" ["🍶"])
+             (":wine_glass:" ["🍷"])
+             (":cocktail:" ["🍸"])
+             (":tropical_drink:" ["🍹"])
+             (":beer:" ["🍺"])
+             (":beers:" ["🍻"])
+             (":baby_bottle:" ["🍼"])
+             (":knife_fork_plate:" ["🍽️"])
+             (":champagne:" ["🍾"])
+             (":popcorn:" ["🍿"])
+             (":ribbon:" ["🎀"])
+             (":gift:" ["🎁"])
+             (":birthday:" ["🎂"])
+             (":jack_o_lantern:" ["🎃"])
+             (":christmas_tree:" ["🎄"])
+             (":santa:" ["🎅"])
+             (":fireworks:" ["🎆"])
+             (":sparkler:" ["🎇"])
+             (":balloon:" ["🎈"])
+             (":tada:" ["🎉"])
+             (":confetti_ball:" ["🎊"])
+             (":tanabata_tree:" ["🎋"])
+             (":crossed_flags:" ["🎌"])
+             (":bamboo:" ["🎍"])
+             (":dolls:" ["🎎"])
+             (":flags:" ["🎏"])
+             (":wind_chime:" ["🎐"])
+             (":rice_scene:" ["🎑"])
+             (":school_satchel:" ["🎒"])
+             (":mortar_board:" ["🎓"])
+             (":medal:" ["🎖️"])
+             (":reminder_ribbon:" ["🎗️"])
+             (":studio_microphone:" ["🎙️"])
+             (":level_slider:" ["🎚️"])
+             (":control_knobs:" ["🎛️"])
+             (":film_frames:" ["🎞️"])
+             (":admission_tickets:" ["🎟️"])
+             (":carousel_horse:" ["🎠"])
+             (":ferris_wheel:" ["🎡"])
+             (":roller_coaster:" ["🎢"])
+             (":fishing_pole_and_fish:" ["🎣"])
+             (":microphone:" ["🎤"])
+             (":movie_camera:" ["🎥"])
+             (":cinema:" ["🎦"])
+             (":headphones:" ["🎧"])
+             (":art:" ["🎨"])
+             (":tophat:" ["🎩"])
+             (":circus_tent:" ["🎪"])
+             (":ticket:" ["🎫"])
+             (":clapper:" ["🎬"])
+             (":performing_arts:" ["🎭"])
+             (":video_game:" ["🎮"])
+             (":dart:" ["🎯"])
+             (":slot_machine:" ["🎰"])
+             (":8ball:" ["🎱"])
+             (":game_die:" ["🎲"])
+             (":bowling:" ["🎳"])
+             (":flower_playing_cards:" ["🎴"])
+             (":musical_note:" ["🎵"])
+             (":notes:" ["🎶"])
+             (":saxophone:" ["🎷"])
+             (":guitar:" ["🎸"])
+             (":musical_keyboard:" ["🎹"])
+             (":trumpet:" ["🎺"])
+             (":violin:" ["🎻"])
+             (":musical_score:" ["🎼"])
+             (":running_shirt_with_sash:" ["🎽"])
+             (":tennis:" ["🎾"])
+             (":ski:" ["🎿"])
+             (":basketball:" ["🏀"])
+             (":checkered_flag:" ["🏁"])
+             (":snowboarder:" ["🏂"])
+             (":woman-running:" ["🏃‍♀️"])
+             (":man-running:" ["🏃‍♂️"])
+             (":runner:" ["🏃"])
+             (":running:" ["🏃"])
+             (":woman-surfing:" ["🏄‍♀️"])
+             (":man-surfing:" ["🏄‍♂️"])
+             (":surfer:" ["🏄"])
+             (":sports_medal:" ["🏅"])
+             (":trophy:" ["🏆"])
+             (":horse_racing:" ["🏇"])
+             (":football:" ["🏈"])
+             (":rugby_football:" ["🏉"])
+             (":woman-swimming:" ["🏊‍♀️"])
+             (":man-swimming:" ["🏊‍♂️"])
+             (":swimmer:" ["🏊"])
+             (":woman-lifting-weights:" ["🏋️‍♀️"])
+             (":man-lifting-weights:" ["🏋️‍♂️"])
+             (":weight_lifter:" ["🏋️"])
+             (":woman-golfing:" ["🏌️‍♀️"])
+             (":man-golfing:" ["🏌️‍♂️"])
+             (":golfer:" ["🏌️"])
+             (":racing_motorcycle:" ["🏍️"])
+             (":racing_car:" ["🏎️"])
+             (":cricket_bat_and_ball:" ["🏏"])
+             (":volleyball:" ["🏐"])
+             (":field_hockey_stick_and_ball:" ["🏑"])
+             (":ice_hockey_stick_and_puck:" ["🏒"])
+             (":table_tennis_paddle_and_ball:" ["🏓"])
+             (":snow_capped_mountain:" ["🏔️"])
+             (":camping:" ["🏕️"])
+             (":beach_with_umbrella:" ["🏖️"])
+             (":building_construction:" ["🏗️"])
+             (":house_buildings:" ["🏘️"])
+             (":cityscape:" ["🏙️"])
+             (":derelict_house_building:" ["🏚️"])
+             (":classical_building:" ["🏛️"])
+             (":desert:" ["🏜️"])
+             (":desert_island:" ["🏝️"])
+             (":national_park:" ["🏞️"])
+             (":stadium:" ["🏟️"])
+             (":house:" ["🏠"])
+             (":house_with_garden:" ["🏡"])
+             (":office:" ["🏢"])
+             (":post_office:" ["🏣"])
+             (":european_post_office:" ["🏤"])
+             (":hospital:" ["🏥"])
+             (":bank:" ["🏦"])
+             (":atm:" ["🏧"])
+             (":hotel:" ["🏨"])
+             (":love_hotel:" ["🏩"])
+             (":convenience_store:" ["🏪"])
+             (":school:" ["🏫"])
+             (":department_store:" ["🏬"])
+             (":factory:" ["🏭"])
+             (":izakaya_lantern:" ["🏮"])
+             (":lantern:" ["🏮"])
+             (":japanese_castle:" ["🏯"])
+             (":european_castle:" ["🏰"])
+             (":rainbow-flag:" ["🏳️‍🌈"])
+             (":transgender_flag:" ["🏳️‍⚧️"])
+             (":waving_white_flag:" ["🏳️"])
+             (":pirate_flag:" ["🏴‍☠️"])
+             (":flag-england:" ["🏴󠁧󠁢󠁥󠁮󠁧󠁿"])
+             (":flag-scotland:" ["🏴󠁧󠁢󠁳󠁣󠁴󠁿"])
+             (":flag-wales:" ["🏴󠁧󠁢󠁷󠁬󠁳󠁿"])
+             (":waving_black_flag:" ["🏴"])
+             (":rosette:" ["🏵️"])
+             (":label:" ["🏷️"])
+             (":badminton_racquet_and_shuttlecock:" ["🏸"])
+             (":bow_and_arrow:" ["🏹"])
+             (":amphora:" ["🏺"])
+             (":skin-tone-2:" ["🏻"])
+             (":skin-tone-3:" ["🏼"])
+             (":skin-tone-4:" ["🏽"])
+             (":skin-tone-5:" ["🏾"])
+             (":skin-tone-6:" ["🏿"])
+             (":rat:" ["🐀"])
+             (":mouse2:" ["🐁"])
+             (":ox:" ["🐂"])
+             (":water_buffalo:" ["🐃"])
+             (":cow2:" ["🐄"])
+             (":tiger2:" ["🐅"])
+             (":leopard:" ["🐆"])
+             (":rabbit2:" ["🐇"])
+             (":black_cat:" ["🐈‍⬛"])
+             (":cat2:" ["🐈"])
+             (":dragon:" ["🐉"])
+             (":crocodile:" ["🐊"])
+             (":whale2:" ["🐋"])
+             (":snail:" ["🐌"])
+             (":snake:" ["🐍"])
+             (":racehorse:" ["🐎"])
+             (":ram:" ["🐏"])
+             (":goat:" ["🐐"])
+             (":sheep:" ["🐑"])
+             (":monkey:" ["🐒"])
+             (":rooster:" ["🐓"])
+             (":chicken:" ["🐔"])
+             (":service_dog:" ["🐕‍🦺"])
+             (":dog2:" ["🐕"])
+             (":pig2:" ["🐖"])
+             (":boar:" ["🐗"])
+             (":elephant:" ["🐘"])
+             (":octopus:" ["🐙"])
+             (":shell:" ["🐚"])
+             (":bug:" ["🐛"])
+             (":ant:" ["🐜"])
+             (":bee:" ["🐝"])
+             (":honeybee:" ["🐝"])
+             (":ladybug:" ["🐞"])
+             (":lady_beetle:" ["🐞"])
+             (":fish:" ["🐟"])
+             (":tropical_fish:" ["🐠"])
+             (":blowfish:" ["🐡"])
+             (":turtle:" ["🐢"])
+             (":hatching_chick:" ["🐣"])
+             (":baby_chick:" ["🐤"])
+             (":hatched_chick:" ["🐥"])
+             (":bird:" ["🐦"])
+             (":penguin:" ["🐧"])
+             (":koala:" ["🐨"])
+             (":poodle:" ["🐩"])
+             (":dromedary_camel:" ["🐪"])
+             (":camel:" ["🐫"])
+             (":dolphin:" ["🐬"])
+             (":flipper:" ["🐬"])
+             (":mouse:" ["🐭"])
+             (":cow:" ["🐮"])
+             (":tiger:" ["🐯"])
+             (":rabbit:" ["🐰"])
+             (":cat:" ["🐱"])
+             (":dragon_face:" ["🐲"])
+             (":whale:" ["🐳"])
+             (":horse:" ["🐴"])
+             (":monkey_face:" ["🐵"])
+             (":o)" ["🐵"])
+             (":dog:" ["🐶"])
+             (":pig:" ["🐷"])
+             (":frog:" ["🐸"])
+             (":hamster:" ["🐹"])
+             (":wolf:" ["🐺"])
+             (":polar_bear:" ["🐻‍❄️"])
+             (":bear:" ["🐻"])
+             (":panda_face:" ["🐼"])
+             (":pig_nose:" ["🐽"])
+             (":feet:" ["🐾"])
+             (":paw_prints:" ["🐾"])
+             (":chipmunk:" ["🐿️"])
+             (":eyes:" ["👀"])
+             (":eye-in-speech-bubble:" ["👁️‍🗨️"])
+             (":eye:" ["👁️"])
+             (":ear:" ["👂"])
+             (":nose:" ["👃"])
+             (":lips:" ["👄"])
+             (":tongue:" ["👅"])
+             (":point_up_2:" ["👆"])
+             (":point_down:" ["👇"])
+             (":point_left:" ["👈"])
+             (":point_right:" ["👉"])
+             (":facepunch:" ["👊"])
+             (":punch:" ["👊"])
+             (":wave:" ["👋"])
+             (":ok_hand:" ["👌"])
+             (":+1:" ["👍"])
+             (":thumbsup:" ["👍"])
+             (":-1:" ["👎"])
+             (":thumbsdown:" ["👎"])
+             (":clap:" ["👏"])
+             (":open_hands:" ["👐"])
+             (":crown:" ["👑"])
+             (":womans_hat:" ["👒"])
+             (":eyeglasses:" ["👓"])
+             (":necktie:" ["👔"])
+             (":shirt:" ["👕"])
+             (":tshirt:" ["👕"])
+             (":jeans:" ["👖"])
+             (":dress:" ["👗"])
+             (":kimono:" ["👘"])
+             (":bikini:" ["👙"])
+             (":womans_clothes:" ["👚"])
+             (":purse:" ["👛"])
+             (":handbag:" ["👜"])
+             (":pouch:" ["👝"])
+             (":mans_shoe:" ["👞"])
+             (":shoe:" ["👞"])
+             (":athletic_shoe:" ["👟"])
+             (":high_heel:" ["👠"])
+             (":sandal:" ["👡"])
+             (":boot:" ["👢"])
+             (":footprints:" ["👣"])
+             (":bust_in_silhouette:" ["👤"])
+             (":busts_in_silhouette:" ["👥"])
+             (":boy:" ["👦"])
+             (":girl:" ["👧"])
+             (":male-farmer:" ["👨‍🌾"])
+             (":male-cook:" ["👨‍🍳"])
+             (":man_feeding_baby:" ["👨‍🍼"])
+             (":male-student:" ["👨‍🎓"])
+             (":male-singer:" ["👨‍🎤"])
+             (":male-artist:" ["👨‍🎨"])
+             (":male-teacher:" ["👨‍🏫"])
+             (":male-factory-worker:" ["👨‍🏭"])
+             (":man-boy-boy:" ["👨‍👦‍👦"])
+             (":man-boy:" ["👨‍👦"])
+             (":man-girl-boy:" ["👨‍👧‍👦"])
+             (":man-girl-girl:" ["👨‍👧‍👧"])
+             (":man-girl:" ["👨‍👧"])
+             (":man-man-boy:" ["👨‍👨‍👦"])
+             (":man-man-boy-boy:" ["👨‍👨‍👦‍👦"])
+             (":man-man-girl:" ["👨‍👨‍👧"])
+             (":man-man-girl-boy:" ["👨‍👨‍👧‍👦"])
+             (":man-man-girl-girl:" ["👨‍👨‍👧‍👧"])
+             (":man-woman-boy:" ["👨‍👩‍👦"])
+             (":man-woman-boy-boy:" ["👨‍👩‍👦‍👦"])
+             (":man-woman-girl:" ["👨‍👩‍👧"])
+             (":man-woman-girl-boy:" ["👨‍👩‍👧‍👦"])
+             (":man-woman-girl-girl:" ["👨‍👩‍👧‍👧"])
+             (":male-technologist:" ["👨‍💻"])
+             (":male-office-worker:" ["👨‍💼"])
+             (":male-mechanic:" ["👨‍🔧"])
+             (":male-scientist:" ["👨‍🔬"])
+             (":male-astronaut:" ["👨‍🚀"])
+             (":male-firefighter:" ["👨‍🚒"])
+             (":man_with_probing_cane:" ["👨‍🦯"])
+             (":red_haired_man:" ["👨‍🦰"])
+             (":curly_haired_man:" ["👨‍🦱"])
+             (":bald_man:" ["👨‍🦲"])
+             (":white_haired_man:" ["👨‍🦳"])
+             (":man_in_motorized_wheelchair:" ["👨‍🦼"])
+             (":man_in_manual_wheelchair:" ["👨‍🦽"])
+             (":male-doctor:" ["👨‍⚕️"])
+             (":male-judge:" ["👨‍⚖️"])
+             (":male-pilot:" ["👨‍✈️"])
+             (":man-heart-man:" ["👨‍❤️‍👨"])
+             (":man-kiss-man:" ["👨‍❤️‍💋‍👨"])
+             (":man:" ["👨"])
+             (":female-farmer:" ["👩‍🌾"])
+             (":female-cook:" ["👩‍🍳"])
+             (":woman_feeding_baby:" ["👩‍🍼"])
+             (":female-student:" ["👩‍🎓"])
+             (":female-singer:" ["👩‍🎤"])
+             (":female-artist:" ["👩‍🎨"])
+             (":female-teacher:" ["👩‍🏫"])
+             (":female-factory-worker:" ["👩‍🏭"])
+             (":woman-boy-boy:" ["👩‍👦‍👦"])
+             (":woman-boy:" ["👩‍👦"])
+             (":woman-girl-boy:" ["👩‍👧‍👦"])
+             (":woman-girl-girl:" ["👩‍👧‍👧"])
+             (":woman-girl:" ["👩‍👧"])
+             (":woman-woman-boy:" ["👩‍👩‍👦"])
+             (":woman-woman-boy-boy:" ["👩‍👩‍👦‍👦"])
+             (":woman-woman-girl:" ["👩‍👩‍👧"])
+             (":woman-woman-girl-boy:" ["👩‍👩‍👧‍👦"])
+             (":woman-woman-girl-girl:" ["👩‍👩‍👧‍👧"])
+             (":female-technologist:" ["👩‍💻"])
+             (":female-office-worker:" ["👩‍💼"])
+             (":female-mechanic:" ["👩‍🔧"])
+             (":female-scientist:" ["👩‍🔬"])
+             (":female-astronaut:" ["👩‍🚀"])
+             (":female-firefighter:" ["👩‍🚒"])
+             (":woman_with_probing_cane:" ["👩‍🦯"])
+             (":red_haired_woman:" ["👩‍🦰"])
+             (":curly_haired_woman:" ["👩‍🦱"])
+             (":bald_woman:" ["👩‍🦲"])
+             (":white_haired_woman:" ["👩‍🦳"])
+             (":woman_in_motorized_wheelchair:" ["👩‍🦼"])
+             (":woman_in_manual_wheelchair:" ["👩‍🦽"])
+             (":female-doctor:" ["👩‍⚕️"])
+             (":female-judge:" ["👩‍⚖️"])
+             (":female-pilot:" ["👩‍✈️"])
+             (":woman-heart-man:" ["👩‍❤️‍👨"])
+             (":woman-heart-woman:" ["👩‍❤️‍👩"])
+             (":woman-kiss-man:" ["👩‍❤️‍💋‍👨"])
+             (":woman-kiss-woman:" ["👩‍❤️‍💋‍👩"])
+             (":woman:" ["👩"])
+             (":family:" ["👪"])
+             (":man_and_woman_holding_hands:" ["👫"])
+             (":woman_and_man_holding_hands:" ["👫"])
+             (":couple:" ["👫"])
+             (":two_men_holding_hands:" ["👬"])
+             (":men_holding_hands:" ["👬"])
+             (":two_women_holding_hands:" ["👭"])
+             (":women_holding_hands:" ["👭"])
+             (":female-police-officer:" ["👮‍♀️"])
+             (":male-police-officer:" ["👮‍♂️"])
+             (":cop:" ["👮"])
+             (":women-with-bunny-ears-partying:" ["👯‍♀️"])
+             (":woman-with-bunny-ears-partying:" ["👯‍♀️"])
+             (":men-with-bunny-ears-partying:" ["👯‍♂️"])
+             (":man-with-bunny-ears-partying:" ["👯‍♂️"])
+             (":dancers:" ["👯"])
+             (":woman_with_veil:" ["👰‍♀️"])
+             (":man_with_veil:" ["👰‍♂️"])
+             (":bride_with_veil:" ["👰"])
+             (":blond-haired-woman:" ["👱‍♀️"])
+             (":blond-haired-man:" ["👱‍♂️"])
+             (":person_with_blond_hair:" ["👱"])
+             (":man_with_gua_pi_mao:" ["👲"])
+             (":woman-wearing-turban:" ["👳‍♀️"])
+             (":man-wearing-turban:" ["👳‍♂️"])
+             (":man_with_turban:" ["👳"])
+             (":older_man:" ["👴"])
+             (":older_woman:" ["👵"])
+             (":baby:" ["👶"])
+             (":female-construction-worker:" ["👷‍♀️"])
+             (":male-construction-worker:" ["👷‍♂️"])
+             (":construction_worker:" ["👷"])
+             (":princess:" ["👸"])
+             (":japanese_ogre:" ["👹"])
+             (":japanese_goblin:" ["👺"])
+             (":ghost:" ["👻"])
+             (":angel:" ["👼"])
+             (":alien:" ["👽"])
+             (":space_invader:" ["👾"])
+             (":imp:" ["👿"])
+             (":skull:" ["💀"])
+             (":woman-tipping-hand:" ["💁‍♀️"])
+             (":man-tipping-hand:" ["💁‍♂️"])
+             (":information_desk_person:" ["💁"])
+             (":female-guard:" ["💂‍♀️"])
+             (":male-guard:" ["💂‍♂️"])
+             (":guardsman:" ["💂"])
+             (":dancer:" ["💃"])
+             (":lipstick:" ["💄"])
+             (":nail_care:" ["💅"])
+             (":woman-getting-massage:" ["💆‍♀️"])
+             (":man-getting-massage:" ["💆‍♂️"])
+             (":massage:" ["💆"])
+             (":woman-getting-haircut:" ["💇‍♀️"])
+             (":man-getting-haircut:" ["💇‍♂️"])
+             (":haircut:" ["💇"])
+             (":barber:" ["💈"])
+             (":syringe:" ["💉"])
+             (":pill:" ["💊"])
+             (":kiss:" ["💋"])
+             (":love_letter:" ["💌"])
+             (":ring:" ["💍"])
+             (":gem:" ["💎"])
+             (":couplekiss:" ["💏"])
+             (":bouquet:" ["💐"])
+             (":couple_with_heart:" ["💑"])
+             (":wedding:" ["💒"])
+             (":heartbeat:" ["💓"])
+             (":broken_heart:" ["💔"])
+             ("</3" ["💔"])
+             (":two_hearts:" ["💕"])
+             (":sparkling_heart:" ["💖"])
+             (":heartpulse:" ["💗"])
+             (":cupid:" ["💘"])
+             (":blue_heart:" ["💙"])
+             ("<3" ["💙"])
+             (":green_heart:" ["💚"])
+             ("<3" ["💚"])
+             (":yellow_heart:" ["💛"])
+             ("<3" ["💛"])
+             (":purple_heart:" ["💜"])
+             ("<3" ["💜"])
+             (":gift_heart:" ["💝"])
+             (":revolving_hearts:" ["💞"])
+             (":heart_decoration:" ["💟"])
+             (":diamond_shape_with_a_dot_inside:" ["💠"])
+             (":bulb:" ["💡"])
+             (":anger:" ["💢"])
+             (":bomb:" ["💣"])
+             (":zzz:" ["💤"])
+             (":boom:" ["💥"])
+             (":collision:" ["💥"])
+             (":sweat_drops:" ["💦"])
+             (":droplet:" ["💧"])
+             (":dash:" ["💨"])
+             (":hankey:" ["💩"])
+             (":poop:" ["💩"])
+             (":shit:" ["💩"])
+             (":muscle:" ["💪"])
+             (":dizzy:" ["💫"])
+             (":speech_balloon:" ["💬"])
+             (":thought_balloon:" ["💭"])
+             (":white_flower:" ["💮"])
+             (":100:" ["💯"])
+             (":moneybag:" ["💰"])
+             (":currency_exchange:" ["💱"])
+             (":heavy_dollar_sign:" ["💲"])
+             (":credit_card:" ["💳"])
+             (":yen:" ["💴"])
+             (":dollar:" ["💵"])
+             (":euro:" ["💶"])
+             (":pound:" ["💷"])
+             (":money_with_wings:" ["💸"])
+             (":chart:" ["💹"])
+             (":seat:" ["💺"])
+             (":computer:" ["💻"])
+             (":briefcase:" ["💼"])
+             (":minidisc:" ["💽"])
+             (":floppy_disk:" ["💾"])
+             (":cd:" ["💿"])
+             (":dvd:" ["📀"])
+             (":file_folder:" ["📁"])
+             (":open_file_folder:" ["📂"])
+             (":page_with_curl:" ["📃"])
+             (":page_facing_up:" ["📄"])
+             (":date:" ["📅"])
+             (":calendar:" ["📆"])
+             (":card_index:" ["📇"])
+             (":chart_with_upwards_trend:" ["📈"])
+             (":chart_with_downwards_trend:" ["📉"])
+             (":bar_chart:" ["📊"])
+             (":clipboard:" ["📋"])
+             (":pushpin:" ["📌"])
+             (":round_pushpin:" ["📍"])
+             (":paperclip:" ["📎"])
+             (":straight_ruler:" ["📏"])
+             (":triangular_ruler:" ["📐"])
+             (":bookmark_tabs:" ["📑"])
+             (":ledger:" ["📒"])
+             (":notebook:" ["📓"])
+             (":notebook_with_decorative_cover:" ["📔"])
+             (":closed_book:" ["📕"])
+             (":book:" ["📖"])
+             (":open_book:" ["📖"])
+             (":green_book:" ["📗"])
+             (":blue_book:" ["📘"])
+             (":orange_book:" ["📙"])
+             (":books:" ["📚"])
+             (":name_badge:" ["📛"])
+             (":scroll:" ["📜"])
+             (":memo:" ["📝"])
+             (":pencil:" ["📝"])
+             (":telephone_receiver:" ["📞"])
+             (":pager:" ["📟"])
+             (":fax:" ["📠"])
+             (":satellite_antenna:" ["📡"])
+             (":loudspeaker:" ["📢"])
+             (":mega:" ["📣"])
+             (":outbox_tray:" ["📤"])
+             (":inbox_tray:" ["📥"])
+             (":package:" ["📦"])
+             (":e-mail:" ["📧"])
+             (":incoming_envelope:" ["📨"])
+             (":envelope_with_arrow:" ["📩"])
+             (":mailbox_closed:" ["📪"])
+             (":mailbox:" ["📫"])
+             (":mailbox_with_mail:" ["📬"])
+             (":mailbox_with_no_mail:" ["📭"])
+             (":postbox:" ["📮"])
+             (":postal_horn:" ["📯"])
+             (":newspaper:" ["📰"])
+             (":iphone:" ["📱"])
+             (":calling:" ["📲"])
+             (":vibration_mode:" ["📳"])
+             (":mobile_phone_off:" ["📴"])
+             (":no_mobile_phones:" ["📵"])
+             (":signal_strength:" ["📶"])
+             (":camera:" ["📷"])
+             (":camera_with_flash:" ["📸"])
+             (":video_camera:" ["📹"])
+             (":tv:" ["📺"])
+             (":radio:" ["📻"])
+             (":vhs:" ["📼"])
+             (":film_projector:" ["📽️"])
+             (":prayer_beads:" ["📿"])
+             (":twisted_rightwards_arrows:" ["🔀"])
+             (":repeat:" ["🔁"])
+             (":repeat_one:" ["🔂"])
+             (":arrows_clockwise:" ["🔃"])
+             (":arrows_counterclockwise:" ["🔄"])
+             (":low_brightness:" ["🔅"])
+             (":high_brightness:" ["🔆"])
+             (":mute:" ["🔇"])
+             (":speaker:" ["🔈"])
+             (":sound:" ["🔉"])
+             (":loud_sound:" ["🔊"])
+             (":battery:" ["🔋"])
+             (":electric_plug:" ["🔌"])
+             (":mag:" ["🔍"])
+             (":mag_right:" ["🔎"])
+             (":lock_with_ink_pen:" ["🔏"])
+             (":closed_lock_with_key:" ["🔐"])
+             (":key:" ["🔑"])
+             (":lock:" ["🔒"])
+             (":unlock:" ["🔓"])
+             (":bell:" ["🔔"])
+             (":no_bell:" ["🔕"])
+             (":bookmark:" ["🔖"])
+             (":link:" ["🔗"])
+             (":radio_button:" ["🔘"])
+             (":back:" ["🔙"])
+             (":end:" ["🔚"])
+             (":on:" ["🔛"])
+             (":soon:" ["🔜"])
+             (":top:" ["🔝"])
+             (":underage:" ["🔞"])
+             (":keycap_ten:" ["🔟"])
+             (":capital_abcd:" ["🔠"])
+             (":abcd:" ["🔡"])
+             (":1234:" ["🔢"])
+             (":symbols:" ["🔣"])
+             (":abc:" ["🔤"])
+             (":fire:" ["🔥"])
+             (":flashlight:" ["🔦"])
+             (":wrench:" ["🔧"])
+             (":hammer:" ["🔨"])
+             (":nut_and_bolt:" ["🔩"])
+             (":hocho:" ["🔪"])
+             (":knife:" ["🔪"])
+             (":gun:" ["🔫"])
+             (":microscope:" ["🔬"])
+             (":telescope:" ["🔭"])
+             (":crystal_ball:" ["🔮"])
+             (":six_pointed_star:" ["🔯"])
+             (":beginner:" ["🔰"])
+             (":trident:" ["🔱"])
+             (":black_square_button:" ["🔲"])
+             (":white_square_button:" ["🔳"])
+             (":red_circle:" ["🔴"])
+             (":large_blue_circle:" ["🔵"])
+             (":large_orange_diamond:" ["🔶"])
+             (":large_blue_diamond:" ["🔷"])
+             (":small_orange_diamond:" ["🔸"])
+             (":small_blue_diamond:" ["🔹"])
+             (":small_red_triangle:" ["🔺"])
+             (":small_red_triangle_down:" ["🔻"])
+             (":arrow_up_small:" ["🔼"])
+             (":arrow_down_small:" ["🔽"])
+             (":om_symbol:" ["🕉️"])
+             (":dove_of_peace:" ["🕊️"])
+             (":kaaba:" ["🕋"])
+             (":mosque:" ["🕌"])
+             (":synagogue:" ["🕍"])
+             (":menorah_with_nine_branches:" ["🕎"])
+             (":clock1:" ["🕐"])
+             (":clock2:" ["🕑"])
+             (":clock3:" ["🕒"])
+             (":clock4:" ["🕓"])
+             (":clock5:" ["🕔"])
+             (":clock6:" ["🕕"])
+             (":clock7:" ["🕖"])
+             (":clock8:" ["🕗"])
+             (":clock9:" ["🕘"])
+             (":clock10:" ["🕙"])
+             (":clock11:" ["🕚"])
+             (":clock12:" ["🕛"])
+             (":clock130:" ["🕜"])
+             (":clock230:" ["🕝"])
+             (":clock330:" ["🕞"])
+             (":clock430:" ["🕟"])
+             (":clock530:" ["🕠"])
+             (":clock630:" ["🕡"])
+             (":clock730:" ["🕢"])
+             (":clock830:" ["🕣"])
+             (":clock930:" ["🕤"])
+             (":clock1030:" ["🕥"])
+             (":clock1130:" ["🕦"])
+             (":clock1230:" ["🕧"])
+             (":candle:" ["🕯️"])
+             (":mantelpiece_clock:" ["🕰️"])
+             (":hole:" ["🕳️"])
+             (":man_in_business_suit_levitating:" ["🕴️"])
+             (":female-detective:" ["🕵️‍♀️"])
+             (":male-detective:" ["🕵️‍♂️"])
+             (":sleuth_or_spy:" ["🕵️"])
+             (":dark_sunglasses:" ["🕶️"])
+             (":spider:" ["🕷️"])
+             (":spider_web:" ["🕸️"])
+             (":joystick:" ["🕹️"])
+             (":man_dancing:" ["🕺"])
+             (":linked_paperclips:" ["🖇️"])
+             (":lower_left_ballpoint_pen:" ["🖊️"])
+             (":lower_left_fountain_pen:" ["🖋️"])
+             (":lower_left_paintbrush:" ["🖌️"])
+             (":lower_left_crayon:" ["🖍️"])
+             (":raised_hand_with_fingers_splayed:" ["🖐️"])
+             (":middle_finger:" ["🖕"])
+             (":reversed_hand_with_middle_finger_extended:" ["🖕"])
+             (":spock-hand:" ["🖖"])
+             (":black_heart:" ["🖤"])
+             (":desktop_computer:" ["🖥️"])
+             (":printer:" ["🖨️"])
+             (":three_button_mouse:" ["🖱️"])
+             (":trackball:" ["🖲️"])
+             (":frame_with_picture:" ["🖼️"])
+             (":card_index_dividers:" ["🗂️"])
+             (":card_file_box:" ["🗃️"])
+             (":file_cabinet:" ["🗄️"])
+             (":wastebasket:" ["🗑️"])
+             (":spiral_note_pad:" ["🗒️"])
+             (":spiral_calendar_pad:" ["🗓️"])
+             (":compression:" ["🗜️"])
+             (":old_key:" ["🗝️"])
+             (":rolled_up_newspaper:" ["🗞️"])
+             (":dagger_knife:" ["🗡️"])
+             (":speaking_head_in_silhouette:" ["🗣️"])
+             (":left_speech_bubble:" ["🗨️"])
+             (":right_anger_bubble:" ["🗯️"])
+             (":ballot_box_with_ballot:" ["🗳️"])
+             (":world_map:" ["🗺️"])
+             (":mount_fuji:" ["🗻"])
+             (":tokyo_tower:" ["🗼"])
+             (":statue_of_liberty:" ["🗽"])
+             (":japan:" ["🗾"])
+             (":moyai:" ["🗿"])
+             (":grinning:" ["😀"])
+             (":D" ["😀"])
+             (":grin:" ["😁"])
+             (":joy:" ["😂"])
+             (":smiley:" ["😃"])
+             (":)" ["😃"])
+             ("=)" ["😃"])
+             ("=-)" ["😃"])
+             (":smile:" ["😄"])
+             (":)" ["😄"])
+             ("C:" ["😄"])
+             ("c:" ["😄"])
+             (":D" ["😄"])
+             (":-D" ["😄"])
+             (":sweat_smile:" ["😅"])
+             (":laughing:" ["😆"])
+             (":satisfied:" ["😆"])
+             (":>" ["😆"])
+             (":->" ["😆"])
+             (":innocent:" ["😇"])
+             (":smiling_imp:" ["😈"])
+             (":wink:" ["😉"])
+             (";)" ["😉"])
+             (";-)" ["😉"])
+             (":blush:" ["😊"])
+             (":)" ["😊"])
+             (":yum:" ["😋"])
+             (":relieved:" ["😌"])
+             (":heart_eyes:" ["😍"])
+             (":sunglasses:" ["😎"])
+             ("8)" ["😎"])
+             (":smirk:" ["😏"])
+             (":neutral_face:" ["😐"])
+             (":|" ["😐"])
+             (":-|" ["😐"])
+             (":expressionless:" ["😑"])
+             (":unamused:" ["😒"])
+             (":(" ["😒"])
+             (":sweat:" ["😓"])
+             (":pensive:" ["😔"])
+             (":confused:" ["😕"])
+             (":\\" ["😕"])
+             (":-\\" ["😕"])
+             (":/" ["😕"])
+             (":-/" ["😕"])
+             (":confounded:" ["😖"])
+             (":kissing:" ["😗"])
+             (":kissing_heart:" ["😘"])
+             (":*" ["😘"])
+             (":-*" ["😘"])
+             (":kissing_smiling_eyes:" ["😙"])
+             (":kissing_closed_eyes:" ["😚"])
+             (":stuck_out_tongue:" ["😛"])
+             (":p" ["😛"])
+             (":-p" ["😛"])
+             (":P" ["😛"])
+             (":-P" ["😛"])
+             (":b" ["😛"])
+             (":-b" ["😛"])
+             (":stuck_out_tongue_winking_eye:" ["😜"])
+             (";p" ["😜"])
+             (";-p" ["😜"])
+             (";b" ["😜"])
+             (";-b" ["😜"])
+             (";P" ["😜"])
+             (";-P" ["😜"])
+             (":stuck_out_tongue_closed_eyes:" ["😝"])
+             (":disappointed:" ["😞"])
+             (":(" ["😞"])
+             ("):" ["😞"])
+             (":-(" ["😞"])
+             (":worried:" ["😟"])
+             (":angry:" ["😠"])
+             (">:(" ["😠"])
+             (">:-(" ["😠"])
+             (":rage:" ["😡"])
+             (":cry:" ["😢"])
+             (":'(" ["😢"])
+             (":persevere:" ["😣"])
+             (":triumph:" ["😤"])
+             (":disappointed_relieved:" ["😥"])
+             (":frowning:" ["😦"])
+             (":anguished:" ["😧"])
+             ("D:" ["😧"])
+             (":fearful:" ["😨"])
+             (":weary:" ["😩"])
+             (":sleepy:" ["😪"])
+             (":tired_face:" ["😫"])
+             (":grimacing:" ["😬"])
+             (":sob:" ["😭"])
+             (":'(" ["😭"])
+             (":face_exhaling:" ["😮‍💨"])
+             (":open_mouth:" ["😮"])
+             (":o" ["😮"])
+             (":-o" ["😮"])
+             (":O" ["😮"])
+             (":-O" ["😮"])
+             (":hushed:" ["😯"])
+             (":cold_sweat:" ["😰"])
+             (":scream:" ["😱"])
+             (":astonished:" ["😲"])
+             (":flushed:" ["😳"])
+             (":sleeping:" ["😴"])
+             (":face_with_spiral_eyes:" ["😵‍💫"])
+             (":dizzy_face:" ["😵"])
+             (":face_in_clouds:" ["😶‍🌫️"])
+             (":no_mouth:" ["😶"])
+             (":mask:" ["😷"])
+             (":smile_cat:" ["😸"])
+             (":joy_cat:" ["😹"])
+             (":smiley_cat:" ["😺"])
+             (":heart_eyes_cat:" ["😻"])
+             (":smirk_cat:" ["😼"])
+             (":kissing_cat:" ["😽"])
+             (":pouting_cat:" ["😾"])
+             (":crying_cat_face:" ["😿"])
+             (":scream_cat:" ["🙀"])
+             (":slightly_frowning_face:" ["🙁"])
+             (":slightly_smiling_face:" ["🙂"])
+             (":)" ["🙂"])
+             ("(:" ["🙂"])
+             (":-)" ["🙂"])
+             (":upside_down_face:" ["🙃"])
+             (":face_with_rolling_eyes:" ["🙄"])
+             (":woman-gesturing-no:" ["🙅‍♀️"])
+             (":man-gesturing-no:" ["🙅‍♂️"])
+             (":no_good:" ["🙅"])
+             (":woman-gesturing-ok:" ["🙆‍♀️"])
+             (":man-gesturing-ok:" ["🙆‍♂️"])
+             (":ok_woman:" ["🙆"])
+             (":woman-bowing:" ["🙇‍♀️"])
+             (":man-bowing:" ["🙇‍♂️"])
+             (":bow:" ["🙇"])
+             (":see_no_evil:" ["🙈"])
+             (":hear_no_evil:" ["🙉"])
+             (":speak_no_evil:" ["🙊"])
+             (":woman-raising-hand:" ["🙋‍♀️"])
+             (":man-raising-hand:" ["🙋‍♂️"])
+             (":raising_hand:" ["🙋"])
+             (":raised_hands:" ["🙌"])
+             (":woman-frowning:" ["🙍‍♀️"])
+             (":man-frowning:" ["🙍‍♂️"])
+             (":person_frowning:" ["🙍"])
+             (":woman-pouting:" ["🙎‍♀️"])
+             (":man-pouting:" ["🙎‍♂️"])
+             (":person_with_pouting_face:" ["🙎"])
+             (":pray:" ["🙏"])
+             (":rocket:" ["🚀"])
+             (":helicopter:" ["🚁"])
+             (":steam_locomotive:" ["🚂"])
+             (":railway_car:" ["🚃"])
+             (":bullettrain_side:" ["🚄"])
+             (":bullettrain_front:" ["🚅"])
+             (":train2:" ["🚆"])
+             (":metro:" ["🚇"])
+             (":light_rail:" ["🚈"])
+             (":station:" ["🚉"])
+             (":tram:" ["🚊"])
+             (":train:" ["🚋"])
+             (":bus:" ["🚌"])
+             (":oncoming_bus:" ["🚍"])
+             (":trolleybus:" ["🚎"])
+             (":busstop:" ["🚏"])
+             (":minibus:" ["🚐"])
+             (":ambulance:" ["🚑"])
+             (":fire_engine:" ["🚒"])
+             (":police_car:" ["🚓"])
+             (":oncoming_police_car:" ["🚔"])
+             (":taxi:" ["🚕"])
+             (":oncoming_taxi:" ["🚖"])
+             (":car:" ["🚗"])
+             (":red_car:" ["🚗"])
+             (":oncoming_automobile:" ["🚘"])
+             (":blue_car:" ["🚙"])
+             (":truck:" ["🚚"])
+             (":articulated_lorry:" ["🚛"])
+             (":tractor:" ["🚜"])
+             (":monorail:" ["🚝"])
+             (":mountain_railway:" ["🚞"])
+             (":suspension_railway:" ["🚟"])
+             (":mountain_cableway:" ["🚠"])
+             (":aerial_tramway:" ["🚡"])
+             (":ship:" ["🚢"])
+             (":woman-rowing-boat:" ["🚣‍♀️"])
+             (":man-rowing-boat:" ["🚣‍♂️"])
+             (":rowboat:" ["🚣"])
+             (":speedboat:" ["🚤"])
+             (":traffic_light:" ["🚥"])
+             (":vertical_traffic_light:" ["🚦"])
+             (":construction:" ["🚧"])
+             (":rotating_light:" ["🚨"])
+             (":triangular_flag_on_post:" ["🚩"])
+             (":door:" ["🚪"])
+             (":no_entry_sign:" ["🚫"])
+             (":smoking:" ["🚬"])
+             (":no_smoking:" ["🚭"])
+             (":put_litter_in_its_place:" ["🚮"])
+             (":do_not_litter:" ["🚯"])
+             (":potable_water:" ["🚰"])
+             (":non-potable_water:" ["🚱"])
+             (":bike:" ["🚲"])
+             (":no_bicycles:" ["🚳"])
+             (":woman-biking:" ["🚴‍♀️"])
+             (":man-biking:" ["🚴‍♂️"])
+             (":bicyclist:" ["🚴"])
+             (":woman-mountain-biking:" ["🚵‍♀️"])
+             (":man-mountain-biking:" ["🚵‍♂️"])
+             (":mountain_bicyclist:" ["🚵"])
+             (":woman-walking:" ["🚶‍♀️"])
+             (":man-walking:" ["🚶‍♂️"])
+             (":walking:" ["🚶"])
+             (":no_pedestrians:" ["🚷"])
+             (":children_crossing:" ["🚸"])
+             (":mens:" ["🚹"])
+             (":womens:" ["🚺"])
+             (":restroom:" ["🚻"])
+             (":baby_symbol:" ["🚼"])
+             (":toilet:" ["🚽"])
+             (":wc:" ["🚾"])
+             (":shower:" ["🚿"])
+             (":bath:" ["🛀"])
+             (":bathtub:" ["🛁"])
+             (":passport_control:" ["🛂"])
+             (":customs:" ["🛃"])
+             (":baggage_claim:" ["🛄"])
+             (":left_luggage:" ["🛅"])
+             (":couch_and_lamp:" ["🛋️"])
+             (":sleeping_accommodation:" ["🛌"])
+             (":shopping_bags:" ["🛍️"])
+             (":bellhop_bell:" ["🛎️"])
+             (":bed:" ["🛏️"])
+             (":place_of_worship:" ["🛐"])
+             (":octagonal_sign:" ["🛑"])
+             (":shopping_trolley:" ["🛒"])
+             (":hindu_temple:" ["🛕"])
+             (":hut:" ["🛖"])
+             (":elevator:" ["🛗"])
+             (":hammer_and_wrench:" ["🛠️"])
+             (":shield:" ["🛡️"])
+             (":oil_drum:" ["🛢️"])
+             (":motorway:" ["🛣️"])
+             (":railway_track:" ["🛤️"])
+             (":motor_boat:" ["🛥️"])
+             (":small_airplane:" ["🛩️"])
+             (":airplane_departure:" ["🛫"])
+             (":airplane_arriving:" ["🛬"])
+             (":satellite:" ["🛰️"])
+             (":passenger_ship:" ["🛳️"])
+             (":scooter:" ["🛴"])
+             (":motor_scooter:" ["🛵"])
+             (":canoe:" ["🛶"])
+             (":sled:" ["🛷"])
+             (":flying_saucer:" ["🛸"])
+             (":skateboard:" ["🛹"])
+             (":auto_rickshaw:" ["🛺"])
+             (":pickup_truck:" ["🛻"])
+             (":roller_skate:" ["🛼"])
+             (":large_orange_circle:" ["🟠"])
+             (":large_yellow_circle:" ["🟡"])
+             (":large_green_circle:" ["🟢"])
+             (":large_purple_circle:" ["🟣"])
+             (":large_brown_circle:" ["🟤"])
+             (":large_red_square:" ["🟥"])
+             (":large_blue_square:" ["🟦"])
+             (":large_orange_square:" ["🟧"])
+             (":large_yellow_square:" ["🟨"])
+             (":large_green_square:" ["🟩"])
+             (":large_purple_square:" ["🟪"])
+             (":large_brown_square:" ["🟫"])
+             (":pinched_fingers:" ["🤌"])
+             (":white_heart:" ["🤍"])
+             (":brown_heart:" ["🤎"])
+             (":pinching_hand:" ["🤏"])
+             (":zipper_mouth_face:" ["🤐"])
+             (":money_mouth_face:" ["🤑"])
+             (":face_with_thermometer:" ["🤒"])
+             (":nerd_face:" ["🤓"])
+             (":thinking_face:" ["🤔"])
+             (":face_with_head_bandage:" ["🤕"])
+             (":robot_face:" ["🤖"])
+             (":hugging_face:" ["🤗"])
+             (":the_horns:" ["🤘"])
+             (":sign_of_the_horns:" ["🤘"])
+             (":call_me_hand:" ["🤙"])
+             (":raised_back_of_hand:" ["🤚"])
+             (":left-facing_fist:" ["🤛"])
+             (":right-facing_fist:" ["🤜"])
+             (":handshake:" ["🤝"])
+             (":crossed_fingers:" ["🤞"])
+             (":hand_with_index_and_middle_fingers_crossed:" ["🤞"])
+             (":i_love_you_hand_sign:" ["🤟"])
+             (":face_with_cowboy_hat:" ["🤠"])
+             (":clown_face:" ["🤡"])
+             (":nauseated_face:" ["🤢"])
+             (":rolling_on_the_floor_laughing:" ["🤣"])
+             (":drooling_face:" ["🤤"])
+             (":lying_face:" ["🤥"])
+             (":woman-facepalming:" ["🤦‍♀️"])
+             (":man-facepalming:" ["🤦‍♂️"])
+             (":face_palm:" ["🤦"])
+             (":sneezing_face:" ["🤧"])
+             (":face_with_raised_eyebrow:" ["🤨"])
+             (":face_with_one_eyebrow_raised:" ["🤨"])
+             (":star-struck:" ["🤩"])
+             (":grinning_face_with_star_eyes:" ["🤩"])
+             (":zany_face:" ["🤪"])
+             (":grinning_face_with_one_large_and_one_small_eye:" ["🤪"])
+             (":shushing_face:" ["🤫"])
+             (":face_with_finger_covering_closed_lips:" ["🤫"])
+             (":face_with_symbols_on_mouth:" ["🤬"])
+             (":serious_face_with_symbols_covering_mouth:" ["🤬"])
+             (":face_with_hand_over_mouth:" ["🤭"])
+             (":smiling_face_with_smiling_eyes_and_hand_covering_mouth:" ["🤭"])
+             (":face_vomiting:" ["🤮"])
+             (":face_with_open_mouth_vomiting:" ["🤮"])
+             (":exploding_head:" ["🤯"])
+             (":shocked_face_with_exploding_head:" ["🤯"])
+             (":pregnant_woman:" ["🤰"])
+             (":breast-feeding:" ["🤱"])
+             (":palms_up_together:" ["🤲"])
+             (":selfie:" ["🤳"])
+             (":prince:" ["🤴"])
+             (":woman_in_tuxedo:" ["🤵‍♀️"])
+             (":man_in_tuxedo:" ["🤵‍♂️"])
+             (":person_in_tuxedo:" ["🤵"])
+             (":mrs_claus:" ["🤶"])
+             (":mother_christmas:" ["🤶"])
+             (":woman-shrugging:" ["🤷‍♀️"])
+             (":man-shrugging:" ["🤷‍♂️"])
+             (":shrug:" ["🤷"])
+             (":woman-cartwheeling:" ["🤸‍♀️"])
+             (":man-cartwheeling:" ["🤸‍♂️"])
+             (":person_doing_cartwheel:" ["🤸"])
+             (":woman-juggling:" ["🤹‍♀️"])
+             (":man-juggling:" ["🤹‍♂️"])
+             (":juggling:" ["🤹"])
+             (":fencer:" ["🤺"])
+             (":woman-wrestling:" ["🤼‍♀️"])
+             (":man-wrestling:" ["🤼‍♂️"])
+             (":wrestlers:" ["🤼"])
+             (":woman-playing-water-polo:" ["🤽‍♀️"])
+             (":man-playing-water-polo:" ["🤽‍♂️"])
+             (":water_polo:" ["🤽"])
+             (":woman-playing-handball:" ["🤾‍♀️"])
+             (":man-playing-handball:" ["🤾‍♂️"])
+             (":handball:" ["🤾"])
+             (":diving_mask:" ["🤿"])
+             (":wilted_flower:" ["🥀"])
+             (":drum_with_drumsticks:" ["🥁"])
+             (":clinking_glasses:" ["🥂"])
+             (":tumbler_glass:" ["🥃"])
+             (":spoon:" ["🥄"])
+             (":goal_net:" ["🥅"])
+             (":first_place_medal:" ["🥇"])
+             (":second_place_medal:" ["🥈"])
+             (":third_place_medal:" ["🥉"])
+             (":boxing_glove:" ["🥊"])
+             (":martial_arts_uniform:" ["🥋"])
+             (":curling_stone:" ["🥌"])
+             (":lacrosse:" ["🥍"])
+             (":softball:" ["🥎"])
+             (":flying_disc:" ["🥏"])
+             (":croissant:" ["🥐"])
+             (":avocado:" ["🥑"])
+             (":cucumber:" ["🥒"])
+             (":bacon:" ["🥓"])
+             (":potato:" ["🥔"])
+             (":carrot:" ["🥕"])
+             (":baguette_bread:" ["🥖"])
+             (":green_salad:" ["🥗"])
+             (":shallow_pan_of_food:" ["🥘"])
+             (":stuffed_flatbread:" ["🥙"])
+             (":egg:" ["🥚"])
+             (":glass_of_milk:" ["🥛"])
+             (":peanuts:" ["🥜"])
+             (":kiwifruit:" ["🥝"])
+             (":pancakes:" ["🥞"])
+             (":dumpling:" ["🥟"])
+             (":fortune_cookie:" ["🥠"])
+             (":takeout_box:" ["🥡"])
+             (":chopsticks:" ["🥢"])
+             (":bowl_with_spoon:" ["🥣"])
+             (":cup_with_straw:" ["🥤"])
+             (":coconut:" ["🥥"])
+             (":broccoli:" ["🥦"])
+             (":pie:" ["🥧"])
+             (":pretzel:" ["🥨"])
+             (":cut_of_meat:" ["🥩"])
+             (":sandwich:" ["🥪"])
+             (":canned_food:" ["🥫"])
+             (":leafy_green:" ["🥬"])
+             (":mango:" ["🥭"])
+             (":moon_cake:" ["🥮"])
+             (":bagel:" ["🥯"])
+             (":smiling_face_with_3_hearts:" ["🥰"])
+             (":yawning_face:" ["🥱"])
+             (":smiling_face_with_tear:" ["🥲"])
+             (":partying_face:" ["🥳"])
+             (":woozy_face:" ["🥴"])
+             (":hot_face:" ["🥵"])
+             (":cold_face:" ["🥶"])
+             (":ninja:" ["🥷"])
+             (":disguised_face:" ["🥸"])
+             (":pleading_face:" ["🥺"])
+             (":sari:" ["🥻"])
+             (":lab_coat:" ["🥼"])
+             (":goggles:" ["🥽"])
+             (":hiking_boot:" ["🥾"])
+             (":womans_flat_shoe:" ["🥿"])
+             (":crab:" ["🦀"])
+             (":lion_face:" ["🦁"])
+             (":scorpion:" ["🦂"])
+             (":turkey:" ["🦃"])
+             (":unicorn_face:" ["🦄"])
+             (":eagle:" ["🦅"])
+             (":duck:" ["🦆"])
+             (":bat:" ["🦇"])
+             (":shark:" ["🦈"])
+             (":owl:" ["🦉"])
+             (":fox_face:" ["🦊"])
+             (":butterfly:" ["🦋"])
+             (":deer:" ["🦌"])
+             (":gorilla:" ["🦍"])
+             (":lizard:" ["🦎"])
+             (":rhinoceros:" ["🦏"])
+             (":shrimp:" ["🦐"])
+             (":squid:" ["🦑"])
+             (":giraffe_face:" ["🦒"])
+             (":zebra_face:" ["🦓"])
+             (":hedgehog:" ["🦔"])
+             (":sauropod:" ["🦕"])
+             (":t-rex:" ["🦖"])
+             (":cricket:" ["🦗"])
+             (":kangaroo:" ["🦘"])
+             (":llama:" ["🦙"])
+             (":peacock:" ["🦚"])
+             (":hippopotamus:" ["🦛"])
+             (":parrot:" ["🦜"])
+             (":raccoon:" ["🦝"])
+             (":lobster:" ["🦞"])
+             (":mosquito:" ["🦟"])
+             (":microbe:" ["🦠"])
+             (":badger:" ["🦡"])
+             (":swan:" ["🦢"])
+             (":mammoth:" ["🦣"])
+             (":dodo:" ["🦤"])
+             (":sloth:" ["🦥"])
+             (":otter:" ["🦦"])
+             (":orangutan:" ["🦧"])
+             (":skunk:" ["🦨"])
+             (":flamingo:" ["🦩"])
+             (":oyster:" ["🦪"])
+             (":beaver:" ["🦫"])
+             (":bison:" ["🦬"])
+             (":seal:" ["🦭"])
+             (":guide_dog:" ["🦮"])
+             (":probing_cane:" ["🦯"])
+             (":bone:" ["🦴"])
+             (":leg:" ["🦵"])
+             (":foot:" ["🦶"])
+             (":tooth:" ["🦷"])
+             (":female_superhero:" ["🦸‍♀️"])
+             (":male_superhero:" ["🦸‍♂️"])
+             (":superhero:" ["🦸"])
+             (":female_supervillain:" ["🦹‍♀️"])
+             (":male_supervillain:" ["🦹‍♂️"])
+             (":supervillain:" ["🦹"])
+             (":safety_vest:" ["🦺"])
+             (":ear_with_hearing_aid:" ["🦻"])
+             (":motorized_wheelchair:" ["🦼"])
+             (":manual_wheelchair:" ["🦽"])
+             (":mechanical_arm:" ["🦾"])
+             (":mechanical_leg:" ["🦿"])
+             (":cheese_wedge:" ["🧀"])
+             (":cupcake:" ["🧁"])
+             (":salt:" ["🧂"])
+             (":beverage_box:" ["🧃"])
+             (":garlic:" ["🧄"])
+             (":onion:" ["🧅"])
+             (":falafel:" ["🧆"])
+             (":waffle:" ["🧇"])
+             (":butter:" ["🧈"])
+             (":mate_drink:" ["🧉"])
+             (":ice_cube:" ["🧊"])
+             (":bubble_tea:" ["🧋"])
+             (":woman_standing:" ["🧍‍♀️"])
+             (":man_standing:" ["🧍‍♂️"])
+             (":standing_person:" ["🧍"])
+             (":woman_kneeling:" ["🧎‍♀️"])
+             (":man_kneeling:" ["🧎‍♂️"])
+             (":kneeling_person:" ["🧎"])
+             (":deaf_woman:" ["🧏‍♀️"])
+             (":deaf_man:" ["🧏‍♂️"])
+             (":deaf_person:" ["🧏"])
+             (":face_with_monocle:" ["🧐"])
+             (":farmer:" ["🧑‍🌾"])
+             (":cook:" ["🧑‍🍳"])
+             (":person_feeding_baby:" ["🧑‍🍼"])
+             (":mx_claus:" ["🧑‍🎄"])
+             (":student:" ["🧑‍🎓"])
+             (":singer:" ["🧑‍🎤"])
+             (":artist:" ["🧑‍🎨"])
+             (":teacher:" ["🧑‍🏫"])
+             (":factory_worker:" ["🧑‍🏭"])
+             (":technologist:" ["🧑‍💻"])
+             (":office_worker:" ["🧑‍💼"])
+             (":mechanic:" ["🧑‍🔧"])
+             (":scientist:" ["🧑‍🔬"])
+             (":astronaut:" ["🧑‍🚀"])
+             (":firefighter:" ["🧑‍🚒"])
+             (":people_holding_hands:" ["🧑‍🤝‍🧑"])
+             (":person_with_probing_cane:" ["🧑‍🦯"])
+             (":red_haired_person:" ["🧑‍🦰"])
+             (":curly_haired_person:" ["🧑‍🦱"])
+             (":bald_person:" ["🧑‍🦲"])
+             (":white_haired_person:" ["🧑‍🦳"])
+             (":person_in_motorized_wheelchair:" ["🧑‍🦼"])
+             (":person_in_manual_wheelchair:" ["🧑‍🦽"])
+             (":health_worker:" ["🧑‍⚕️"])
+             (":judge:" ["🧑‍⚖️"])
+             (":pilot:" ["🧑‍✈️"])
+             (":adult:" ["🧑"])
+             (":child:" ["🧒"])
+             (":older_adult:" ["🧓"])
+             (":woman_with_beard:" ["🧔‍♀️"])
+             (":man_with_beard:" ["🧔‍♂️"])
+             (":bearded_person:" ["🧔"])
+             (":person_with_headscarf:" ["🧕"])
+             (":woman_in_steamy_room:" ["🧖‍♀️"])
+             (":man_in_steamy_room:" ["🧖‍♂️"])
+             (":person_in_steamy_room:" ["🧖"])
+             (":woman_climbing:" ["🧗‍♀️"])
+             (":man_climbing:" ["🧗‍♂️"])
+             (":person_climbing:" ["🧗"])
+             (":woman_in_lotus_position:" ["🧘‍♀️"])
+             (":man_in_lotus_position:" ["🧘‍♂️"])
+             (":person_in_lotus_position:" ["🧘"])
+             (":female_mage:" ["🧙‍♀️"])
+             (":male_mage:" ["🧙‍♂️"])
+             (":mage:" ["🧙"])
+             (":female_fairy:" ["🧚‍♀️"])
+             (":male_fairy:" ["🧚‍♂️"])
+             (":fairy:" ["🧚"])
+             (":female_vampire:" ["🧛‍♀️"])
+             (":male_vampire:" ["🧛‍♂️"])
+             (":vampire:" ["🧛"])
+             (":mermaid:" ["🧜‍♀️"])
+             (":merman:" ["🧜‍♂️"])
+             (":merperson:" ["🧜"])
+             (":female_elf:" ["🧝‍♀️"])
+             (":male_elf:" ["🧝‍♂️"])
+             (":elf:" ["🧝"])
+             (":female_genie:" ["🧞‍♀️"])
+             (":male_genie:" ["🧞‍♂️"])
+             (":genie:" ["🧞"])
+             (":female_zombie:" ["🧟‍♀️"])
+             (":male_zombie:" ["🧟‍♂️"])
+             (":zombie:" ["🧟"])
+             (":brain:" ["🧠"])
+             (":orange_heart:" ["🧡"])
+             (":billed_cap:" ["🧢"])
+             (":scarf:" ["🧣"])
+             (":gloves:" ["🧤"])
+             (":coat:" ["🧥"])
+             (":socks:" ["🧦"])
+             (":red_envelope:" ["🧧"])
+             (":firecracker:" ["🧨"])
+             (":jigsaw:" ["🧩"])
+             (":test_tube:" ["🧪"])
+             (":petri_dish:" ["🧫"])
+             (":dna:" ["🧬"])
+             (":compass:" ["🧭"])
+             (":abacus:" ["🧮"])
+             (":fire_extinguisher:" ["🧯"])
+             (":toolbox:" ["🧰"])
+             (":bricks:" ["🧱"])
+             (":magnet:" ["🧲"])
+             (":luggage:" ["🧳"])
+             (":lotion_bottle:" ["🧴"])
+             (":thread:" ["🧵"])
+             (":yarn:" ["🧶"])
+             (":safety_pin:" ["🧷"])
+             (":teddy_bear:" ["🧸"])
+             (":broom:" ["🧹"])
+             (":basket:" ["🧺"])
+             (":roll_of_paper:" ["🧻"])
+             (":soap:" ["🧼"])
+             (":sponge:" ["🧽"])
+             (":receipt:" ["🧾"])
+             (":nazar_amulet:" ["🧿"])
+             (":ballet_shoes:" ["🩰"])
+             (":one-piece_swimsuit:" ["🩱"])
+             (":briefs:" ["🩲"])
+             (":shorts:" ["🩳"])
+             (":thong_sandal:" ["🩴"])
+             (":drop_of_blood:" ["🩸"])
+             (":adhesive_bandage:" ["🩹"])
+             (":stethoscope:" ["🩺"])
+             (":yo-yo:" ["🪀"])
+             (":kite:" ["🪁"])
+             (":parachute:" ["🪂"])
+             (":boomerang:" ["🪃"])
+             (":magic_wand:" ["🪄"])
+             (":pinata:" ["🪅"])
+             (":nesting_dolls:" ["🪆"])
+             (":ringed_planet:" ["🪐"])
+             (":chair:" ["🪑"])
+             (":razor:" ["🪒"])
+             (":axe:" ["🪓"])
+             (":diya_lamp:" ["🪔"])
+             (":banjo:" ["🪕"])
+             (":military_helmet:" ["🪖"])
+             (":accordion:" ["🪗"])
+             (":long_drum:" ["🪘"])
+             (":coin:" ["🪙"])
+             (":carpentry_saw:" ["🪚"])
+             (":screwdriver:" ["🪛"])
+             (":ladder:" ["🪜"])
+             (":hook:" ["🪝"])
+             (":mirror:" ["🪞"])
+             (":window:" ["🪟"])
+             (":plunger:" ["🪠"])
+             (":sewing_needle:" ["🪡"])
+             (":knot:" ["🪢"])
+             (":bucket:" ["🪣"])
+             (":mouse_trap:" ["🪤"])
+             (":toothbrush:" ["🪥"])
+             (":headstone:" ["🪦"])
+             (":placard:" ["🪧"])
+             (":rock:" ["🪨"])
+             (":fly:" ["🪰"])
+             (":worm:" ["🪱"])
+             (":beetle:" ["🪲"])
+             (":cockroach:" ["🪳"])
+             (":potted_plant:" ["🪴"])
+             (":wood:" ["🪵"])
+             (":feather:" ["🪶"])
+             (":anatomical_heart:" ["🫀"])
+             (":lungs:" ["🫁"])
+             (":people_hugging:" ["🫂"])
+             (":blueberries:" ["🫐"])
+             (":bell_pepper:" ["🫑"])
+             (":olive:" ["🫒"])
+             (":flatbread:" ["🫓"])
+             (":tamale:" ["🫔"])
+             (":fondue:" ["🫕"])
+             (":teapot:" ["🫖"])
+             (":bangbang:" ["‼️"])
+             (":interrobang:" ["⁉️"])
+             (":tm:" ["™️"])
+             (":information_source:" ["ℹ️"])
+             (":left_right_arrow:" ["↔️"])
+             (":arrow_up_down:" ["↕️"])
+             (":arrow_upper_left:" ["↖️"])
+             (":arrow_upper_right:" ["↗️"])
+             (":arrow_lower_right:" ["↘️"])
+             (":arrow_lower_left:" ["↙️"])
+             (":leftwards_arrow_with_hook:" ["↩️"])
+             (":arrow_right_hook:" ["↪️"])
+             (":watch:" ["⌚"])
+             (":hourglass:" ["⌛"])
+             (":keyboard:" ["⌨️"])
+             (":eject:" ["⏏️"])
+             (":fast_forward:" ["⏩"])
+             (":rewind:" ["⏪"])
+             (":arrow_double_up:" ["⏫"])
+             (":arrow_double_down:" ["⏬"])
+             (":black_right_pointing_double_triangle_with_vertical_bar:" 
["⏭️"])
+             (":black_left_pointing_double_triangle_with_vertical_bar:" ["⏮️"])
+             (":black_right_pointing_triangle_with_double_vertical_bar:" 
["⏯️"])
+             (":alarm_clock:" ["⏰"])
+             (":stopwatch:" ["⏱️"])
+             (":timer_clock:" ["⏲️"])
+             (":hourglass_flowing_sand:" ["⏳"])
+             (":double_vertical_bar:" ["⏸️"])
+             (":black_square_for_stop:" ["⏹️"])
+             (":black_circle_for_record:" ["⏺️"])
+             (":m:" ["Ⓜ️"])
+             (":black_small_square:" ["▪️"])
+             (":white_small_square:" ["▫️"])
+             (":arrow_forward:" ["▶️"])
+             (":arrow_backward:" ["◀️"])
+             (":white_medium_square:" ["◻️"])
+             (":black_medium_square:" ["◼️"])
+             (":white_medium_small_square:" ["◽"])
+             (":black_medium_small_square:" ["◾"])
+             (":sunny:" ["☀️"])
+             (":cloud:" ["☁️"])
+             (":umbrella:" ["☂️"])
+             (":snowman:" ["☃️"])
+             (":comet:" ["☄️"])
+             (":phone:" ["☎️"])
+             (":telephone:" ["☎️"])
+             (":ballot_box_with_check:" ["☑️"])
+             (":umbrella_with_rain_drops:" ["☔"])
+             (":coffee:" ["☕"])
+             (":shamrock:" ["☘️"])
+             (":point_up:" ["☝️"])
+             (":skull_and_crossbones:" ["☠️"])
+             (":radioactive_sign:" ["☢️"])
+             (":biohazard_sign:" ["☣️"])
+             (":orthodox_cross:" ["☦️"])
+             (":star_and_crescent:" ["☪️"])
+             (":peace_symbol:" ["☮️"])
+             (":yin_yang:" ["☯️"])
+             (":wheel_of_dharma:" ["☸️"])
+             (":white_frowning_face:" ["☹️"])
+             (":relaxed:" ["☺️"])
+             (":female_sign:" ["♀️"])
+             (":male_sign:" ["♂️"])
+             (":aries:" ["♈"])
+             (":taurus:" ["♉"])
+             (":gemini:" ["♊"])
+             (":cancer:" ["♋"])
+             (":leo:" ["♌"])
+             (":virgo:" ["♍"])
+             (":libra:" ["♎"])
+             (":scorpius:" ["♏"])
+             (":sagittarius:" ["♐"])
+             (":capricorn:" ["♑"])
+             (":aquarius:" ["♒"])
+             (":pisces:" ["♓"])
+             (":chess_pawn:" ["♟️"])
+             (":spades:" ["♠️"])
+             (":clubs:" ["♣️"])
+             (":hearts:" ["♥️"])
+             (":diamonds:" ["♦️"])
+             (":hotsprings:" ["♨️"])
+             (":recycle:" ["♻️"])
+             (":infinity:" ["♾️"])
+             (":wheelchair:" ["♿"])
+             (":hammer_and_pick:" ["⚒️"])
+             (":anchor:" ["⚓"])
+             (":crossed_swords:" ["⚔️"])
+             (":medical_symbol:" ["⚕️"])
+             (":staff_of_aesculapius:" ["⚕️"])
+             (":scales:" ["⚖️"])
+             (":alembic:" ["⚗️"])
+             (":gear:" ["⚙️"])
+             (":atom_symbol:" ["⚛️"])
+             (":fleur_de_lis:" ["⚜️"])
+             (":warning:" ["⚠️"])
+             (":zap:" ["⚡"])
+             (":transgender_symbol:" ["⚧️"])
+             (":white_circle:" ["⚪"])
+             (":black_circle:" ["⚫"])
+             (":coffin:" ["⚰️"])
+             (":funeral_urn:" ["⚱️"])
+             (":soccer:" ["⚽"])
+             (":baseball:" ["⚾"])
+             (":snowman_without_snow:" ["⛄"])
+             (":partly_sunny:" ["⛅"])
+             (":thunder_cloud_and_rain:" ["⛈️"])
+             (":ophiuchus:" ["⛎"])
+             (":pick:" ["⛏️"])
+             (":helmet_with_white_cross:" ["⛑️"])
+             (":chains:" ["⛓️"])
+             (":no_entry:" ["⛔"])
+             (":shinto_shrine:" ["⛩️"])
+             (":church:" ["⛪"])
+             (":mountain:" ["⛰️"])
+             (":umbrella_on_ground:" ["⛱️"])
+             (":fountain:" ["⛲"])
+             (":golf:" ["⛳"])
+             (":ferry:" ["⛴️"])
+             (":boat:" ["⛵"])
+             (":sailboat:" ["⛵"])
+             (":skier:" ["⛷️"])
+             (":ice_skate:" ["⛸️"])
+             (":woman-bouncing-ball:" ["⛹️‍♀️"])
+             (":man-bouncing-ball:" ["⛹️‍♂️"])
+             (":person_with_ball:" ["⛹️"])
+             (":tent:" ["⛺"])
+             (":fuelpump:" ["⛽"])
+             (":scissors:" ["✂️"])
+             (":white_check_mark:" ["✅"])
+             (":airplane:" ["✈️"])
+             (":email:" ["✉️"])
+             (":envelope:" ["✉️"])
+             (":fist:" ["✊"])
+             (":hand:" ["✋"])
+             (":raised_hand:" ["✋"])
+             (":v:" ["✌️"])
+             (":writing_hand:" ["✍️"])
+             (":pencil2:" ["✏️"])
+             (":black_nib:" ["✒️"])
+             (":heavy_check_mark:" ["✔️"])
+             (":heavy_multiplication_x:" ["✖️"])
+             (":latin_cross:" ["✝️"])
+             (":star_of_david:" ["✡️"])
+             (":sparkles:" ["✨"])
+             (":eight_spoked_asterisk:" ["✳️"])
+             (":eight_pointed_black_star:" ["✴️"])
+             (":snowflake:" ["❄️"])
+             (":sparkle:" ["❇️"])
+             (":x:" ["❌"])
+             (":negative_squared_cross_mark:" ["❎"])
+             (":question:" ["❓"])
+             (":grey_question:" ["❔"])
+             (":grey_exclamation:" ["❕"])
+             (":exclamation:" ["❗"])
+             (":heavy_exclamation_mark:" ["❗"])
+             (":heavy_heart_exclamation_mark_ornament:" ["❣️"])
+             (":heart_on_fire:" ["❤️‍🔥"])
+             (":mending_heart:" ["❤️‍🩹"])
+             (":heart:" ["❤️"])
+             ("<3" ["❤️"])
+             (":heavy_plus_sign:" ["➕"])
+             (":heavy_minus_sign:" ["➖"])
+             (":heavy_division_sign:" ["➗"])
+             (":arrow_right:" ["➡️"])
+             (":curly_loop:" ["➰"])
+             (":loop:" ["➿"])
+             (":arrow_heading_up:" ["⤴️"])
+             (":arrow_heading_down:" ["⤵️"])
+             (":arrow_left:" ["⬅️"])
+             (":arrow_up:" ["⬆️"])
+             (":arrow_down:" ["⬇️"])
+             (":black_large_square:" ["⬛"])
+             (":white_large_square:" ["⬜"])
+             (":star:" ["⭐"])
+             (":o:" ["⭕"])
+             (":wavy_dash:" ["〰️"])
+             (":part_alternation_mark:" ["〽️"])
+             (":congratulations:" ["㊗️"])
+             (":secret:" ["㊙️"])))))))
+
+(emoji--define-rules)
+
+(provide 'emoji)
+;;; emoji.el ends here
diff --git a/lisp/man.el b/lisp/man.el
index adf244a11a..d6146a2c4d 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1976,6 +1976,30 @@ Uses `Man-name-local-regexp'."
     (bookmark-default-handler
      `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark)))))
 
+;;; Mouse support
+(defun Man-at-mouse (e)
+  "Open man manual at point."
+  (interactive "e")
+  (save-excursion
+    (mouse-set-point e)
+    (man (Man-default-man-entry))))
+
+;;;###autoload
+(defun Man-context-menu (menu click)
+  "Populate MENU with commands that open a man page at point."
+  (save-excursion
+    (mouse-set-point click)
+    (when (save-excursion
+            (skip-syntax-backward "^ ")
+            (and (looking-at
+                  "[[:space:]]*\\([[:alnum:]_-]+([[:alnum:]]+)\\)")
+                  (match-string 1)))
+      (define-key-after menu [man-separator] menu-bar-separator)
+      (define-key-after menu [man-at-mouse]
+    '(menu-item "Open man page" man-at-mouse
+            :help "Open man page around mouse click"))))
+  menu)
+
 
 ;; Init the man package variables, if not already done.
 (Man-init-defvars)
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index e0cf6c588c..36cbd6a9c5 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -109,6 +109,16 @@
       (bindings--define-key menu [separator-tab]
         menu-bar-separator))
 
+    (bindings--define-key menu [enable-undelete-frame-mode]
+      '(menu-item "Enable Undeleting Frames" undelete-frame-mode
+                  :visible (null undelete-frame-mode)
+                  :help "Enable undeleting frames in this session"))
+    (bindings--define-key menu [undelete-last-deleted-frame]
+      '(menu-item "Undelete Frame" undelete-frame
+                  :visible (and undelete-frame-mode
+                                (car undelete-frame--deleted-frames))
+                  :help "Undelete the most recently deleted frame"))
+
     ;; Don't use delete-frame as event name because that is a special
     ;; event.
     (bindings--define-key menu [delete-this-frame]
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 1a76b9a0b6..46dd0397d7 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -298,6 +298,9 @@ and should return the same menu with changes such as added 
new menu items."
                   (function-item context-menu-buffers)
                   (function-item context-menu-vc)
                   (function-item context-menu-ffap)
+                  (function-item Man-context-menu)
+                  (function-item hi-lock-context-menu)
+                  (function-item context-menu-online-search)
                   (function :tag "Custom function")))
   :version "28.1")
 
@@ -531,6 +534,16 @@ Some context functions add menu items below the separator."
                     :help "Find file or URL from text around mouse click"))))
   menu)
 
+(defun context-menu-online-search (menu click)
+  "Populate MENU with command to search online."
+  (save-excursion
+    (mouse-set-point click)
+    (define-key-after menu [online-search-separator] menu-bar-separator)
+    (define-key-after menu [online-search-at-mouse]
+      '(menu-item "Online search" mouse-online-search-at-point
+                  :help "Search for region or word online")))
+  menu)
+
 (defvar context-menu-entry
   `(menu-item ,(purecopy "Context Menu") ,(make-sparse-keymap)
               :filter ,(lambda (_) (context-menu-map)))
@@ -3217,6 +3230,26 @@ is copied instead of being cut."
         (with-current-buffer (window-buffer window)
           (setq cursor-type (nth 3 state)))))))
 
+(defvar eww-search-prefix)
+(defun mouse-online-search-at-point (event)
+  "Query an online search engine at EVENT.
+If a region is active, the entire region will be sent, otherwise
+the symbol at point will be used.  This command uses EWW's
+default search engine, as configured by `eww-search-prefix'."
+  (interactive "e")
+  (require 'eww)
+  (let ((query (if (use-region-p)
+                   (buffer-substring (region-beginning)
+                                     (region-end))
+                 (save-excursion
+                   (mouse-set-point event)
+                   (thing-at-point 'symbol)))))
+    (unless query
+      (user-error "Nothing to search for"))
+    (browse-url (concat
+                 eww-search-prefix
+                 (mapconcat #'url-hexify-string (split-string query) "+")))))
+
 
 ;;; Bindings for mouse commands.
 
diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el
index bf3c8edd1e..daa2d5a3fb 100644
--- a/lisp/net/mailcap.el
+++ b/lisp/net/mailcap.el
@@ -439,9 +439,10 @@ MAILCAPS if set; otherwise (on Unix) use the path from RFC 
1524, plus
              ("/usr/local/etc/mailcap" system)))))
     (when (stringp path)
       (setq path (mapcar #'list (split-string path path-separator t))))
-    (when (seq-some (lambda (f)
-                      (file-has-changed-p (car f) 'mail-parse-mailcaps))
-                    path)
+    (when (or (null mailcap--computed-mime-data)
+              (seq-some (lambda (f)
+                          (file-has-changed-p (car f) 'mail-parse-mailcaps))
+                        path))
       ;; Clear out all old data.
       (setq mailcap--computed-mime-data nil)
       ;; Add the Emacs-distributed defaults (which will be used as
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 36443e0983..c2c3689c61 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -39,7 +39,7 @@
 ;; first time you access a crypted remote directory.  It is kept in
 ;; your user directory "~/.emacs.d/" with the url-encoded directory
 ;; name as part of the basename, and ".encfs6.xml" as suffix.  Do not
-;; loose this file and the corresponding password; otherwise there is
+;; lose this file and the corresponding password; otherwise there is
 ;; no way to decrypt your crypted files.
 
 ;; If the user option `tramp-crypt-save-encfs-config-remote' is
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index b1bef82842..3f78c9eb15 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -744,10 +744,10 @@ The option \"--fullname\" must be included in this value."
 
     output))
 
-(easy-mmode-defmap gud-minibuffer-local-map
-  '(("\C-i" . comint-dynamic-complete-filename))
-  "Keymap for minibuffer prompting of gud startup command."
-  :inherit minibuffer-local-map)
+(defvar-keymap gud-minibuffer-local-map
+  :doc "Keymap for minibuffer prompting of gud startup command."
+  :parent minibuffer-local-map
+  "C-i" #'comint-dynamic-complete-filename)
 
 (defun gud-query-cmdline (minor-mode &optional init)
   (let* ((hist-sym (gud-symbol 'history nil minor-mode))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index edd3139a7a..5889f2ab67 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -3216,11 +3216,13 @@ detecting a prompt at the end of the buffer."
 (defun python-shell-send-string-no-output (string &optional process)
   "Send STRING to PROCESS and inhibit output.
 Return the output."
-  (let ((process (or process (python-shell-get-process-or-error)))
-        (comint-preoutput-filter-functions
-         '(python-shell-output-filter))
-        (python-shell-output-filter-in-progress t)
-        (inhibit-quit t))
+  (or process (setq process (python-shell-get-process-or-error)))
+  (cl-letf (((process-filter process)
+             (lambda (_proc str)
+               (with-current-buffer (process-buffer process)
+                 (python-shell-output-filter str))))
+            (python-shell-output-filter-in-progress t)
+            (inhibit-quit t))
     (or
      (with-local-quit
        (python-shell-send-string string process)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 9ce63a8f8a..066c051cfc 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -738,11 +738,20 @@ quit the *xref* buffer."
   "Perform interactive replacement of FROM with TO in all displayed xrefs.
 
 This command interactively replaces FROM with TO in the names of the
-references displayed in the current *xref* buffer."
+references displayed in the current *xref* buffer.
+
+When called interactively, it uses '.*' as FROM, which means
+replace the whole name.  Unless called with prefix argument, in
+which case the user is prompted for both FROM and TO."
   (interactive
-   (let ((fr (read-regexp "Xref query-replace (regexp)" ".*")))
-     (list fr
-           (read-regexp (format "Xref query-replace (regexp) %s with: " fr)))))
+   (let* ((fr
+           (if current-prefix-arg
+               (read-regexp "Query-replace (regexp)" ".*")
+             ".*"))
+          (prompt (if current-prefix-arg
+                      (format "Query-replace (regexp) %s with: " fr)
+                    "Query-replace all matches with: ")))
+     (list fr (read-regexp prompt))))
   (let* (item xrefs iter)
     (save-excursion
       (while (setq item (xref--search-property 'xref-item))
@@ -1469,6 +1478,22 @@ is nil, prompt only if there's no usable symbol at 
point."
   (interactive (list (xref--read-identifier "Find references of: ")))
   (xref--find-xrefs identifier 'references identifier nil))
 
+(defun xref-find-references-and-replace (from to)
+  "Replace all references to identifier FROM with TO."
+  (interactive
+   (let ((common
+          (query-replace-read-args "Query replace identifier" nil)))
+     (list (nth 0 common) (nth 1 common))))
+  (require 'xref)
+  (with-current-buffer
+      (let ((xref-show-xrefs-function
+             ;; Some future-proofing (bug#44905).
+             (custom--standard-value 'xref-show-xrefs-function))
+            ;; Disable auto-jumping, it will mess up replacement logic.
+            xref-auto-jump-to-first-xref)
+        (xref-find-references from))
+    (xref-query-replace-in-results ".*" to)))
+
 ;;;###autoload
 (defun xref-find-definitions-at-mouse (event)
   "Find the definition of identifier at or around mouse click.
diff --git a/lisp/subr.el b/lisp/subr.el
index 7906324f80..dd260dfe41 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -1971,7 +1971,7 @@ one will be removed."
                                 (format "%s hook to remove: "
                                         (if local "Buffer-local" "Global"))
                                 fn-alist
-                                nil t)
+                                nil t nil 'set-variable-value-history)
                                fn-alist nil nil #'string=)))
      (list hook function local)))
   (or (boundp hook) (set hook nil))
@@ -6537,4 +6537,26 @@ string will be displayed only if BODY takes longer than 
TIMEOUT seconds.
                                  (lambda ()
                                    ,@body)))
 
+(defun function-alias-p (func &optional noerror)
+  "Return nil if FUNC is not a function alias.
+If FUNC is a function alias, return the function alias chain.
+
+If the function alias chain contains loops, an error will be
+signalled.  If NOERROR, the non-loop parts of the chain is returned."
+  (declare (side-effect-free t))
+  (let ((chain nil)
+        (orig-func func))
+    (nreverse
+     (catch 'loop
+       (while (and (symbolp func)
+                   (setq func (symbol-function func))
+                   (symbolp func))
+         (when (or (memq func chain)
+                   (eq func orig-func))
+           (if noerror
+               (throw 'loop chain)
+             (signal 'cyclic-function-indirection (list orig-func))))
+         (push func chain))
+       chain))))
+
 ;;; subr.el ends here
diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el
index 11d14f9576..341fa243cf 100644
--- a/lisp/vc/pcvs-info.el
+++ b/lisp/vc/pcvs-info.el
@@ -130,9 +130,11 @@ to confuse some users sometimes."
 (defvar cvs-bakprefix ".#"
   "The prefix that CVS prepends to files when rcsmerge'ing.")
 
-(easy-mmode-defmap cvs-status-map
-  '(([(mouse-2)] . cvs-mode-toggle-mark))
-  "Local keymap for text properties of status.")
+(autoload 'cvs-mode-toggle-mark "pcvs")
+
+(defvar-keymap cvs-status-map
+  :doc "Local keymap for text properties of status."
+  "<mouse-2>" #'cvs-mode-toggle-mark)
 
 ;; Constructor:
 
diff --git a/src/buffer.c b/src/buffer.c
index 10ac91915c..a3091015d9 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1247,7 +1247,7 @@ buffer_local_value (Lisp_Object variable, Lisp_Object 
buffer)
       { /* Look in local_var_alist.  */
        struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
        XSETSYMBOL (variable, sym); /* Update In case of aliasing.  */
-       result = Fassoc (variable, BVAR (buf, local_var_alist), Qnil);
+       result = assq_no_quit (variable, BVAR (buf, local_var_alist));
        if (!NILP (result))
          {
            if (blv->fwd.fwdptr)
diff --git a/src/data.c b/src/data.c
index e999cee242..7422348e39 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2180,7 +2180,7 @@ Instead, use `add-hook' and specify t for the LOCAL 
argument.  */)
 
   /* Make sure this buffer has its own value of symbol.  */
   XSETSYMBOL (variable, sym);  /* Update in case of aliasing.  */
-  tem = Fassq (variable, BVAR (current_buffer, local_var_alist));
+  tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist));
   if (NILP (tem))
     {
       if (let_shadows_buffer_binding_p (sym))
@@ -2260,7 +2260,7 @@ From now on the default value will apply in this buffer.  
Return VARIABLE.  */)
 
   /* Get rid of this buffer's alist element, if any.  */
   XSETSYMBOL (variable, sym);  /* Propagate variable indirection.  */
-  tem = Fassq (variable, BVAR (current_buffer, local_var_alist));
+  tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist));
   if (!NILP (tem))
     bset_local_var_alist
       (current_buffer,
@@ -2301,7 +2301,7 @@ Also see `buffer-local-boundp'.*/)
     case SYMBOL_PLAINVAL: return Qnil;
     case SYMBOL_LOCALIZED:
       {
-       Lisp_Object tail, elt, tmp;
+       Lisp_Object tmp;
        struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
        XSETBUFFER (tmp, buf);
        XSETSYMBOL (variable, sym); /* Update in case of aliasing.  */
@@ -2309,13 +2309,9 @@ Also see `buffer-local-boundp'.*/)
        if (EQ (blv->where, tmp)) /* The binding is already loaded.  */
          return blv_found (blv) ? Qt : Qnil;
        else
-         for (tail = BVAR (buf, local_var_alist); CONSP (tail); tail = XCDR 
(tail))
-           {
-             elt = XCAR (tail);
-             if (EQ (variable, XCAR (elt)))
-               return Qt;
-           }
-       return Qnil;
+         return NILP (assq_no_quit (variable, BVAR (buf, local_var_alist)))
+           ? Qnil
+           : Qt;
       }
     case SYMBOL_FORWARDED:
       {
diff --git a/src/font.c b/src/font.c
index 266e5bc75c..7e0219181c 100644
--- a/src/font.c
+++ b/src/font.c
@@ -2183,7 +2183,9 @@ font_score (Lisp_Object entity, Lisp_Object *spec_prop)
 
   /* Score three style numeric fields.  Maximum difference is 127. */
   for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
-    if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
+    if (! NILP (spec_prop[i])
+       && ! EQ (AREF (entity, i), spec_prop[i])
+       && FIXNUMP (AREF (entity, i)))
       {
        EMACS_INT diff = ((XFIXNUM (AREF (entity, i)) >> 8)
                          - (XFIXNUM (spec_prop[i]) >> 8));
@@ -2764,26 +2766,31 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object 
spec, int size)
        {
          if (FIXNUMP (AREF (spec, prop)))
            {
-             int required = XFIXNUM (AREF (spec, prop)) >> 8;
-             int candidate = XFIXNUM (AREF (entity, prop)) >> 8;
+             if (!FIXNUMP (AREF (entity, prop)))
+               prop = FONT_SPEC_MAX;
+             else
+               {
+                 int required = XFIXNUM (AREF (spec, prop)) >> 8;
+                 int candidate = XFIXNUM (AREF (entity, prop)) >> 8;
 
-             if (candidate != required
+                 if (candidate != required
 #ifdef HAVE_NTGUI
-                 /* A kludge for w32 font search, where listing a
-                    family returns only 4 standard weights: regular,
-                    italic, bold, bold-italic.  For other values one
-                    must specify the font, not just the family in the
-                    :family attribute of the face.  But specifying
-                    :family in the face attributes looks for regular
-                    weight, so if we require exact match, the
-                    non-regular font will be rejected.  So we relax
-                    the accuracy of the match here, and let
-                    font_sort_entities find the best match.  */
-                 && (prop != FONT_WEIGHT_INDEX
-                     || eabs (candidate - required) > 100)
+                     /* A kludge for w32 font search, where listing a
+                        family returns only 4 standard weights: regular,
+                        italic, bold, bold-italic.  For other values one
+                        must specify the font, not just the family in the
+                        :family attribute of the face.  But specifying
+                        :family in the face attributes looks for regular
+                        weight, so if we require exact match, the
+                        non-regular font will be rejected.  So we relax
+                        the accuracy of the match here, and let
+                        font_sort_entities find the best match.  */
+                     && (prop != FONT_WEIGHT_INDEX
+                         || eabs (candidate - required) > 100)
 #endif
-                 )
-               prop = FONT_SPEC_MAX;
+                     )
+                   prop = FONT_SPEC_MAX;
+               }
            }
        }
       if (prop < FONT_SPEC_MAX
diff --git a/src/frame.c b/src/frame.c
index c0f4f3ecde..e5d74edc16 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -2382,9 +2382,12 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
 }
 
 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
-       doc: /* Delete FRAME, permanently eliminating it from use.
+       doc: /* Delete FRAME, eliminating it from use.
 FRAME must be a live frame and defaults to the selected one.
 
+When `undelete-frame-mode' is enabled, the 16 most recently deleted
+frames can be undeleted with `undelete-frame', which see.
+
 A frame may not be deleted if its minibuffer serves as surrogate
 minibuffer for another frame.  Normally, you may not delete a frame if
 all other frames are invisible, but if the second optional argument
diff --git a/src/ftfont.c b/src/ftfont.c
index 2bdcce306b..5797300d23 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -189,6 +189,24 @@ ftfont_pattern_entity (FcPattern *p, Lisp_Object extra)
     return Qnil;
   if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
     return Qnil;
+#ifdef FC_VARIABLE
+  /* This is a virtual/meta FcPattern for a variable weight font, from
+     which it is possible to extract an FcRange value specifying the
+     minimum and maximum weights available in this file.  We don't
+     need to know that information explicitly, so skip it.  We will be
+     called with an FcPattern for each actually available, non-virtual
+     weight.
+
+     Fontconfig started generating virtual/meta patterns for variable
+     weight fonts in the same release that FC_VARIABLE was added, so
+     we conditionalize on that constant.  This also ensures that
+     FcPatternGetRange is available.  */
+  FcRange *range;
+  if (FcPatternGetRange (p, FC_WEIGHT, 0, &range) == FcResultMatch
+      && FcPatternGetBool (p, FC_VARIABLE, 0, &b) == FcResultMatch
+      && b == FcTrue)
+    return Qnil;
+#endif /* FC_VARIABLE */
 
   file = (char *) str;
   key = Fcons (build_unibyte_string (file), make_fixnum (idx));
@@ -863,6 +881,9 @@ ftfont_list (struct frame *f, Lisp_Object spec)
 #if defined HAVE_XFT && defined FC_COLOR
                              FC_COLOR,
 #endif
+#ifdef FC_VARIABLE
+                            FC_VARIABLE,
+#endif /* FC_VARIABLE */
                             NULL);
   if (! objset)
     goto err;
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 1db166b1ba..36ed55bc03 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -6255,16 +6255,19 @@ xg_widget_key_press_event_cb (GtkWidget *widget, 
GdkEvent *event,
       kbd_buffer_store_buffered_event (&inev, &xg_pending_quit_event);
     }
 
-#ifdef USABLE_SIGIO
-  raise (SIGIO);
-#endif
+  XNoOp (FRAME_X_DISPLAY (f));
   return true;
 }
 
 bool
 xg_filter_key (struct frame *frame, XEvent *xkey)
 {
-  GdkEvent *xg_event = gdk_event_new (GDK_KEY_PRESS);
+  GdkEvent *xg_event = gdk_event_new ((xkey->type == ButtonPress
+#ifdef HAVE_XINPUT2
+                                      || (xkey->type == GenericEvent
+                                          && xkey->xgeneric.evtype == 
XI_KeyPress)
+#endif
+                                      ) ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
   GdkDisplay *dpy = gtk_widget_get_display (FRAME_GTK_WIDGET (frame));
   GdkKeymap *keymap = gdk_keymap_get_for_display (dpy);
   GdkModifierType consumed;
diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc
index 5d355ac205..270a619b89 100644
--- a/src/haiku_draw_support.cc
+++ b/src/haiku_draw_support.cc
@@ -313,7 +313,7 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int 
x,
       BRect bounds = bc.Bounds ();
       for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y)
        {
-         for (int x = 0; x <= BE_RECT_WIDTH (bounds); ++x)
+         for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x)
            {
              if (bits[y * (stride / 4) + x] == 0xFF000000)
                bits[y * (stride / 4) + x] = RGB_COLOR_UINT32 (low_color);
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 531dfb5c64..d49e319b98 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -136,6 +136,15 @@ gui_abort (const char *msg)
   emacs_abort ();
 }
 
+/* Convert a raw character RAW produced by the keycode KEY into a key
+   symbol and place it in KEYSYM.
+
+   If RAW cannot be converted into a keysym, value is 0.  If RAW can
+   be converted into a keysym, but it should be ignored, value is -1.
+
+   Any other value means success, and that the keysym should be used
+   instead of mapping the keycode into a character.  */
+
 static int
 keysym_from_raw_char (int32 raw, int32 key, unsigned *code)
 {
@@ -186,6 +195,19 @@ keysym_from_raw_char (int32 raw, int32 key, unsigned *code)
 
     case B_FUNCTION_KEY:
       *code = XK_F1 + key - 2;
+
+      if (*code - XK_F1 == 12)
+       *code = XK_Print;
+      else if (*code - XK_F1 == 13)
+       /* Okay, Scroll Lock is a bit too much: keyboard.c doesn't
+          know about it yet, and it shouldn't, since that's a
+          modifier key.
+
+          *code = XK_Scroll_Lock; */
+       return -1;
+      else if (*code - XK_F1 == 14)
+       *code = XK_Pause;
+
       break;
 
     default:
@@ -693,6 +715,7 @@ public:
        rq.window = this;
 
        int32 raw, key;
+       int ret;
        msg->FindInt32 ("raw_char", &raw);
        msg->FindInt32 ("key", &key);
 
@@ -711,9 +734,14 @@ public:
        if (mods & B_OPTION_KEY)
          rq.modifiers |= HAIKU_MODIFIER_SUPER;
 
-       if (!keysym_from_raw_char (raw, key, &rq.keysym))
+       ret = keysym_from_raw_char (raw, key, &rq.keysym);
+
+       if (!ret)
          rq.keysym = 0;
 
+       if (ret < 0)
+         return;
+
        rq.multibyte_char = 0;
 
        if (!rq.keysym)
diff --git a/src/haikuterm.c b/src/haikuterm.c
index be28649aef..3e99cc1c8d 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -2222,6 +2222,7 @@ haiku_draw_fringe_bitmap (struct window *w, struct 
glyph_row *row,
   void *view = FRAME_HAIKU_VIEW (XFRAME (WINDOW_FRAME (w)));
   struct face *face = p->face;
 
+  block_input ();
   BView_draw_lock (view);
   BView_StartClip (view);
 
@@ -2256,6 +2257,7 @@ haiku_draw_fringe_bitmap (struct window *w, struct 
glyph_row *row,
     }
   BView_EndClip (view);
   BView_draw_unlock (view);
+  unblock_input ();
 }
 
 static void
@@ -3233,7 +3235,10 @@ haiku_read_socket (struct terminal *terminal, struct 
input_event *hold_quit)
            struct frame *f = haiku_window_to_frame (b->window);
 
            if (!f)
-             continue;
+             {
+               free (b->ref);
+               continue;
+             }
 
            inev.kind = DRAG_N_DROP_EVENT;
            inev.arg = build_string_from_utf8 (b->ref);
diff --git a/src/window.c b/src/window.c
index 7155f0e6bc..2a5e4042a4 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5861,7 +5861,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, 
bool whole, bool noerror)
 
       /* We moved the window start towards ZV, so PT may be now
         in the scroll margin at the top.  */
-      move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+      if (IT_CHARPOS (it) < PT)
+       move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
       if (IT_CHARPOS (it) == PT
          && it.current_y >= this_scroll_margin
          && it.current_y <= last_y - WINDOW_TAB_LINE_HEIGHT (w)
diff --git a/src/xdisp.c b/src/xdisp.c
index 2326df4300..977d31703f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -18557,6 +18557,20 @@ try_cursor_movement (Lisp_Object window, struct 
text_pos startp,
                            || (NILP (g->object)
                                && (g->charpos == PT
                                    || (g->charpos == 0 && endpos - 1 == PT)));
+                         /* Perhaps the point position is inside
+                            invisible text?  In that case, we trust
+                            'set_cursor_from_row' to do its job and
+                            find the best position for the cursor.  */
+                         if (!exact_match_p)
+                           {
+                             Lisp_Object val =
+                               get_char_property_and_overlay (make_fixnum (PT),
+                                                              Qinvisible,
+                                                              Qnil, NULL);
+
+                             if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
+                               exact_match_p = true;
+                           }
                        }
                      if (at_zv_p || exact_match_p)
                        {
diff --git a/src/xfns.c b/src/xfns.c
index 028ee29a4a..ffad0bc3d1 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3347,6 +3347,8 @@ setup_xi_event_mask (struct frame *f)
   XISetMask (m, XI_Motion);
   XISetMask (m, XI_Enter);
   XISetMask (m, XI_Leave);
+  XISetMask (m, XI_FocusIn);
+  XISetMask (m, XI_FocusOut);
   XISetMask (m, XI_KeyPress);
   XISetMask (m, XI_KeyRelease);
   XISelectEvents (FRAME_X_DISPLAY (f),
@@ -3359,6 +3361,8 @@ setup_xi_event_mask (struct frame *f)
 #ifdef USE_X_TOOLKIT
   XISetMask (m, XI_KeyPress);
   XISetMask (m, XI_KeyRelease);
+  XISetMask (m, XI_FocusIn);
+  XISetMask (m, XI_FocusOut);
 
   XISelectEvents (FRAME_X_DISPLAY (f),
                  FRAME_OUTER_WINDOW (f),
diff --git a/src/xterm.c b/src/xterm.c
index 5271589270..ec415f5ffa 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -20,6 +20,72 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 /* New display code by Gerd Moellmann <gerd@gnu.org>.  */
 /* Xt features made by Fred Pierresteguy.  */
 
+/* X window system support for GNU Emacs
+
+   This file is part of the X window system support for GNU Emacs.  It
+   contains subroutines comprising the redisplay interface, setting up
+   scroll bars and widgets, and handling input.
+
+   INPUT
+
+   Emacs handles input by running pselect in a loop, which returns
+   whenever there is input available on the connection to the X
+   server.  On some systems, Emacs also arranges for any new input on
+   that connection to send an asynchronous signal.  Whenever pselect
+   returns, or such a signal is received and input is not blocked,
+   XTread_socket is called and translates X11 events read by Xlib into
+   struct input_events, which are then stored in the keyboard buffer,
+   to be processed and acted upon at some later time.  The function
+   handle_one_xevent is responsible for handling core events after
+   they are filtered, and filtering X Input Extension events.  It also
+   performs actions on some special events, such as updating the
+   dimensions of a frame after a ConfigureNotify is sent by the X
+   server to inform us that it changed.
+
+   Before such events are translated, an Emacs build with
+   internationalization enabled (the default since X11R6) will filter
+   events through an X Input Method (XIM) or GTK, which might decide
+   to intercept the event and send a different one in its place, for
+   reasons such as enabling the user to insert international
+   characters that aren't on his keyboard by typing a sequence of
+   characters which are.  See the function x_filter_event and its
+   callers for more details.
+
+   Events that cause Emacs to quit are treated specially by the code
+   that stores them in the keyboard buffer and generally cause an
+   immediate interrupt.  Such an interrupt can lead to a longjmp from
+   the code that stored the keyboard event, which isn't safe inside
+   XTread_socket.  To avoid this problem, XTread_socket is provided a
+   special event buffer named hold_quit.  When a quit event is
+   encountered, it is stored inside this special buffer, which will
+   cause the keyboard code that called XTread_socket to store it at a
+   later time when it is safe to do so.
+
+   handle_one_xevent will generally have to determine which frame an
+   event should be attributed to.  This is not easy, because events
+   can come from multiple X windows, and a frame can also have
+   multiple windows.  handle_one_xevent usually calls the function
+   x_any_window_to_frame, which searches for a frame by toplevel
+   window and widget windows.  There are also some other functions for
+   searching by specific types of window, such as
+   x_top_window_to_frame (which only searches for frames by toplevel
+   window), and x_menubar_window_to_frame (which will only search
+   through frame menu bars).
+
+   INPUT FOCUS
+
+   Under X, the window where keyboard input is sent is not always
+   explictly defined.  When there is a focus window, it receives what
+   is referred to as "explicit focus", but when there is none, it
+   receives "implicit focus" whenever the pointer enters it, and loses
+   that focus when the pointer leaves.  When the toplevel window of a
+   frame receives an explicit focus event (FocusIn or FocusOut), we
+   treat that frame as having the current input focus, but when there
+   is no focus window, we treat each frame as having the input focus
+   whenever the pointer enters it, and undo that treatment when the
+   pointer leaves it.  See the callers of x_detect_focus_change for
+   more details.  */
+
 #include <config.h>
 #include <stdlib.h>
 #include <math.h>
@@ -4126,7 +4192,9 @@ x_draw_glyph_string (struct glyph_string *s)
       area_max_x = area_x + area_width - 1;
 
       decoration_width = s->width;
-      if (area_max_x < (s->x + decoration_width - 1))
+      if (!s->row->mode_line_p
+         && !s->row->tab_line_p
+         && area_max_x < (s->x + decoration_width - 1))
        decoration_width -= (s->x + decoration_width - 1) - area_max_x;
 
       /* Draw relief if not yet drawn.  */
@@ -5252,21 +5320,18 @@ x_detect_focus_change (struct x_display_info *dpyinfo, 
struct frame *frame,
         int focus_state
           = focus_frame ? focus_frame->output_data.x->focus_state : 0;
 
-#ifdef USE_GTK
        if (xi_event->evtype == XI_FocusIn
            || xi_event->evtype == XI_FocusOut)
          x_focus_changed ((xi_event->evtype == XI_FocusIn
                            ? FocusIn : FocusOut),
                           FOCUS_EXPLICIT,
                           dpyinfo, frame, bufp);
-       else
-#endif
-         if ((xi_event->evtype == XI_Enter
-              || xi_event->evtype == XI_Leave)
-             && (((XIEnterEvent *) xi_event)->detail
-                 != XINotifyInferior)
-             && ((XIEnterEvent *) xi_event)->focus
-             && !(focus_state & FOCUS_EXPLICIT))
+       else if ((xi_event->evtype == XI_Enter
+                 || xi_event->evtype == XI_Leave)
+                && (((XIEnterEvent *) xi_event)->detail
+                    != XINotifyInferior)
+                && ((XIEnterEvent *) xi_event)->focus
+                && !(focus_state & FOCUS_EXPLICIT))
          x_focus_changed ((xi_event->evtype == XI_Enter
                            ? FocusIn : FocusOut),
                           FOCUS_IMPLICIT,
@@ -5386,8 +5451,6 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
   dpyinfo->super_mod_mask = 0;
   dpyinfo->hyper_mod_mask = 0;
 
-  XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-
 #ifdef HAVE_XKB
   if (dpyinfo->xkb_desc)
     {
@@ -5432,6 +5495,8 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
     }
 #endif
 
+  XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
+
   syms = XGetKeyboardMapping (dpyinfo->display,
                              min_code, max_code - min_code + 1,
                              &syms_per_code);
@@ -5924,7 +5989,7 @@ XTmouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
        if (!f1 && insist > 0)
          f1 = SELECTED_FRAME ();
 
-       if (f1)
+       if (f1 && FRAME_X_P (f1))
          {
            /* Ok, we found a frame.  Store all the values.
               last_mouse_glyph is a rectangle used to reduce the
@@ -5934,7 +5999,6 @@ XTmouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
-           /* FIXME: what if F1 is not an X frame?  */
            dpyinfo = FRAME_DISPLAY_INFO (f1);
            remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
            dpyinfo->last_mouse_glyph_frame = f1;
@@ -8285,8 +8349,10 @@ x_filter_event (struct x_display_info *dpyinfo, XEvent 
*event)
       && event->type == GenericEvent
       && (event->xgeneric.extension
          == dpyinfo->xi2_opcode)
-      && (event->xgeneric.evtype
-         == XI_KeyPress))
+      && ((event->xgeneric.evtype
+          == XI_KeyPress)
+         || (event->xgeneric.evtype
+             == XI_KeyRelease)))
     {
       f1 = x_any_window_to_frame (dpyinfo,
                                  ((XIDeviceEvent *)
@@ -9458,7 +9524,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
     case EnterNotify:
       x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
-      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+      if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
+       x_detect_focus_change (dpyinfo, any, event, &inev.ie);
 
 #ifdef HAVE_XWIDGETS
       {
@@ -9540,7 +9608,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
       }
 #endif
       x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
-      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+      if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
+       x_detect_focus_change (dpyinfo, any, event, &inev.ie);
 
       f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
 #if defined HAVE_X_TOOLKIT && defined HAVE_XINPUT2
@@ -10151,13 +10221,23 @@ handle_one_xevent (struct x_display_info *dpyinfo,
            x_detect_focus_change (dpyinfo, any, event, &inev.ie);
            goto XI_OTHER;
          case XI_Enter:
-           any = x_any_window_to_frame (dpyinfo, enter->event);
+
+           any = x_top_window_to_frame (dpyinfo, enter->event);
            ev.x = lrint (enter->event_x);
            ev.y = lrint (enter->event_y);
-           ev.window = leave->event;
-
+           ev.window = enter->event;
            x_display_set_last_user_time (dpyinfo, xi_event->time);
-           x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+           /* There is no need to handle entry/exit events for
+              passive focus from non-top windows at all, since they
+              are an inferiors of the frame's top window, which will
+              get virtual events.  */
+           if (any)
+             x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+           if (!any)
+             any = x_any_window_to_frame (dpyinfo, enter->event);
+
            {
 #ifdef HAVE_XWIDGETS
              struct xwidget_view *xwidget_view = xwidget_view_from_window 
(enter->event);
@@ -10221,11 +10301,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev);
 #endif
            goto XI_OTHER;
+
          case XI_Leave:
            ev.x = lrint (leave->event_x);
            ev.y = lrint (leave->event_y);
            ev.window = leave->event;
-           any = x_any_window_to_frame (dpyinfo, leave->event);
+           any = x_top_window_to_frame (dpyinfo, leave->event);
 
 #ifdef HAVE_XWIDGETS
            {
@@ -10243,7 +10324,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #endif
 
            x_display_set_last_user_time (dpyinfo, xi_event->time);
-           x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+           if (any)
+             x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+           if (!any)
+             any = x_any_window_to_frame (dpyinfo, leave->event);
 
 #ifndef USE_X_TOOLKIT
            f = x_top_window_to_frame (dpyinfo, leave->event);
@@ -11167,6 +11253,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
          case XI_PropertyEvent:
          case XI_HierarchyChanged:
          case XI_DeviceChanged:
+
+#ifdef XISlaveSwitch
+           if (xi_event->evtype == XI_DeviceChanged
+               && (((XIDeviceChangedEvent *) xi_event)->reason
+                   == XISlaveSwitch))
+             goto XI_OTHER;
+#endif
            x_init_master_valuators (dpyinfo);
            goto XI_OTHER;
 #ifdef XI_TouchBegin
@@ -11433,6 +11526,22 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
                  x_find_modifier_meanings (dpyinfo);
                }
+             else
+               {
+                 dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
+                                                (XkbKeySymsMask
+                                                 | XkbKeyTypesMask
+                                                 | XkbModifierMapMask
+                                                 | XkbVirtualModsMask),
+                                                XkbUseCoreKbd);
+
+                 if (dpyinfo->xkb_desc)
+                   XkbGetNames (dpyinfo->display,
+                                XkbGroupNamesMask | XkbVirtualModNamesMask,
+                                dpyinfo->xkb_desc);
+               }
+
+             XkbRefreshKeyboardMapping (&xkbevent->map);
            }
        }
 #endif
diff --git a/src/xwidget.c b/src/xwidget.c
index 7d6d256a19..45879b15cb 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -1447,8 +1447,8 @@ xwidget_motion_or_crossing (struct xwidget_view *view, 
const XEvent *event)
 #ifdef HAVE_XINPUT2
   else if (event->type == GenericEvent)
     {
-      xg_event->crossing.x = (gdouble) xev->event_x;
-      xg_event->crossing.y = (gdouble) xev->event_y;
+      xg_event->crossing.x = x;
+      xg_event->crossing.y = y;
       xg_event->crossing.x_root = (gdouble) xev->root_x;
       xg_event->crossing.y_root = (gdouble) xev->root_y;
       xg_event->crossing.time = xev->time;
diff --git a/test/Makefile.in b/test/Makefile.in
index d6ab7b244d..9ad994e110 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -75,7 +75,7 @@ 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 XDG_CONFIG_HOME
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH GREP_OPTIONS 
XDG_CONFIG_HOME
 
 # To run tests under a debugger, set this to eg: "gdb --args".
 GDB =
@@ -118,10 +118,8 @@ MODULES_EMACSOPT :=
 endif
 
 # The actual Emacs command run in the targets below.
-# Prevent any setting of EMACSLOADPATH in user environment causing problems,
-# and prevent locals to influence the text of the errors we expect to receive.
-emacs = LANG=C EMACSLOADPATH=             \
- EMACS_TEST_DIRECTORY=$(abspath $(srcdir)) \
+# Prevent locales influencing the text of the errors we expect to receive.
+emacs = LANG=C EMACS_TEST_DIRECTORY=$(abspath $(srcdir)) \
  $(GDB) $(TEST_TIMEOUT) "$(EMACS)" $(MODULES_EMACSOPT) $(EMACSOPT)
 
 # Set HOME to a nonexistent directory to prevent tests from accessing
diff --git a/test/lisp/emacs-lisp/edebug-tests.el 
b/test/lisp/emacs-lisp/edebug-tests.el
index d238bffdaa..35259a796a 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -1094,5 +1094,15 @@ This avoids potential duplicate definitions (Bug#41988)."
               (edebug-new-definition name))))
       (should-error (eval-buffer) :type 'invalid-read-syntax))))
 
+(ert-deftest edebug-tests-inline ()
+  "Check that Edebug can instrument inline functions (Bug#53068)."
+  (with-temp-buffer
+    (print '(define-inline edebug-tests-inline (arg)
+              (inline-quote ,arg))
+           (current-buffer))
+    (let ((edebug-all-defs t)
+          (edebug-initial-mode 'Go-nonstop))
+      (eval-buffer))))
+
 (provide 'edebug-tests)
 ;;; edebug-tests.el ends here
diff --git a/test/lisp/emacs-lisp/ert-tests.el 
b/test/lisp/emacs-lisp/ert-tests.el
index ac13064474..270cca1c2e 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -881,6 +881,9 @@ This macro is used to test if macroexpansion in `should' 
works."
   "Check that `lexical-binding' in `ert-deftest' has the file value."
   (should (equal lexical-binding t)))
 
+(ert-deftest ert-test-get-explainer ()
+  (should (eq (ert--get-explainer 'string-equal) 'ert--explain-string-equal))
+  (should (eq (ert--get-explainer 'string=) 'ert--explain-string-equal)))
 
 (provide 'ert-tests)
 
diff --git a/test/lisp/eshell/esh-opt-tests.el 
b/test/lisp/eshell/esh-opt-tests.el
index 532adfb733..255768635b 100644
--- a/test/lisp/eshell/esh-opt-tests.el
+++ b/test/lisp/eshell/esh-opt-tests.el
@@ -57,7 +57,7 @@
            '((?u "user" t user "execute a command as another USER")
              :parse-leading-options-only))))
   (should
-   (equal '("world" "emerge")
+   (equal '("DN" "emerge" "world")
           (eshell--process-args
            "sudo"
            '("-u" "root" "emerge" "-uDN" "world")
@@ -65,59 +65,132 @@
 
 (ert-deftest test-eshell-eval-using-options ()
   "Tests for `eshell-eval-using-options'."
+  ;; Test short options.
   (eshell-eval-using-options
-   "sudo" '("-u" "root" "whoami")
-   '((?u "user" t user "execute a command as another USER")
-     :parse-leading-options-only)
-   (should (equal user "root")))
+   "ls" '("-a" "/some/path")
+   '((?a "all" nil show-all
+         "do not ignore entries starting with ."))
+   (should (eq show-all t))
+   (should (equal args '("/some/path"))))
   (eshell-eval-using-options
-   "sudo" '("--user" "root" "whoami")
-   '((?u "user" t user "execute a command as another USER")
-     :parse-leading-options-only)
-   (should (equal user "root")))
+   "ls" '("/some/path")
+   '((?a "all" nil show-all
+         "do not ignore entries starting with ."))
+   (should (eq show-all nil))
+   (should (equal args '("/some/path"))))
 
+  ;; Test long options.
   (eshell-eval-using-options
-   "sudo" '("emerge" "-uDN" "world")
-   '((?u "user" t user "execute a command as another USER"))
-   (should (equal user "world")))
+   "ls" '("--all" "/some/path")
+   '((?a "all" nil show-all
+         "do not ignore entries starting with ."))
+   (should (eq show-all t))
+   (should (equal args '("/some/path"))))
+
+  ;; Test options with constant values.
   (eshell-eval-using-options
-   "sudo" '("emerge" "-uDN" "world")
-   '((?u "user" t user "execute a command as another USER")
-     :parse-leading-options-only)
-   (should (eq user nil)))
+   "ls" '("/some/path" "-h")
+   '((?h "human-readable" 1024 human-readable
+         "print sizes in human readable format"))
+   (should (eql human-readable 1024))
+   (should (equal args '("/some/path"))))
+  (eshell-eval-using-options
+   "ls" '("/some/path" "--human-readable")
+   '((?h "human-readable" 1024 human-readable
+         "print sizes in human readable format"))
+   (should (eql human-readable 1024))
+   (should (equal args '("/some/path"))))
+  (eshell-eval-using-options
+   "ls" '("/some/path")
+   '((?h "human-readable" 1024 human-readable
+         "print sizes in human readable format"))
+   (should (eq human-readable nil))
+   (should (equal args '("/some/path"))))
 
+  ;; Test options with user-specified values.
+  (eshell-eval-using-options
+   "ls" '("-I" "*.txt" "/some/path")
+   '((?I "ignore" t ignore-pattern
+         "do not list implied entries matching pattern"))
+   (should (equal ignore-pattern "*.txt"))
+   (should (equal args '("/some/path"))))
+  (eshell-eval-using-options
+   "ls" '("-I*.txt" "/some/path")
+   '((?I "ignore" t ignore-pattern
+         "do not list implied entries matching pattern"))
+   (should (equal ignore-pattern "*.txt"))
+   (should (equal args '("/some/path"))))
   (eshell-eval-using-options
-   "ls" '("-I" "*.txt" "/dev/null")
+   "ls" '("--ignore" "*.txt" "/some/path")
    '((?I "ignore" t ignore-pattern
-        "do not list implied entries matching pattern"))
-   (should (equal ignore-pattern "*.txt")))
+         "do not list implied entries matching pattern"))
+   (should (equal ignore-pattern "*.txt"))
+   (should (equal args '("/some/path"))))
+  (eshell-eval-using-options
+   "ls" '("--ignore=*.txt" "/some/path")
+   '((?I "ignore" t ignore-pattern
+         "do not list implied entries matching pattern"))
+   (should (equal ignore-pattern "*.txt"))
+   (should (equal args '("/some/path"))))
 
+  ;; Test multiple short options in a single token.
   (eshell-eval-using-options
-   "ls" '("-l" "/dev/null")
-   '((?l nil long-listing listing-style
-        "use a long listing format"))
-   (should (eql listing-style 'long-listing)))
+   "ls" '("-al" "/some/path")
+   '((?a "all" nil show-all
+         "do not ignore entries starting with .")
+     (?l nil long-listing listing-style
+         "use a long listing format"))
+   (should (eq t show-all))
+   (should (eql listing-style 'long-listing))
+   (should (equal args '("/some/path"))))
   (eshell-eval-using-options
-   "ls" '("/dev/null")
-   '((?l nil long-listing listing-style
-        "use a long listing format"))
-   (should (eq listing-style nil)))
+   "ls" '("-aI*.txt" "/some/path")
+   '((?a "all" nil show-all
+         "do not ignore entries starting with .")
+     (?I "ignore" t ignore-pattern
+         "do not list implied entries matching pattern"))
+   (should (eq t show-all))
+   (should (equal ignore-pattern "*.txt"))
+   (should (equal args '("/some/path"))))
 
+  ;; Test that "--" terminates options.
   (eshell-eval-using-options
-   "ls" '("/dev/null" "-h")
-   '((?h "human-readable" 1024 human-readable
-        "print sizes in human readable format"))
-   (should (eql human-readable 1024)))
+   "ls" '("--" "-a")
+   '((?a "all" nil show-all
+         "do not ignore entries starting with ."))
+   (should (eq show-all nil))
+   (should (equal args '("-a"))))
   (eshell-eval-using-options
-   "ls" '("/dev/null" "--human-readable")
-   '((?h "human-readable" 1024 human-readable
-        "print sizes in human readable format"))
-   (should (eql human-readable 1024)))
+   "ls" '("--" "--all")
+   '((?a "all" nil show-all
+         "do not ignore entries starting with ."))
+   (should (eq show-all nil))
+   (should (equal args '("--all"))))
+
+  ;; Test :parse-leading-options-only.
   (eshell-eval-using-options
-   "ls" '("/dev/null")
-   '((?h "human-readable" 1024 human-readable
-        "print sizes in human readable format"))
-   (should (eq human-readable nil))))
+   "sudo" '("-u" "root" "whoami")
+   '((?u "user" t user "execute a command as another USER")
+     :parse-leading-options-only)
+   (should (equal user "root"))
+   (should (equal args '("whoami"))))
+  (eshell-eval-using-options
+   "sudo" '("--user" "root" "whoami")
+   '((?u "user" t user "execute a command as another USER")
+     :parse-leading-options-only)
+   (should (equal user "root"))
+   (should (equal args '("whoami"))))
+  (eshell-eval-using-options
+   "sudo" '("emerge" "-uDN" "world")
+   '((?u "user" t user "execute a command as another USER"))
+   (should (equal user "DN"))
+   (should (equal args '("emerge" "world"))))
+  (eshell-eval-using-options
+   "sudo" '("emerge" "-uDN" "world")
+   '((?u "user" t user "execute a command as another USER")
+     :parse-leading-options-only)
+   (should (eq user nil))
+   (should (equal args '("emerge" "-uDN" "world")))))
 
 (provide 'esh-opt-tests)
 
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index aebc9b6dbb..0fdc31e8b6 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -141,6 +141,23 @@ left alone when opening a URL in an external browser."
         (let (kill-buffer-query-functions)
           (kill-buffer (call-interactively #'find-file-at-point)))))))
 
+(ert-deftest ffap-test-path ()
+  (skip-unless (file-exists-p "/bin"))
+  (skip-unless (file-exists-p "/usr/bin"))
+  (with-temp-buffer
+    (insert "/usr/bin:/bin")
+    (goto-char (point-min))
+    (should (equal (ffap-file-at-point) "/usr/bin")))
+  (with-temp-buffer
+    (insert "/usr/bin:/bin")
+    (goto-char (point-min))
+    (search-forward ":")
+    (should (equal (ffap-file-at-point) "/bin")))
+  (with-temp-buffer
+    (insert ":/bin")
+    (goto-char (point-min))
+    (should (equal (ffap-file-at-point) nil))))
+
 (provide 'ffap-tests)
 
 ;;; ffap-tests.el ends here
diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el
index 6ee7b4f3eb..4df8e3c9ef 100644
--- a/test/lisp/help-fns-tests.el
+++ b/test/lisp/help-fns-tests.el
@@ -177,4 +177,13 @@ Return first line of the output of (describe-function-1 
FUNC)."
     (should-not (find-lisp-object-file-name help-fns--test-var 'defface))
     (should-not (find-lisp-object-file-name help-fns--test-var 1))))
 
+(ert-deftest help-fns--analyze-function-recursive ()
+  (defalias 'help-fns--a 'help-fns--b)
+  (should (equal (help-fns--analyze-function 'help-fns--a)
+                 '(help-fns--a help-fns--b t help-fns--b)))
+  ;; Make a loop and see that it doesn't infloop.
+  (defalias 'help-fns--b 'help-fns--a)
+  (should (equal (help-fns--analyze-function 'help-fns--a)
+                 '(help-fns--a help-fns--b t help-fns--b))))
+
 ;;; help-fns-tests.el ends here
diff --git a/test/lisp/so-long-tests/spelling-tests.el 
b/test/lisp/so-long-tests/spelling-tests.el
index 317513e9a9..ce4b0844c9 100644
--- a/test/lisp/so-long-tests/spelling-tests.el
+++ b/test/lisp/so-long-tests/spelling-tests.el
@@ -36,12 +36,11 @@
 ;; make lisp/so-long-tests/spelling-tests SELECTOR=t
 
 ;; Only define the test if spell-checking is possible.
-(when (and ispell-program-name
-           (executable-find ispell-program-name)
-           (condition-case ()
-               (progn (ispell-check-version) t)
-             (error nil))
-           (member "british" (ispell-valid-dictionary-list)))
+(when (ignore-errors
+        (and ispell-program-name
+             (executable-find ispell-program-name)
+             (progn (ispell-check-version) t)
+             (member "british" (ispell-valid-dictionary-list))))
   (ert-deftest so-long-spelling ()
     "Check the spelling in the source code."
     :tags '(:unstable) ;; It works for me, but I'm not sure about others.
@@ -51,8 +50,9 @@
     ;; The Emacs test Makefile's use of HOME=/nonexistent triggers an error
     ;; when starting the inferior ispell process, so we set HOME to a valid
     ;; (but empty) temporary directory for this test.
-    (ert-with-temp-file tmpdir
-      :suffix "so-long.ispell"
+    (ert-with-temp-directory tmpdir
+      :prefix "so-long."
+      :suffix ".ispell"
       (let* ((process-environment (cons (format "HOME=%s" tmpdir)
                                         process-environment))
              (find-spelling-mistake
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 9be7511bdc..512b654535 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -1007,5 +1007,22 @@ final or penultimate step during initialization."))
   (should (equal (ensure-list :foo) '(:foo)))
   (should (equal (ensure-list '(1 2 3)) '(1 2 3))))
 
+(ert-deftest test-alias-p ()
+  (should-not (function-alias-p 1))
+
+  (defun subr-tests--fun ())
+  (should-not (function-alias-p 'subr-tests--fun))
+
+  (defalias 'subr-tests--a 'subr-tests--b)
+  (defalias 'subr-tests--b 'subr-tests--c)
+  (should (equal (function-alias-p 'subr-tests--a)
+                 '(subr-tests--b subr-tests--c)))
+
+  (defalias 'subr-tests--d 'subr-tests--e)
+  (defalias 'subr-tests--e 'subr-tests--d)
+  (should-error (function-alias-p 'subr-tests--d))
+  (should (equal (function-alias-p 'subr-tests--d t)
+                 '(subr-tests--e))))
+
 (provide 'subr-tests)
 ;;; subr-tests.el ends here



reply via email to

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