emacs-diffs
[Top][All Lists]
Advanced

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

feature/android c389df992a9: Merge remote-tracking branch 'origin/master


From: Po Lu
Subject: feature/android c389df992a9: Merge remote-tracking branch 'origin/master' into feature/android
Date: Sat, 3 Jun 2023 20:35:29 -0400 (EDT)

branch: feature/android
commit c389df992a9f054f9aced4f9a267730b2221e03a
Merge: a4bf3ad9586 6847c01568e
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Merge remote-tracking branch 'origin/master' into feature/android
---
 admin/notes/emba                            |   7 +-
 admin/notes/unicode                         |  17 +-
 admin/unidata/emoji-variation-sequences.txt | 723 ++++++++++++++++++++++++++++
 admin/unidata/emoji-zwj.awk                 |   3 +-
 doc/misc/calc.texi                          |   2 +-
 doc/misc/transient.texi                     |   6 +-
 etc/NEWS.29                                 |  13 +-
 lisp/calendar/todo-mode.el                  | 298 +++++++-----
 lisp/composite.el                           |   2 +-
 lisp/emacs-lisp/package.el                  |  19 +-
 lisp/info-look.el                           |   6 +-
 lisp/minibuffer.el                          |  13 +-
 lisp/net/browse-url.el                      |  13 +-
 lisp/plstore.el                             | 203 +++++++-
 lisp/progmodes/dockerfile-ts-mode.el        |   5 +-
 lisp/progmodes/go-ts-mode.el                |   1 +
 lisp/progmodes/java-ts-mode.el              |   3 +
 lisp/progmodes/project.el                   |   4 +-
 lisp/progmodes/python.el                    |  52 +-
 lisp/progmodes/rust-ts-mode.el              |  16 +-
 lisp/progmodes/typescript-ts-mode.el        |   2 +-
 lisp/simple.el                              |   3 +-
 lisp/textmodes/enriched.el                  |   1 +
 lisp/tmm.el                                 |  33 +-
 lisp/transient.el                           |  19 +-
 lisp/treesit.el                             |  42 +-
 lisp/use-package/use-package-core.el        |   3 +-
 lisp/wdired.el                              |   5 +-
 src/lread.c                                 |   4 +-
 test/infra/Dockerfile.emba                  |   2 +-
 test/infra/Makefile.in                      |  13 +-
 test/infra/gitlab-ci.yml                    |  23 +-
 test/infra/test-jobs.yml                    |  11 +
 test/lisp/progmodes/python-tests.el         | 144 ------
 test/lisp/use-package/use-package-tests.el  |  11 +
 35 files changed, 1309 insertions(+), 413 deletions(-)

diff --git a/admin/notes/emba b/admin/notes/emba
index 1f87a99ddc0..cad7a2e121c 100644
--- a/admin/notes/emba
+++ b/admin/notes/emba
@@ -107,12 +107,11 @@ via "make bootstrap".  In order to use the image, start a 
container
 like
 
   docker run --interactive --tty --env EMACS_EMBA_CI=1 --name emacs-inotify \
-    emacs-inotify /bin/sh -i
+    emacs-inotify /bin/bash -i
 
-In this container, change the current directory to "/checkout".  Now
-you can apply all commands known for Emacs, like
+In this container, your working directory is "/checkout".  Now you can
+apply all commands known for Emacs, like
 
-  cd /checkout
   make -C test files-tests.log
 
 While this container runs, you can also access its filesystem from
diff --git a/admin/notes/unicode b/admin/notes/unicode
index 0e000365da7..31c850af8fd 100644
--- a/admin/notes/unicode
+++ b/admin/notes/unicode
@@ -22,6 +22,7 @@ Emacs uses the following files from the Unicode Character 
Database
   . confusables.txt
   . emoji-data.txt
   . emoji-zwj-sequences.txt
+  . emoji-variation-sequences.txt
   . emoji-sequences.txt
   . BidiCharacterTest.txt
 
@@ -29,7 +30,7 @@ Emacs also uses the file emoji-test.txt which should be 
imported from
 the Unicode's Public/emoji/ directory, and IdnaMappingTable.txt from
 the Public/idna/ directory.
 
-First, the first 14 files, emoji-test.txt and IdnaMappingTable.txt
+First, the first 15 files, emoji-test.txt and IdnaMappingTable.txt
 need to be copied into admin/unidata/, and the file
 https://www.unicode.org/copyright.html should be copied over
 copyright.html in admin/unidata (some of them might need trailing
@@ -142,6 +143,20 @@ generated for auto-composition-emoji-eligible-codepoints by
 admin/unidata/emoji-zwj.awk.  Note that your emoji font might not have
 glyphs for the newest codepoints yet.
 
+Visit "emoji-variation-sequences.txt", and run the following lisp
+fragment to actually insert the described codepoints, then check that
+all the text in parentheses displays correctly (it can be helpful to
+have `glyphless-char-display-control' customized to show hex codes for
+variation selectors).
+
+(save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "^\\([0-9A-Z]+\\) \\([0-9A-Z]+\\).*(\\([^)]+\\))" 
nil t)
+   (let ((ch (string-to-number (match-string 1) 16))
+         (sel (string-to-number (match-string 2) 16))
+         (sp (match-string 3)))
+     (replace-match (format "%s %c%c " sp ch sel) nil nil nil 3))))
+
 Finally, etc/NEWS should be updated to announce the support for the
 new Unicode version.
 
diff --git a/admin/unidata/emoji-variation-sequences.txt 
b/admin/unidata/emoji-variation-sequences.txt
new file mode 100644
index 00000000000..f3396ada19d
--- /dev/null
+++ b/admin/unidata/emoji-variation-sequences.txt
@@ -0,0 +1,723 @@
+# emoji-variation-sequences.txt
+# Date: 2022-05-13, 21:54:24 GMT
+# © 2022 Unicode®, Inc.
+# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in 
the U.S. and other countries.
+# For terms of use, see https://www.unicode.org/terms_of_use.html
+#
+# Emoji Variation Sequences for UTS #51
+# Used with Emoji Version 15.0 and subsequent minor revisions (if any)
+#
+# For documentation and usage, see https://www.unicode.org/reports/tr51
+#
+0023 FE0E  ; text style;  # (1.1 #︎ ) NUMBER SIGN
+0023 FE0F  ; emoji style; # (1.1 #️ ) NUMBER SIGN
+002A FE0E  ; text style;  # (1.1 *︎ ) ASTERISK
+002A FE0F  ; emoji style; # (1.1 *️ ) ASTERISK
+0030 FE0E  ; text style;  # (1.1 0︎ ) DIGIT ZERO
+0030 FE0F  ; emoji style; # (1.1 0️ ) DIGIT ZERO
+0031 FE0E  ; text style;  # (1.1 1︎ ) DIGIT ONE
+0031 FE0F  ; emoji style; # (1.1 1️ ) DIGIT ONE
+0032 FE0E  ; text style;  # (1.1 2︎ ) DIGIT TWO
+0032 FE0F  ; emoji style; # (1.1 2️ ) DIGIT TWO
+0033 FE0E  ; text style;  # (1.1 3︎ ) DIGIT THREE
+0033 FE0F  ; emoji style; # (1.1 3️ ) DIGIT THREE
+0034 FE0E  ; text style;  # (1.1 4︎ ) DIGIT FOUR
+0034 FE0F  ; emoji style; # (1.1 4️ ) DIGIT FOUR
+0035 FE0E  ; text style;  # (1.1 5︎ ) DIGIT FIVE
+0035 FE0F  ; emoji style; # (1.1 5️ ) DIGIT FIVE
+0036 FE0E  ; text style;  # (1.1 6︎ ) DIGIT SIX
+0036 FE0F  ; emoji style; # (1.1 6️ ) DIGIT SIX
+0037 FE0E  ; text style;  # (1.1 7︎ ) DIGIT SEVEN
+0037 FE0F  ; emoji style; # (1.1 7️ ) DIGIT SEVEN
+0038 FE0E  ; text style;  # (1.1 8︎ ) DIGIT EIGHT
+0038 FE0F  ; emoji style; # (1.1 8️ ) DIGIT EIGHT
+0039 FE0E  ; text style;  # (1.1 9︎ ) DIGIT NINE
+0039 FE0F  ; emoji style; # (1.1 9️ ) DIGIT NINE
+00A9 FE0E  ; text style;  # (1.1 ©︎ ) COPYRIGHT SIGN
+00A9 FE0F  ; emoji style; # (1.1 ©️ ) COPYRIGHT SIGN
+00AE FE0E  ; text style;  # (1.1 ®︎ ) REGISTERED SIGN
+00AE FE0F  ; emoji style; # (1.1 ®️ ) REGISTERED SIGN
+203C FE0E  ; text style;  # (1.1 ‼︎ ) DOUBLE EXCLAMATION MARK
+203C FE0F  ; emoji style; # (1.1 ‼️ ) DOUBLE EXCLAMATION MARK
+2049 FE0E  ; text style;  # (3.0 ⁉︎ ) EXCLAMATION QUESTION MARK
+2049 FE0F  ; emoji style; # (3.0 ⁉️ ) EXCLAMATION QUESTION MARK
+2122 FE0E  ; text style;  # (1.1 ™︎ ) TRADE MARK SIGN
+2122 FE0F  ; emoji style; # (1.1 ™️ ) TRADE MARK SIGN
+2139 FE0E  ; text style;  # (3.0 ℹ︎ ) INFORMATION SOURCE
+2139 FE0F  ; emoji style; # (3.0 ℹ️ ) INFORMATION SOURCE
+2194 FE0E  ; text style;  # (1.1 ↔︎ ) LEFT RIGHT ARROW
+2194 FE0F  ; emoji style; # (1.1 ↔️ ) LEFT RIGHT ARROW
+2195 FE0E  ; text style;  # (1.1 ↕︎ ) UP DOWN ARROW
+2195 FE0F  ; emoji style; # (1.1 ↕️ ) UP DOWN ARROW
+2196 FE0E  ; text style;  # (1.1 ↖︎ ) NORTH WEST ARROW
+2196 FE0F  ; emoji style; # (1.1 ↖️ ) NORTH WEST ARROW
+2197 FE0E  ; text style;  # (1.1 ↗︎ ) NORTH EAST ARROW
+2197 FE0F  ; emoji style; # (1.1 ↗️ ) NORTH EAST ARROW
+2198 FE0E  ; text style;  # (1.1 ↘︎ ) SOUTH EAST ARROW
+2198 FE0F  ; emoji style; # (1.1 ↘️ ) SOUTH EAST ARROW
+2199 FE0E  ; text style;  # (1.1 ↙︎ ) SOUTH WEST ARROW
+2199 FE0F  ; emoji style; # (1.1 ↙️ ) SOUTH WEST ARROW
+21A9 FE0E  ; text style;  # (1.1 ↩︎ ) LEFTWARDS ARROW WITH HOOK
+21A9 FE0F  ; emoji style; # (1.1 ↩️ ) LEFTWARDS ARROW WITH HOOK
+21AA FE0E  ; text style;  # (1.1 ↪︎ ) RIGHTWARDS ARROW WITH HOOK
+21AA FE0F  ; emoji style; # (1.1 ↪️ ) RIGHTWARDS ARROW WITH HOOK
+231A FE0E  ; text style;  # (1.1 ⌚︎ ) WATCH
+231A FE0F  ; emoji style; # (1.1 ⌚️ ) WATCH
+231B FE0E  ; text style;  # (1.1 ⌛︎ ) HOURGLASS
+231B FE0F  ; emoji style; # (1.1 ⌛️ ) HOURGLASS
+2328 FE0E  ; text style;  # (1.1 ⌨︎ ) KEYBOARD
+2328 FE0F  ; emoji style; # (1.1 ⌨️ ) KEYBOARD
+23CF FE0E  ; text style;  # (4.0 ⏏︎ ) EJECT SYMBOL
+23CF FE0F  ; emoji style; # (4.0 ⏏️ ) EJECT SYMBOL
+23E9 FE0E  ; text style;  # (6.0 ⏩︎ ) BLACK RIGHT-POINTING DOUBLE TRIANGLE
+23E9 FE0F  ; emoji style; # (6.0 ⏩️ ) BLACK RIGHT-POINTING DOUBLE TRIANGLE
+23EA FE0E  ; text style;  # (6.0 ⏪︎ ) BLACK LEFT-POINTING DOUBLE TRIANGLE
+23EA FE0F  ; emoji style; # (6.0 ⏪️ ) BLACK LEFT-POINTING DOUBLE TRIANGLE
+23ED FE0E  ; text style;  # (6.0 ⏭︎ ) BLACK RIGHT-POINTING DOUBLE TRIANGLE 
WITH VERTICAL BAR
+23ED FE0F  ; emoji style; # (6.0 ⏭️ ) BLACK RIGHT-POINTING DOUBLE TRIANGLE 
WITH VERTICAL BAR
+23EE FE0E  ; text style;  # (6.0 ⏮︎ ) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH 
VERTICAL BAR
+23EE FE0F  ; emoji style; # (6.0 ⏮️ ) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH 
VERTICAL BAR
+23EF FE0E  ; text style;  # (6.0 ⏯︎ ) BLACK RIGHT-POINTING TRIANGLE WITH 
DOUBLE VERTICAL BAR
+23EF FE0F  ; emoji style; # (6.0 ⏯️ ) BLACK RIGHT-POINTING TRIANGLE WITH 
DOUBLE VERTICAL BAR
+23F1 FE0E  ; text style;  # (6.0 ⏱︎ ) STOPWATCH
+23F1 FE0F  ; emoji style; # (6.0 ⏱️ ) STOPWATCH
+23F2 FE0E  ; text style;  # (6.0 ⏲︎ ) TIMER CLOCK
+23F2 FE0F  ; emoji style; # (6.0 ⏲️ ) TIMER CLOCK
+23F3 FE0E  ; text style;  # (6.0 ⏳︎ ) HOURGLASS WITH FLOWING SAND
+23F3 FE0F  ; emoji style; # (6.0 ⏳️ ) HOURGLASS WITH FLOWING SAND
+23F8 FE0E  ; text style;  # (7.0 ⏸︎ ) DOUBLE VERTICAL BAR
+23F8 FE0F  ; emoji style; # (7.0 ⏸️ ) DOUBLE VERTICAL BAR
+23F9 FE0E  ; text style;  # (7.0 ⏹︎ ) BLACK SQUARE FOR STOP
+23F9 FE0F  ; emoji style; # (7.0 ⏹️ ) BLACK SQUARE FOR STOP
+23FA FE0E  ; text style;  # (7.0 ⏺︎ ) BLACK CIRCLE FOR RECORD
+23FA FE0F  ; emoji style; # (7.0 ⏺️ ) BLACK CIRCLE FOR RECORD
+24C2 FE0E  ; text style;  # (1.1 Ⓜ︎ ) CIRCLED LATIN CAPITAL LETTER M
+24C2 FE0F  ; emoji style; # (1.1 Ⓜ️ ) CIRCLED LATIN CAPITAL LETTER M
+25AA FE0E  ; text style;  # (1.1 ▪︎ ) BLACK SMALL SQUARE
+25AA FE0F  ; emoji style; # (1.1 ▪️ ) BLACK SMALL SQUARE
+25AB FE0E  ; text style;  # (1.1 ▫︎ ) WHITE SMALL SQUARE
+25AB FE0F  ; emoji style; # (1.1 ▫️ ) WHITE SMALL SQUARE
+25B6 FE0E  ; text style;  # (1.1 ▶︎ ) BLACK RIGHT-POINTING TRIANGLE
+25B6 FE0F  ; emoji style; # (1.1 ▶️ ) BLACK RIGHT-POINTING TRIANGLE
+25C0 FE0E  ; text style;  # (1.1 ◀︎ ) BLACK LEFT-POINTING TRIANGLE
+25C0 FE0F  ; emoji style; # (1.1 ◀️ ) BLACK LEFT-POINTING TRIANGLE
+25FB FE0E  ; text style;  # (3.2 ◻︎ ) WHITE MEDIUM SQUARE
+25FB FE0F  ; emoji style; # (3.2 ◻️ ) WHITE MEDIUM SQUARE
+25FC FE0E  ; text style;  # (3.2 ◼︎ ) BLACK MEDIUM SQUARE
+25FC FE0F  ; emoji style; # (3.2 ◼️ ) BLACK MEDIUM SQUARE
+25FD FE0E  ; text style;  # (3.2 ◽︎ ) WHITE MEDIUM SMALL SQUARE
+25FD FE0F  ; emoji style; # (3.2 ◽️ ) WHITE MEDIUM SMALL SQUARE
+25FE FE0E  ; text style;  # (3.2 ◾︎ ) BLACK MEDIUM SMALL SQUARE
+25FE FE0F  ; emoji style; # (3.2 ◾️ ) BLACK MEDIUM SMALL SQUARE
+2600 FE0E  ; text style;  # (1.1 ☀︎ ) BLACK SUN WITH RAYS
+2600 FE0F  ; emoji style; # (1.1 ☀️ ) BLACK SUN WITH RAYS
+2601 FE0E  ; text style;  # (1.1 ☁︎ ) CLOUD
+2601 FE0F  ; emoji style; # (1.1 ☁️ ) CLOUD
+2602 FE0E  ; text style;  # (1.1 ☂︎ ) UMBRELLA
+2602 FE0F  ; emoji style; # (1.1 ☂️ ) UMBRELLA
+2603 FE0E  ; text style;  # (1.1 ☃︎ ) SNOWMAN
+2603 FE0F  ; emoji style; # (1.1 ☃️ ) SNOWMAN
+2604 FE0E  ; text style;  # (1.1 ☄︎ ) COMET
+2604 FE0F  ; emoji style; # (1.1 ☄️ ) COMET
+260E FE0E  ; text style;  # (1.1 ☎︎ ) BLACK TELEPHONE
+260E FE0F  ; emoji style; # (1.1 ☎️ ) BLACK TELEPHONE
+2611 FE0E  ; text style;  # (1.1 ☑︎ ) BALLOT BOX WITH CHECK
+2611 FE0F  ; emoji style; # (1.1 ☑️ ) BALLOT BOX WITH CHECK
+2614 FE0E  ; text style;  # (4.0 ☔︎ ) UMBRELLA WITH RAIN DROPS
+2614 FE0F  ; emoji style; # (4.0 ☔️ ) UMBRELLA WITH RAIN DROPS
+2615 FE0E  ; text style;  # (4.0 ☕︎ ) HOT BEVERAGE
+2615 FE0F  ; emoji style; # (4.0 ☕️ ) HOT BEVERAGE
+2618 FE0E  ; text style;  # (4.1 ☘︎ ) SHAMROCK
+2618 FE0F  ; emoji style; # (4.1 ☘️ ) SHAMROCK
+261D FE0E  ; text style;  # (1.1 ☝︎ ) WHITE UP POINTING INDEX
+261D FE0F  ; emoji style; # (1.1 ☝️ ) WHITE UP POINTING INDEX
+2620 FE0E  ; text style;  # (1.1 ☠︎ ) SKULL AND CROSSBONES
+2620 FE0F  ; emoji style; # (1.1 ☠️ ) SKULL AND CROSSBONES
+2622 FE0E  ; text style;  # (1.1 ☢︎ ) RADIOACTIVE SIGN
+2622 FE0F  ; emoji style; # (1.1 ☢️ ) RADIOACTIVE SIGN
+2623 FE0E  ; text style;  # (1.1 ☣︎ ) BIOHAZARD SIGN
+2623 FE0F  ; emoji style; # (1.1 ☣️ ) BIOHAZARD SIGN
+2626 FE0E  ; text style;  # (1.1 ☦︎ ) ORTHODOX CROSS
+2626 FE0F  ; emoji style; # (1.1 ☦️ ) ORTHODOX CROSS
+262A FE0E  ; text style;  # (1.1 ☪︎ ) STAR AND CRESCENT
+262A FE0F  ; emoji style; # (1.1 ☪️ ) STAR AND CRESCENT
+262E FE0E  ; text style;  # (1.1 ☮︎ ) PEACE SYMBOL
+262E FE0F  ; emoji style; # (1.1 ☮️ ) PEACE SYMBOL
+262F FE0E  ; text style;  # (1.1 ☯︎ ) YIN YANG
+262F FE0F  ; emoji style; # (1.1 ☯️ ) YIN YANG
+2638 FE0E  ; text style;  # (1.1 ☸︎ ) WHEEL OF DHARMA
+2638 FE0F  ; emoji style; # (1.1 ☸️ ) WHEEL OF DHARMA
+2639 FE0E  ; text style;  # (1.1 ☹︎ ) WHITE FROWNING FACE
+2639 FE0F  ; emoji style; # (1.1 ☹️ ) WHITE FROWNING FACE
+263A FE0E  ; text style;  # (1.1 ☺︎ ) WHITE SMILING FACE
+263A FE0F  ; emoji style; # (1.1 ☺️ ) WHITE SMILING FACE
+2640 FE0E  ; text style;  # (1.1 ♀︎ ) FEMALE SIGN
+2640 FE0F  ; emoji style; # (1.1 ♀️ ) FEMALE SIGN
+2642 FE0E  ; text style;  # (1.1 ♂︎ ) MALE SIGN
+2642 FE0F  ; emoji style; # (1.1 ♂️ ) MALE SIGN
+2648 FE0E  ; text style;  # (1.1 ♈︎ ) ARIES
+2648 FE0F  ; emoji style; # (1.1 ♈️ ) ARIES
+2649 FE0E  ; text style;  # (1.1 ♉︎ ) TAURUS
+2649 FE0F  ; emoji style; # (1.1 ♉️ ) TAURUS
+264A FE0E  ; text style;  # (1.1 ♊︎ ) GEMINI
+264A FE0F  ; emoji style; # (1.1 ♊️ ) GEMINI
+264B FE0E  ; text style;  # (1.1 ♋︎ ) CANCER
+264B FE0F  ; emoji style; # (1.1 ♋️ ) CANCER
+264C FE0E  ; text style;  # (1.1 ♌︎ ) LEO
+264C FE0F  ; emoji style; # (1.1 ♌️ ) LEO
+264D FE0E  ; text style;  # (1.1 ♍︎ ) VIRGO
+264D FE0F  ; emoji style; # (1.1 ♍️ ) VIRGO
+264E FE0E  ; text style;  # (1.1 ♎︎ ) LIBRA
+264E FE0F  ; emoji style; # (1.1 ♎️ ) LIBRA
+264F FE0E  ; text style;  # (1.1 ♏︎ ) SCORPIUS
+264F FE0F  ; emoji style; # (1.1 ♏️ ) SCORPIUS
+2650 FE0E  ; text style;  # (1.1 ♐︎ ) SAGITTARIUS
+2650 FE0F  ; emoji style; # (1.1 ♐️ ) SAGITTARIUS
+2651 FE0E  ; text style;  # (1.1 ♑︎ ) CAPRICORN
+2651 FE0F  ; emoji style; # (1.1 ♑️ ) CAPRICORN
+2652 FE0E  ; text style;  # (1.1 ♒︎ ) AQUARIUS
+2652 FE0F  ; emoji style; # (1.1 ♒️ ) AQUARIUS
+2653 FE0E  ; text style;  # (1.1 ♓︎ ) PISCES
+2653 FE0F  ; emoji style; # (1.1 ♓️ ) PISCES
+265F FE0E  ; text style;  # (1.1 ♟︎ ) BLACK CHESS PAWN
+265F FE0F  ; emoji style; # (1.1 ♟️ ) BLACK CHESS PAWN
+2660 FE0E  ; text style;  # (1.1 ♠︎ ) BLACK SPADE SUIT
+2660 FE0F  ; emoji style; # (1.1 ♠️ ) BLACK SPADE SUIT
+2663 FE0E  ; text style;  # (1.1 ♣︎ ) BLACK CLUB SUIT
+2663 FE0F  ; emoji style; # (1.1 ♣️ ) BLACK CLUB SUIT
+2665 FE0E  ; text style;  # (1.1 ♥︎ ) BLACK HEART SUIT
+2665 FE0F  ; emoji style; # (1.1 ♥️ ) BLACK HEART SUIT
+2666 FE0E  ; text style;  # (1.1 ♦︎ ) BLACK DIAMOND SUIT
+2666 FE0F  ; emoji style; # (1.1 ♦️ ) BLACK DIAMOND SUIT
+2668 FE0E  ; text style;  # (1.1 ♨︎ ) HOT SPRINGS
+2668 FE0F  ; emoji style; # (1.1 ♨️ ) HOT SPRINGS
+267B FE0E  ; text style;  # (3.2 ♻︎ ) BLACK UNIVERSAL RECYCLING SYMBOL
+267B FE0F  ; emoji style; # (3.2 ♻️ ) BLACK UNIVERSAL RECYCLING SYMBOL
+267E FE0E  ; text style;  # (4.1 ♾︎ ) PERMANENT PAPER SIGN
+267E FE0F  ; emoji style; # (4.1 ♾️ ) PERMANENT PAPER SIGN
+267F FE0E  ; text style;  # (4.1 ♿︎ ) WHEELCHAIR SYMBOL
+267F FE0F  ; emoji style; # (4.1 ♿️ ) WHEELCHAIR SYMBOL
+2692 FE0E  ; text style;  # (4.1 ⚒︎ ) HAMMER AND PICK
+2692 FE0F  ; emoji style; # (4.1 ⚒️ ) HAMMER AND PICK
+2693 FE0E  ; text style;  # (4.1 ⚓︎ ) ANCHOR
+2693 FE0F  ; emoji style; # (4.1 ⚓️ ) ANCHOR
+2694 FE0E  ; text style;  # (4.1 ⚔︎ ) CROSSED SWORDS
+2694 FE0F  ; emoji style; # (4.1 ⚔️ ) CROSSED SWORDS
+2695 FE0E  ; text style;  # (4.1 ⚕︎ ) STAFF OF AESCULAPIUS
+2695 FE0F  ; emoji style; # (4.1 ⚕️ ) STAFF OF AESCULAPIUS
+2696 FE0E  ; text style;  # (4.1 ⚖︎ ) SCALES
+2696 FE0F  ; emoji style; # (4.1 ⚖️ ) SCALES
+2697 FE0E  ; text style;  # (4.1 ⚗︎ ) ALEMBIC
+2697 FE0F  ; emoji style; # (4.1 ⚗️ ) ALEMBIC
+2699 FE0E  ; text style;  # (4.1 ⚙︎ ) GEAR
+2699 FE0F  ; emoji style; # (4.1 ⚙️ ) GEAR
+269B FE0E  ; text style;  # (4.1 ⚛︎ ) ATOM SYMBOL
+269B FE0F  ; emoji style; # (4.1 ⚛️ ) ATOM SYMBOL
+269C FE0E  ; text style;  # (4.1 ⚜︎ ) FLEUR-DE-LIS
+269C FE0F  ; emoji style; # (4.1 ⚜️ ) FLEUR-DE-LIS
+26A0 FE0E  ; text style;  # (4.0 ⚠︎ ) WARNING SIGN
+26A0 FE0F  ; emoji style; # (4.0 ⚠️ ) WARNING SIGN
+26A1 FE0E  ; text style;  # (4.0 ⚡︎ ) HIGH VOLTAGE SIGN
+26A1 FE0F  ; emoji style; # (4.0 ⚡️ ) HIGH VOLTAGE SIGN
+26A7 FE0E  ; text style;  # (4.1 ⚧︎ ) MALE WITH STROKE AND MALE AND FEMALE SIGN
+26A7 FE0F  ; emoji style; # (4.1 ⚧️ ) MALE WITH STROKE AND MALE AND FEMALE SIGN
+26AA FE0E  ; text style;  # (4.1 ⚪︎ ) MEDIUM WHITE CIRCLE
+26AA FE0F  ; emoji style; # (4.1 ⚪️ ) MEDIUM WHITE CIRCLE
+26AB FE0E  ; text style;  # (4.1 ⚫︎ ) MEDIUM BLACK CIRCLE
+26AB FE0F  ; emoji style; # (4.1 ⚫️ ) MEDIUM BLACK CIRCLE
+26B0 FE0E  ; text style;  # (4.1 ⚰︎ ) COFFIN
+26B0 FE0F  ; emoji style; # (4.1 ⚰️ ) COFFIN
+26B1 FE0E  ; text style;  # (4.1 ⚱︎ ) FUNERAL URN
+26B1 FE0F  ; emoji style; # (4.1 ⚱️ ) FUNERAL URN
+26BD FE0E  ; text style;  # (5.2 ⚽︎ ) SOCCER BALL
+26BD FE0F  ; emoji style; # (5.2 ⚽️ ) SOCCER BALL
+26BE FE0E  ; text style;  # (5.2 ⚾︎ ) BASEBALL
+26BE FE0F  ; emoji style; # (5.2 ⚾️ ) BASEBALL
+26C4 FE0E  ; text style;  # (5.2 ⛄︎ ) SNOWMAN WITHOUT SNOW
+26C4 FE0F  ; emoji style; # (5.2 ⛄️ ) SNOWMAN WITHOUT SNOW
+26C5 FE0E  ; text style;  # (5.2 ⛅︎ ) SUN BEHIND CLOUD
+26C5 FE0F  ; emoji style; # (5.2 ⛅️ ) SUN BEHIND CLOUD
+26C8 FE0E  ; text style;  # (5.2 ⛈︎ ) THUNDER CLOUD AND RAIN
+26C8 FE0F  ; emoji style; # (5.2 ⛈️ ) THUNDER CLOUD AND RAIN
+26CF FE0E  ; text style;  # (5.2 ⛏︎ ) PICK
+26CF FE0F  ; emoji style; # (5.2 ⛏️ ) PICK
+26D1 FE0E  ; text style;  # (5.2 ⛑︎ ) HELMET WITH WHITE CROSS
+26D1 FE0F  ; emoji style; # (5.2 ⛑️ ) HELMET WITH WHITE CROSS
+26D3 FE0E  ; text style;  # (5.2 ⛓︎ ) CHAINS
+26D3 FE0F  ; emoji style; # (5.2 ⛓️ ) CHAINS
+26D4 FE0E  ; text style;  # (5.2 ⛔︎ ) NO ENTRY
+26D4 FE0F  ; emoji style; # (5.2 ⛔️ ) NO ENTRY
+26E9 FE0E  ; text style;  # (5.2 ⛩︎ ) SHINTO SHRINE
+26E9 FE0F  ; emoji style; # (5.2 ⛩️ ) SHINTO SHRINE
+26EA FE0E  ; text style;  # (5.2 ⛪︎ ) CHURCH
+26EA FE0F  ; emoji style; # (5.2 ⛪️ ) CHURCH
+26F0 FE0E  ; text style;  # (5.2 ⛰︎ ) MOUNTAIN
+26F0 FE0F  ; emoji style; # (5.2 ⛰️ ) MOUNTAIN
+26F1 FE0E  ; text style;  # (5.2 ⛱︎ ) UMBRELLA ON GROUND
+26F1 FE0F  ; emoji style; # (5.2 ⛱️ ) UMBRELLA ON GROUND
+26F2 FE0E  ; text style;  # (5.2 ⛲︎ ) FOUNTAIN
+26F2 FE0F  ; emoji style; # (5.2 ⛲️ ) FOUNTAIN
+26F3 FE0E  ; text style;  # (5.2 ⛳︎ ) FLAG IN HOLE
+26F3 FE0F  ; emoji style; # (5.2 ⛳️ ) FLAG IN HOLE
+26F4 FE0E  ; text style;  # (5.2 ⛴︎ ) FERRY
+26F4 FE0F  ; emoji style; # (5.2 ⛴️ ) FERRY
+26F5 FE0E  ; text style;  # (5.2 ⛵︎ ) SAILBOAT
+26F5 FE0F  ; emoji style; # (5.2 ⛵️ ) SAILBOAT
+26F7 FE0E  ; text style;  # (5.2 ⛷︎ ) SKIER
+26F7 FE0F  ; emoji style; # (5.2 ⛷️ ) SKIER
+26F8 FE0E  ; text style;  # (5.2 ⛸︎ ) ICE SKATE
+26F8 FE0F  ; emoji style; # (5.2 ⛸️ ) ICE SKATE
+26F9 FE0E  ; text style;  # (5.2 ⛹︎ ) PERSON WITH BALL
+26F9 FE0F  ; emoji style; # (5.2 ⛹️ ) PERSON WITH BALL
+26FA FE0E  ; text style;  # (5.2 ⛺︎ ) TENT
+26FA FE0F  ; emoji style; # (5.2 ⛺️ ) TENT
+26FD FE0E  ; text style;  # (5.2 ⛽︎ ) FUEL PUMP
+26FD FE0F  ; emoji style; # (5.2 ⛽️ ) FUEL PUMP
+2702 FE0E  ; text style;  # (1.1 ✂︎ ) BLACK SCISSORS
+2702 FE0F  ; emoji style; # (1.1 ✂️ ) BLACK SCISSORS
+2708 FE0E  ; text style;  # (1.1 ✈︎ ) AIRPLANE
+2708 FE0F  ; emoji style; # (1.1 ✈️ ) AIRPLANE
+2709 FE0E  ; text style;  # (1.1 ✉︎ ) ENVELOPE
+2709 FE0F  ; emoji style; # (1.1 ✉️ ) ENVELOPE
+270C FE0E  ; text style;  # (1.1 ✌︎ ) VICTORY HAND
+270C FE0F  ; emoji style; # (1.1 ✌️ ) VICTORY HAND
+270D FE0E  ; text style;  # (1.1 ✍︎ ) WRITING HAND
+270D FE0F  ; emoji style; # (1.1 ✍️ ) WRITING HAND
+270F FE0E  ; text style;  # (1.1 ✏︎ ) PENCIL
+270F FE0F  ; emoji style; # (1.1 ✏️ ) PENCIL
+2712 FE0E  ; text style;  # (1.1 ✒︎ ) BLACK NIB
+2712 FE0F  ; emoji style; # (1.1 ✒️ ) BLACK NIB
+2714 FE0E  ; text style;  # (1.1 ✔︎ ) HEAVY CHECK MARK
+2714 FE0F  ; emoji style; # (1.1 ✔️ ) HEAVY CHECK MARK
+2716 FE0E  ; text style;  # (1.1 ✖︎ ) HEAVY MULTIPLICATION X
+2716 FE0F  ; emoji style; # (1.1 ✖️ ) HEAVY MULTIPLICATION X
+271D FE0E  ; text style;  # (1.1 ✝︎ ) LATIN CROSS
+271D FE0F  ; emoji style; # (1.1 ✝️ ) LATIN CROSS
+2721 FE0E  ; text style;  # (1.1 ✡︎ ) STAR OF DAVID
+2721 FE0F  ; emoji style; # (1.1 ✡️ ) STAR OF DAVID
+2733 FE0E  ; text style;  # (1.1 ✳︎ ) EIGHT SPOKED ASTERISK
+2733 FE0F  ; emoji style; # (1.1 ✳️ ) EIGHT SPOKED ASTERISK
+2734 FE0E  ; text style;  # (1.1 ✴︎ ) EIGHT POINTED BLACK STAR
+2734 FE0F  ; emoji style; # (1.1 ✴️ ) EIGHT POINTED BLACK STAR
+2744 FE0E  ; text style;  # (1.1 ❄︎ ) SNOWFLAKE
+2744 FE0F  ; emoji style; # (1.1 ❄️ ) SNOWFLAKE
+2747 FE0E  ; text style;  # (1.1 ❇︎ ) SPARKLE
+2747 FE0F  ; emoji style; # (1.1 ❇️ ) SPARKLE
+2753 FE0E  ; text style;  # (6.0 ❓︎ ) BLACK QUESTION MARK ORNAMENT
+2753 FE0F  ; emoji style; # (6.0 ❓️ ) BLACK QUESTION MARK ORNAMENT
+2757 FE0E  ; text style;  # (5.2 ❗︎ ) HEAVY EXCLAMATION MARK SYMBOL
+2757 FE0F  ; emoji style; # (5.2 ❗️ ) HEAVY EXCLAMATION MARK SYMBOL
+2763 FE0E  ; text style;  # (1.1 ❣︎ ) HEAVY HEART EXCLAMATION MARK ORNAMENT
+2763 FE0F  ; emoji style; # (1.1 ❣️ ) HEAVY HEART EXCLAMATION MARK ORNAMENT
+2764 FE0E  ; text style;  # (1.1 ❤︎ ) HEAVY BLACK HEART
+2764 FE0F  ; emoji style; # (1.1 ❤️ ) HEAVY BLACK HEART
+27A1 FE0E  ; text style;  # (1.1 ➡︎ ) BLACK RIGHTWARDS ARROW
+27A1 FE0F  ; emoji style; # (1.1 ➡️ ) BLACK RIGHTWARDS ARROW
+2934 FE0E  ; text style;  # (3.2 ⤴︎ ) ARROW POINTING RIGHTWARDS THEN CURVING 
UPWARDS
+2934 FE0F  ; emoji style; # (3.2 ⤴️ ) ARROW POINTING RIGHTWARDS THEN CURVING 
UPWARDS
+2935 FE0E  ; text style;  # (3.2 ⤵︎ ) ARROW POINTING RIGHTWARDS THEN CURVING 
DOWNWARDS
+2935 FE0F  ; emoji style; # (3.2 ⤵️ ) ARROW POINTING RIGHTWARDS THEN CURVING 
DOWNWARDS
+2B05 FE0E  ; text style;  # (4.0 ⬅︎ ) LEFTWARDS BLACK ARROW
+2B05 FE0F  ; emoji style; # (4.0 ⬅️ ) LEFTWARDS BLACK ARROW
+2B06 FE0E  ; text style;  # (4.0 ⬆︎ ) UPWARDS BLACK ARROW
+2B06 FE0F  ; emoji style; # (4.0 ⬆️ ) UPWARDS BLACK ARROW
+2B07 FE0E  ; text style;  # (4.0 ⬇︎ ) DOWNWARDS BLACK ARROW
+2B07 FE0F  ; emoji style; # (4.0 ⬇️ ) DOWNWARDS BLACK ARROW
+2B1B FE0E  ; text style;  # (5.1 ⬛︎ ) BLACK LARGE SQUARE
+2B1B FE0F  ; emoji style; # (5.1 ⬛️ ) BLACK LARGE SQUARE
+2B1C FE0E  ; text style;  # (5.1 ⬜︎ ) WHITE LARGE SQUARE
+2B1C FE0F  ; emoji style; # (5.1 ⬜️ ) WHITE LARGE SQUARE
+2B50 FE0E  ; text style;  # (5.1 ⭐︎ ) WHITE MEDIUM STAR
+2B50 FE0F  ; emoji style; # (5.1 ⭐️ ) WHITE MEDIUM STAR
+2B55 FE0E  ; text style;  # (5.2 ⭕︎ ) HEAVY LARGE CIRCLE
+2B55 FE0F  ; emoji style; # (5.2 ⭕️ ) HEAVY LARGE CIRCLE
+3030 FE0E  ; text style;  # (1.1 〰︎ ) WAVY DASH
+3030 FE0F  ; emoji style; # (1.1 〰️ ) WAVY DASH
+303D FE0E  ; text style;  # (3.2 〽︎ ) PART ALTERNATION MARK
+303D FE0F  ; emoji style; # (3.2 〽️ ) PART ALTERNATION MARK
+3297 FE0E  ; text style;  # (1.1 ㊗︎ ) CIRCLED IDEOGRAPH CONGRATULATION
+3297 FE0F  ; emoji style; # (1.1 ㊗️ ) CIRCLED IDEOGRAPH CONGRATULATION
+3299 FE0E  ; text style;  # (1.1 ㊙︎ ) CIRCLED IDEOGRAPH SECRET
+3299 FE0F  ; emoji style; # (1.1 ㊙️ ) CIRCLED IDEOGRAPH SECRET
+1F004 FE0E ; text style;  # (5.1 🀄︎ ) MAHJONG TILE RED DRAGON
+1F004 FE0F ; emoji style; # (5.1 🀄️ ) MAHJONG TILE RED DRAGON
+1F170 FE0E ; text style;  # (6.0 🅰︎ ) NEGATIVE SQUARED LATIN CAPITAL LETTER A
+1F170 FE0F ; emoji style; # (6.0 🅰️ ) NEGATIVE SQUARED LATIN CAPITAL LETTER A
+1F171 FE0E ; text style;  # (6.0 🅱︎ ) NEGATIVE SQUARED LATIN CAPITAL LETTER B
+1F171 FE0F ; emoji style; # (6.0 🅱️ ) NEGATIVE SQUARED LATIN CAPITAL LETTER B
+1F17E FE0E ; text style;  # (6.0 🅾︎ ) NEGATIVE SQUARED LATIN CAPITAL LETTER O
+1F17E FE0F ; emoji style; # (6.0 🅾️ ) NEGATIVE SQUARED LATIN CAPITAL LETTER O
+1F17F FE0E ; text style;  # (5.2 🅿︎ ) NEGATIVE SQUARED LATIN CAPITAL LETTER P
+1F17F FE0F ; emoji style; # (5.2 🅿️ ) NEGATIVE SQUARED LATIN CAPITAL LETTER P
+1F202 FE0E ; text style;  # (6.0 🈂︎ ) SQUARED KATAKANA SA
+1F202 FE0F ; emoji style; # (6.0 🈂️ ) SQUARED KATAKANA SA
+1F21A FE0E ; text style;  # (5.2 🈚︎ ) SQUARED CJK UNIFIED IDEOGRAPH-7121
+1F21A FE0F ; emoji style; # (5.2 🈚️ ) SQUARED CJK UNIFIED IDEOGRAPH-7121
+1F22F FE0E ; text style;  # (5.2 🈯︎ ) SQUARED CJK UNIFIED IDEOGRAPH-6307
+1F22F FE0F ; emoji style; # (5.2 🈯️ ) SQUARED CJK UNIFIED IDEOGRAPH-6307
+1F237 FE0E ; text style;  # (6.0 🈷︎ ) SQUARED CJK UNIFIED IDEOGRAPH-6708
+1F237 FE0F ; emoji style; # (6.0 🈷️ ) SQUARED CJK UNIFIED IDEOGRAPH-6708
+1F30D FE0E ; text style;  # (6.0 🌍︎ ) EARTH GLOBE EUROPE-AFRICA
+1F30D FE0F ; emoji style; # (6.0 🌍️ ) EARTH GLOBE EUROPE-AFRICA
+1F30E FE0E ; text style;  # (6.0 🌎︎ ) EARTH GLOBE AMERICAS
+1F30E FE0F ; emoji style; # (6.0 🌎️ ) EARTH GLOBE AMERICAS
+1F30F FE0E ; text style;  # (6.0 🌏︎ ) EARTH GLOBE ASIA-AUSTRALIA
+1F30F FE0F ; emoji style; # (6.0 🌏️ ) EARTH GLOBE ASIA-AUSTRALIA
+1F315 FE0E ; text style;  # (6.0 🌕︎ ) FULL MOON SYMBOL
+1F315 FE0F ; emoji style; # (6.0 🌕️ ) FULL MOON SYMBOL
+1F31C FE0E ; text style;  # (6.0 🌜︎ ) LAST QUARTER MOON WITH FACE
+1F31C FE0F ; emoji style; # (6.0 🌜️ ) LAST QUARTER MOON WITH FACE
+1F321 FE0E ; text style;  # (7.0 🌡︎ ) THERMOMETER
+1F321 FE0F ; emoji style; # (7.0 🌡️ ) THERMOMETER
+1F324 FE0E ; text style;  # (7.0 🌤︎ ) WHITE SUN WITH SMALL CLOUD
+1F324 FE0F ; emoji style; # (7.0 🌤️ ) WHITE SUN WITH SMALL CLOUD
+1F325 FE0E ; text style;  # (7.0 🌥︎ ) WHITE SUN BEHIND CLOUD
+1F325 FE0F ; emoji style; # (7.0 🌥️ ) WHITE SUN BEHIND CLOUD
+1F326 FE0E ; text style;  # (7.0 🌦︎ ) WHITE SUN BEHIND CLOUD WITH RAIN
+1F326 FE0F ; emoji style; # (7.0 🌦️ ) WHITE SUN BEHIND CLOUD WITH RAIN
+1F327 FE0E ; text style;  # (7.0 🌧︎ ) CLOUD WITH RAIN
+1F327 FE0F ; emoji style; # (7.0 🌧️ ) CLOUD WITH RAIN
+1F328 FE0E ; text style;  # (7.0 🌨︎ ) CLOUD WITH SNOW
+1F328 FE0F ; emoji style; # (7.0 🌨️ ) CLOUD WITH SNOW
+1F329 FE0E ; text style;  # (7.0 🌩︎ ) CLOUD WITH LIGHTNING
+1F329 FE0F ; emoji style; # (7.0 🌩️ ) CLOUD WITH LIGHTNING
+1F32A FE0E ; text style;  # (7.0 🌪︎ ) CLOUD WITH TORNADO
+1F32A FE0F ; emoji style; # (7.0 🌪️ ) CLOUD WITH TORNADO
+1F32B FE0E ; text style;  # (7.0 🌫︎ ) FOG
+1F32B FE0F ; emoji style; # (7.0 🌫️ ) FOG
+1F32C FE0E ; text style;  # (7.0 🌬︎ ) WIND BLOWING FACE
+1F32C FE0F ; emoji style; # (7.0 🌬️ ) WIND BLOWING FACE
+1F336 FE0E ; text style;  # (7.0 🌶︎ ) HOT PEPPER
+1F336 FE0F ; emoji style; # (7.0 🌶️ ) HOT PEPPER
+1F378 FE0E ; text style;  # (6.0 🍸︎ ) COCKTAIL GLASS
+1F378 FE0F ; emoji style; # (6.0 🍸️ ) COCKTAIL GLASS
+1F37D FE0E ; text style;  # (7.0 🍽︎ ) FORK AND KNIFE WITH PLATE
+1F37D FE0F ; emoji style; # (7.0 🍽️ ) FORK AND KNIFE WITH PLATE
+1F393 FE0E ; text style;  # (6.0 🎓︎ ) GRADUATION CAP
+1F393 FE0F ; emoji style; # (6.0 🎓️ ) GRADUATION CAP
+1F396 FE0E ; text style;  # (7.0 🎖︎ ) MILITARY MEDAL
+1F396 FE0F ; emoji style; # (7.0 🎖️ ) MILITARY MEDAL
+1F397 FE0E ; text style;  # (7.0 🎗︎ ) REMINDER RIBBON
+1F397 FE0F ; emoji style; # (7.0 🎗️ ) REMINDER RIBBON
+1F399 FE0E ; text style;  # (7.0 🎙︎ ) STUDIO MICROPHONE
+1F399 FE0F ; emoji style; # (7.0 🎙️ ) STUDIO MICROPHONE
+1F39A FE0E ; text style;  # (7.0 🎚︎ ) LEVEL SLIDER
+1F39A FE0F ; emoji style; # (7.0 🎚️ ) LEVEL SLIDER
+1F39B FE0E ; text style;  # (7.0 🎛︎ ) CONTROL KNOBS
+1F39B FE0F ; emoji style; # (7.0 🎛️ ) CONTROL KNOBS
+1F39E FE0E ; text style;  # (7.0 🎞︎ ) FILM FRAMES
+1F39E FE0F ; emoji style; # (7.0 🎞️ ) FILM FRAMES
+1F39F FE0E ; text style;  # (7.0 🎟︎ ) ADMISSION TICKETS
+1F39F FE0F ; emoji style; # (7.0 🎟️ ) ADMISSION TICKETS
+1F3A7 FE0E ; text style;  # (6.0 🎧︎ ) HEADPHONE
+1F3A7 FE0F ; emoji style; # (6.0 🎧️ ) HEADPHONE
+1F3AC FE0E ; text style;  # (6.0 🎬︎ ) CLAPPER BOARD
+1F3AC FE0F ; emoji style; # (6.0 🎬️ ) CLAPPER BOARD
+1F3AD FE0E ; text style;  # (6.0 🎭︎ ) PERFORMING ARTS
+1F3AD FE0F ; emoji style; # (6.0 🎭️ ) PERFORMING ARTS
+1F3AE FE0E ; text style;  # (6.0 🎮︎ ) VIDEO GAME
+1F3AE FE0F ; emoji style; # (6.0 🎮️ ) VIDEO GAME
+1F3C2 FE0E ; text style;  # (6.0 🏂︎ ) SNOWBOARDER
+1F3C2 FE0F ; emoji style; # (6.0 🏂️ ) SNOWBOARDER
+1F3C4 FE0E ; text style;  # (6.0 🏄︎ ) SURFER
+1F3C4 FE0F ; emoji style; # (6.0 🏄️ ) SURFER
+1F3C6 FE0E ; text style;  # (6.0 🏆︎ ) TROPHY
+1F3C6 FE0F ; emoji style; # (6.0 🏆️ ) TROPHY
+1F3CA FE0E ; text style;  # (6.0 🏊︎ ) SWIMMER
+1F3CA FE0F ; emoji style; # (6.0 🏊️ ) SWIMMER
+1F3CB FE0E ; text style;  # (7.0 🏋︎ ) WEIGHT LIFTER
+1F3CB FE0F ; emoji style; # (7.0 🏋️ ) WEIGHT LIFTER
+1F3CC FE0E ; text style;  # (7.0 🏌︎ ) GOLFER
+1F3CC FE0F ; emoji style; # (7.0 🏌️ ) GOLFER
+1F3CD FE0E ; text style;  # (7.0 🏍︎ ) RACING MOTORCYCLE
+1F3CD FE0F ; emoji style; # (7.0 🏍️ ) RACING MOTORCYCLE
+1F3CE FE0E ; text style;  # (7.0 🏎︎ ) RACING CAR
+1F3CE FE0F ; emoji style; # (7.0 🏎️ ) RACING CAR
+1F3D4 FE0E ; text style;  # (7.0 🏔︎ ) SNOW CAPPED MOUNTAIN
+1F3D4 FE0F ; emoji style; # (7.0 🏔️ ) SNOW CAPPED MOUNTAIN
+1F3D5 FE0E ; text style;  # (7.0 🏕︎ ) CAMPING
+1F3D5 FE0F ; emoji style; # (7.0 🏕️ ) CAMPING
+1F3D6 FE0E ; text style;  # (7.0 🏖︎ ) BEACH WITH UMBRELLA
+1F3D6 FE0F ; emoji style; # (7.0 🏖️ ) BEACH WITH UMBRELLA
+1F3D7 FE0E ; text style;  # (7.0 🏗︎ ) BUILDING CONSTRUCTION
+1F3D7 FE0F ; emoji style; # (7.0 🏗️ ) BUILDING CONSTRUCTION
+1F3D8 FE0E ; text style;  # (7.0 🏘︎ ) HOUSE BUILDINGS
+1F3D8 FE0F ; emoji style; # (7.0 🏘️ ) HOUSE BUILDINGS
+1F3D9 FE0E ; text style;  # (7.0 🏙︎ ) CITYSCAPE
+1F3D9 FE0F ; emoji style; # (7.0 🏙️ ) CITYSCAPE
+1F3DA FE0E ; text style;  # (7.0 🏚︎ ) DERELICT HOUSE BUILDING
+1F3DA FE0F ; emoji style; # (7.0 🏚️ ) DERELICT HOUSE BUILDING
+1F3DB FE0E ; text style;  # (7.0 🏛︎ ) CLASSICAL BUILDING
+1F3DB FE0F ; emoji style; # (7.0 🏛️ ) CLASSICAL BUILDING
+1F3DC FE0E ; text style;  # (7.0 🏜︎ ) DESERT
+1F3DC FE0F ; emoji style; # (7.0 🏜️ ) DESERT
+1F3DD FE0E ; text style;  # (7.0 🏝︎ ) DESERT ISLAND
+1F3DD FE0F ; emoji style; # (7.0 🏝️ ) DESERT ISLAND
+1F3DE FE0E ; text style;  # (7.0 🏞︎ ) NATIONAL PARK
+1F3DE FE0F ; emoji style; # (7.0 🏞️ ) NATIONAL PARK
+1F3DF FE0E ; text style;  # (7.0 🏟︎ ) STADIUM
+1F3DF FE0F ; emoji style; # (7.0 🏟️ ) STADIUM
+1F3E0 FE0E ; text style;  # (6.0 🏠︎ ) HOUSE BUILDING
+1F3E0 FE0F ; emoji style; # (6.0 🏠️ ) HOUSE BUILDING
+1F3ED FE0E ; text style;  # (6.0 🏭︎ ) FACTORY
+1F3ED FE0F ; emoji style; # (6.0 🏭️ ) FACTORY
+1F3F3 FE0E ; text style;  # (7.0 🏳︎ ) WAVING WHITE FLAG
+1F3F3 FE0F ; emoji style; # (7.0 🏳️ ) WAVING WHITE FLAG
+1F3F5 FE0E ; text style;  # (7.0 🏵︎ ) ROSETTE
+1F3F5 FE0F ; emoji style; # (7.0 🏵️ ) ROSETTE
+1F3F7 FE0E ; text style;  # (7.0 🏷︎ ) LABEL
+1F3F7 FE0F ; emoji style; # (7.0 🏷️ ) LABEL
+1F408 FE0E ; text style;  # (6.0 🐈︎ ) CAT
+1F408 FE0F ; emoji style; # (6.0 🐈️ ) CAT
+1F415 FE0E ; text style;  # (6.0 🐕︎ ) DOG
+1F415 FE0F ; emoji style; # (6.0 🐕️ ) DOG
+1F41F FE0E ; text style;  # (6.0 🐟︎ ) FISH
+1F41F FE0F ; emoji style; # (6.0 🐟️ ) FISH
+1F426 FE0E ; text style;  # (6.0 🐦︎ ) BIRD
+1F426 FE0F ; emoji style; # (6.0 🐦️ ) BIRD
+1F43F FE0E ; text style;  # (7.0 🐿︎ ) CHIPMUNK
+1F43F FE0F ; emoji style; # (7.0 🐿️ ) CHIPMUNK
+1F441 FE0E ; text style;  # (7.0 👁︎ ) EYE
+1F441 FE0F ; emoji style; # (7.0 👁️ ) EYE
+1F442 FE0E ; text style;  # (6.0 👂︎ ) EAR
+1F442 FE0F ; emoji style; # (6.0 👂️ ) EAR
+1F446 FE0E ; text style;  # (6.0 👆︎ ) WHITE UP POINTING BACKHAND INDEX
+1F446 FE0F ; emoji style; # (6.0 👆️ ) WHITE UP POINTING BACKHAND INDEX
+1F447 FE0E ; text style;  # (6.0 👇︎ ) WHITE DOWN POINTING BACKHAND INDEX
+1F447 FE0F ; emoji style; # (6.0 👇️ ) WHITE DOWN POINTING BACKHAND INDEX
+1F448 FE0E ; text style;  # (6.0 👈︎ ) WHITE LEFT POINTING BACKHAND INDEX
+1F448 FE0F ; emoji style; # (6.0 👈️ ) WHITE LEFT POINTING BACKHAND INDEX
+1F449 FE0E ; text style;  # (6.0 👉︎ ) WHITE RIGHT POINTING BACKHAND INDEX
+1F449 FE0F ; emoji style; # (6.0 👉️ ) WHITE RIGHT POINTING BACKHAND INDEX
+1F44D FE0E ; text style;  # (6.0 👍︎ ) THUMBS UP SIGN
+1F44D FE0F ; emoji style; # (6.0 👍️ ) THUMBS UP SIGN
+1F44E FE0E ; text style;  # (6.0 👎︎ ) THUMBS DOWN SIGN
+1F44E FE0F ; emoji style; # (6.0 👎️ ) THUMBS DOWN SIGN
+1F453 FE0E ; text style;  # (6.0 👓︎ ) EYEGLASSES
+1F453 FE0F ; emoji style; # (6.0 👓️ ) EYEGLASSES
+1F46A FE0E ; text style;  # (6.0 👪︎ ) FAMILY
+1F46A FE0F ; emoji style; # (6.0 👪️ ) FAMILY
+1F47D FE0E ; text style;  # (6.0 👽︎ ) EXTRATERRESTRIAL ALIEN
+1F47D FE0F ; emoji style; # (6.0 👽️ ) EXTRATERRESTRIAL ALIEN
+1F4A3 FE0E ; text style;  # (6.0 💣︎ ) BOMB
+1F4A3 FE0F ; emoji style; # (6.0 💣️ ) BOMB
+1F4B0 FE0E ; text style;  # (6.0 💰︎ ) MONEY BAG
+1F4B0 FE0F ; emoji style; # (6.0 💰️ ) MONEY BAG
+1F4B3 FE0E ; text style;  # (6.0 💳︎ ) CREDIT CARD
+1F4B3 FE0F ; emoji style; # (6.0 💳️ ) CREDIT CARD
+1F4BB FE0E ; text style;  # (6.0 💻︎ ) PERSONAL COMPUTER
+1F4BB FE0F ; emoji style; # (6.0 💻️ ) PERSONAL COMPUTER
+1F4BF FE0E ; text style;  # (6.0 💿︎ ) OPTICAL DISC
+1F4BF FE0F ; emoji style; # (6.0 💿️ ) OPTICAL DISC
+1F4CB FE0E ; text style;  # (6.0 📋︎ ) CLIPBOARD
+1F4CB FE0F ; emoji style; # (6.0 📋️ ) CLIPBOARD
+1F4DA FE0E ; text style;  # (6.0 📚︎ ) BOOKS
+1F4DA FE0F ; emoji style; # (6.0 📚️ ) BOOKS
+1F4DF FE0E ; text style;  # (6.0 📟︎ ) PAGER
+1F4DF FE0F ; emoji style; # (6.0 📟️ ) PAGER
+1F4E4 FE0E ; text style;  # (6.0 📤︎ ) OUTBOX TRAY
+1F4E4 FE0F ; emoji style; # (6.0 📤️ ) OUTBOX TRAY
+1F4E5 FE0E ; text style;  # (6.0 📥︎ ) INBOX TRAY
+1F4E5 FE0F ; emoji style; # (6.0 📥️ ) INBOX TRAY
+1F4E6 FE0E ; text style;  # (6.0 📦︎ ) PACKAGE
+1F4E6 FE0F ; emoji style; # (6.0 📦️ ) PACKAGE
+1F4EA FE0E ; text style;  # (6.0 📪︎ ) CLOSED MAILBOX WITH LOWERED FLAG
+1F4EA FE0F ; emoji style; # (6.0 📪️ ) CLOSED MAILBOX WITH LOWERED FLAG
+1F4EB FE0E ; text style;  # (6.0 📫︎ ) CLOSED MAILBOX WITH RAISED FLAG
+1F4EB FE0F ; emoji style; # (6.0 📫️ ) CLOSED MAILBOX WITH RAISED FLAG
+1F4EC FE0E ; text style;  # (6.0 📬︎ ) OPEN MAILBOX WITH RAISED FLAG
+1F4EC FE0F ; emoji style; # (6.0 📬️ ) OPEN MAILBOX WITH RAISED FLAG
+1F4ED FE0E ; text style;  # (6.0 📭︎ ) OPEN MAILBOX WITH LOWERED FLAG
+1F4ED FE0F ; emoji style; # (6.0 📭️ ) OPEN MAILBOX WITH LOWERED FLAG
+1F4F7 FE0E ; text style;  # (6.0 📷︎ ) CAMERA
+1F4F7 FE0F ; emoji style; # (6.0 📷️ ) CAMERA
+1F4F9 FE0E ; text style;  # (6.0 📹︎ ) VIDEO CAMERA
+1F4F9 FE0F ; emoji style; # (6.0 📹️ ) VIDEO CAMERA
+1F4FA FE0E ; text style;  # (6.0 📺︎ ) TELEVISION
+1F4FA FE0F ; emoji style; # (6.0 📺️ ) TELEVISION
+1F4FB FE0E ; text style;  # (6.0 📻︎ ) RADIO
+1F4FB FE0F ; emoji style; # (6.0 📻️ ) RADIO
+1F4FD FE0E ; text style;  # (7.0 📽︎ ) FILM PROJECTOR
+1F4FD FE0F ; emoji style; # (7.0 📽️ ) FILM PROJECTOR
+1F508 FE0E ; text style;  # (6.0 🔈︎ ) SPEAKER
+1F508 FE0F ; emoji style; # (6.0 🔈️ ) SPEAKER
+1F50D FE0E ; text style;  # (6.0 🔍︎ ) LEFT-POINTING MAGNIFYING GLASS
+1F50D FE0F ; emoji style; # (6.0 🔍️ ) LEFT-POINTING MAGNIFYING GLASS
+1F512 FE0E ; text style;  # (6.0 🔒︎ ) LOCK
+1F512 FE0F ; emoji style; # (6.0 🔒️ ) LOCK
+1F513 FE0E ; text style;  # (6.0 🔓︎ ) OPEN LOCK
+1F513 FE0F ; emoji style; # (6.0 🔓️ ) OPEN LOCK
+1F549 FE0E ; text style;  # (7.0 🕉︎ ) OM SYMBOL
+1F549 FE0F ; emoji style; # (7.0 🕉️ ) OM SYMBOL
+1F54A FE0E ; text style;  # (7.0 🕊︎ ) DOVE OF PEACE
+1F54A FE0F ; emoji style; # (7.0 🕊️ ) DOVE OF PEACE
+1F550 FE0E ; text style;  # (6.0 🕐︎ ) CLOCK FACE ONE OCLOCK
+1F550 FE0F ; emoji style; # (6.0 🕐️ ) CLOCK FACE ONE OCLOCK
+1F551 FE0E ; text style;  # (6.0 🕑︎ ) CLOCK FACE TWO OCLOCK
+1F551 FE0F ; emoji style; # (6.0 🕑️ ) CLOCK FACE TWO OCLOCK
+1F552 FE0E ; text style;  # (6.0 🕒︎ ) CLOCK FACE THREE OCLOCK
+1F552 FE0F ; emoji style; # (6.0 🕒️ ) CLOCK FACE THREE OCLOCK
+1F553 FE0E ; text style;  # (6.0 🕓︎ ) CLOCK FACE FOUR OCLOCK
+1F553 FE0F ; emoji style; # (6.0 🕓️ ) CLOCK FACE FOUR OCLOCK
+1F554 FE0E ; text style;  # (6.0 🕔︎ ) CLOCK FACE FIVE OCLOCK
+1F554 FE0F ; emoji style; # (6.0 🕔️ ) CLOCK FACE FIVE OCLOCK
+1F555 FE0E ; text style;  # (6.0 🕕︎ ) CLOCK FACE SIX OCLOCK
+1F555 FE0F ; emoji style; # (6.0 🕕️ ) CLOCK FACE SIX OCLOCK
+1F556 FE0E ; text style;  # (6.0 🕖︎ ) CLOCK FACE SEVEN OCLOCK
+1F556 FE0F ; emoji style; # (6.0 🕖️ ) CLOCK FACE SEVEN OCLOCK
+1F557 FE0E ; text style;  # (6.0 🕗︎ ) CLOCK FACE EIGHT OCLOCK
+1F557 FE0F ; emoji style; # (6.0 🕗️ ) CLOCK FACE EIGHT OCLOCK
+1F558 FE0E ; text style;  # (6.0 🕘︎ ) CLOCK FACE NINE OCLOCK
+1F558 FE0F ; emoji style; # (6.0 🕘️ ) CLOCK FACE NINE OCLOCK
+1F559 FE0E ; text style;  # (6.0 🕙︎ ) CLOCK FACE TEN OCLOCK
+1F559 FE0F ; emoji style; # (6.0 🕙️ ) CLOCK FACE TEN OCLOCK
+1F55A FE0E ; text style;  # (6.0 🕚︎ ) CLOCK FACE ELEVEN OCLOCK
+1F55A FE0F ; emoji style; # (6.0 🕚️ ) CLOCK FACE ELEVEN OCLOCK
+1F55B FE0E ; text style;  # (6.0 🕛︎ ) CLOCK FACE TWELVE OCLOCK
+1F55B FE0F ; emoji style; # (6.0 🕛️ ) CLOCK FACE TWELVE OCLOCK
+1F55C FE0E ; text style;  # (6.0 🕜︎ ) CLOCK FACE ONE-THIRTY
+1F55C FE0F ; emoji style; # (6.0 🕜️ ) CLOCK FACE ONE-THIRTY
+1F55D FE0E ; text style;  # (6.0 🕝︎ ) CLOCK FACE TWO-THIRTY
+1F55D FE0F ; emoji style; # (6.0 🕝️ ) CLOCK FACE TWO-THIRTY
+1F55E FE0E ; text style;  # (6.0 🕞︎ ) CLOCK FACE THREE-THIRTY
+1F55E FE0F ; emoji style; # (6.0 🕞️ ) CLOCK FACE THREE-THIRTY
+1F55F FE0E ; text style;  # (6.0 🕟︎ ) CLOCK FACE FOUR-THIRTY
+1F55F FE0F ; emoji style; # (6.0 🕟️ ) CLOCK FACE FOUR-THIRTY
+1F560 FE0E ; text style;  # (6.0 🕠︎ ) CLOCK FACE FIVE-THIRTY
+1F560 FE0F ; emoji style; # (6.0 🕠️ ) CLOCK FACE FIVE-THIRTY
+1F561 FE0E ; text style;  # (6.0 🕡︎ ) CLOCK FACE SIX-THIRTY
+1F561 FE0F ; emoji style; # (6.0 🕡️ ) CLOCK FACE SIX-THIRTY
+1F562 FE0E ; text style;  # (6.0 🕢︎ ) CLOCK FACE SEVEN-THIRTY
+1F562 FE0F ; emoji style; # (6.0 🕢️ ) CLOCK FACE SEVEN-THIRTY
+1F563 FE0E ; text style;  # (6.0 🕣︎ ) CLOCK FACE EIGHT-THIRTY
+1F563 FE0F ; emoji style; # (6.0 🕣️ ) CLOCK FACE EIGHT-THIRTY
+1F564 FE0E ; text style;  # (6.0 🕤︎ ) CLOCK FACE NINE-THIRTY
+1F564 FE0F ; emoji style; # (6.0 🕤️ ) CLOCK FACE NINE-THIRTY
+1F565 FE0E ; text style;  # (6.0 🕥︎ ) CLOCK FACE TEN-THIRTY
+1F565 FE0F ; emoji style; # (6.0 🕥️ ) CLOCK FACE TEN-THIRTY
+1F566 FE0E ; text style;  # (6.0 🕦︎ ) CLOCK FACE ELEVEN-THIRTY
+1F566 FE0F ; emoji style; # (6.0 🕦️ ) CLOCK FACE ELEVEN-THIRTY
+1F567 FE0E ; text style;  # (6.0 🕧︎ ) CLOCK FACE TWELVE-THIRTY
+1F567 FE0F ; emoji style; # (6.0 🕧️ ) CLOCK FACE TWELVE-THIRTY
+1F56F FE0E ; text style;  # (7.0 🕯︎ ) CANDLE
+1F56F FE0F ; emoji style; # (7.0 🕯️ ) CANDLE
+1F570 FE0E ; text style;  # (7.0 🕰︎ ) MANTELPIECE CLOCK
+1F570 FE0F ; emoji style; # (7.0 🕰️ ) MANTELPIECE CLOCK
+1F573 FE0E ; text style;  # (7.0 🕳︎ ) HOLE
+1F573 FE0F ; emoji style; # (7.0 🕳️ ) HOLE
+1F574 FE0E ; text style;  # (7.0 🕴︎ ) MAN IN BUSINESS SUIT LEVITATING
+1F574 FE0F ; emoji style; # (7.0 🕴️ ) MAN IN BUSINESS SUIT LEVITATING
+1F575 FE0E ; text style;  # (7.0 🕵︎ ) SLEUTH OR SPY
+1F575 FE0F ; emoji style; # (7.0 🕵️ ) SLEUTH OR SPY
+1F576 FE0E ; text style;  # (7.0 🕶︎ ) DARK SUNGLASSES
+1F576 FE0F ; emoji style; # (7.0 🕶️ ) DARK SUNGLASSES
+1F577 FE0E ; text style;  # (7.0 🕷︎ ) SPIDER
+1F577 FE0F ; emoji style; # (7.0 🕷️ ) SPIDER
+1F578 FE0E ; text style;  # (7.0 🕸︎ ) SPIDER WEB
+1F578 FE0F ; emoji style; # (7.0 🕸️ ) SPIDER WEB
+1F579 FE0E ; text style;  # (7.0 🕹︎ ) JOYSTICK
+1F579 FE0F ; emoji style; # (7.0 🕹️ ) JOYSTICK
+1F587 FE0E ; text style;  # (7.0 🖇︎ ) LINKED PAPERCLIPS
+1F587 FE0F ; emoji style; # (7.0 🖇️ ) LINKED PAPERCLIPS
+1F58A FE0E ; text style;  # (7.0 🖊︎ ) LOWER LEFT BALLPOINT PEN
+1F58A FE0F ; emoji style; # (7.0 🖊️ ) LOWER LEFT BALLPOINT PEN
+1F58B FE0E ; text style;  # (7.0 🖋︎ ) LOWER LEFT FOUNTAIN PEN
+1F58B FE0F ; emoji style; # (7.0 🖋️ ) LOWER LEFT FOUNTAIN PEN
+1F58C FE0E ; text style;  # (7.0 🖌︎ ) LOWER LEFT PAINTBRUSH
+1F58C FE0F ; emoji style; # (7.0 🖌️ ) LOWER LEFT PAINTBRUSH
+1F58D FE0E ; text style;  # (7.0 🖍︎ ) LOWER LEFT CRAYON
+1F58D FE0F ; emoji style; # (7.0 🖍️ ) LOWER LEFT CRAYON
+1F590 FE0E ; text style;  # (7.0 🖐︎ ) RAISED HAND WITH FINGERS SPLAYED
+1F590 FE0F ; emoji style; # (7.0 🖐️ ) RAISED HAND WITH FINGERS SPLAYED
+1F5A5 FE0E ; text style;  # (7.0 🖥︎ ) DESKTOP COMPUTER
+1F5A5 FE0F ; emoji style; # (7.0 🖥️ ) DESKTOP COMPUTER
+1F5A8 FE0E ; text style;  # (7.0 🖨︎ ) PRINTER
+1F5A8 FE0F ; emoji style; # (7.0 🖨️ ) PRINTER
+1F5B1 FE0E ; text style;  # (7.0 🖱︎ ) THREE BUTTON MOUSE
+1F5B1 FE0F ; emoji style; # (7.0 🖱️ ) THREE BUTTON MOUSE
+1F5B2 FE0E ; text style;  # (7.0 🖲︎ ) TRACKBALL
+1F5B2 FE0F ; emoji style; # (7.0 🖲️ ) TRACKBALL
+1F5BC FE0E ; text style;  # (7.0 🖼︎ ) FRAME WITH PICTURE
+1F5BC FE0F ; emoji style; # (7.0 🖼️ ) FRAME WITH PICTURE
+1F5C2 FE0E ; text style;  # (7.0 🗂︎ ) CARD INDEX DIVIDERS
+1F5C2 FE0F ; emoji style; # (7.0 🗂️ ) CARD INDEX DIVIDERS
+1F5C3 FE0E ; text style;  # (7.0 🗃︎ ) CARD FILE BOX
+1F5C3 FE0F ; emoji style; # (7.0 🗃️ ) CARD FILE BOX
+1F5C4 FE0E ; text style;  # (7.0 🗄︎ ) FILE CABINET
+1F5C4 FE0F ; emoji style; # (7.0 🗄️ ) FILE CABINET
+1F5D1 FE0E ; text style;  # (7.0 🗑︎ ) WASTEBASKET
+1F5D1 FE0F ; emoji style; # (7.0 🗑️ ) WASTEBASKET
+1F5D2 FE0E ; text style;  # (7.0 🗒︎ ) SPIRAL NOTE PAD
+1F5D2 FE0F ; emoji style; # (7.0 🗒️ ) SPIRAL NOTE PAD
+1F5D3 FE0E ; text style;  # (7.0 🗓︎ ) SPIRAL CALENDAR PAD
+1F5D3 FE0F ; emoji style; # (7.0 🗓️ ) SPIRAL CALENDAR PAD
+1F5DC FE0E ; text style;  # (7.0 🗜︎ ) COMPRESSION
+1F5DC FE0F ; emoji style; # (7.0 🗜️ ) COMPRESSION
+1F5DD FE0E ; text style;  # (7.0 🗝︎ ) OLD KEY
+1F5DD FE0F ; emoji style; # (7.0 🗝️ ) OLD KEY
+1F5DE FE0E ; text style;  # (7.0 🗞︎ ) ROLLED-UP NEWSPAPER
+1F5DE FE0F ; emoji style; # (7.0 🗞️ ) ROLLED-UP NEWSPAPER
+1F5E1 FE0E ; text style;  # (7.0 🗡︎ ) DAGGER KNIFE
+1F5E1 FE0F ; emoji style; # (7.0 🗡️ ) DAGGER KNIFE
+1F5E3 FE0E ; text style;  # (7.0 🗣︎ ) SPEAKING HEAD IN SILHOUETTE
+1F5E3 FE0F ; emoji style; # (7.0 🗣️ ) SPEAKING HEAD IN SILHOUETTE
+1F5E8 FE0E ; text style;  # (7.0 🗨︎ ) LEFT SPEECH BUBBLE
+1F5E8 FE0F ; emoji style; # (7.0 🗨️ ) LEFT SPEECH BUBBLE
+1F5EF FE0E ; text style;  # (7.0 🗯︎ ) RIGHT ANGER BUBBLE
+1F5EF FE0F ; emoji style; # (7.0 🗯️ ) RIGHT ANGER BUBBLE
+1F5F3 FE0E ; text style;  # (7.0 🗳︎ ) BALLOT BOX WITH BALLOT
+1F5F3 FE0F ; emoji style; # (7.0 🗳️ ) BALLOT BOX WITH BALLOT
+1F5FA FE0E ; text style;  # (7.0 🗺︎ ) WORLD MAP
+1F5FA FE0F ; emoji style; # (7.0 🗺️ ) WORLD MAP
+1F610 FE0E ; text style;  # (6.0 😐︎ ) NEUTRAL FACE
+1F610 FE0F ; emoji style; # (6.0 😐️ ) NEUTRAL FACE
+1F687 FE0E ; text style;  # (6.0 🚇︎ ) METRO
+1F687 FE0F ; emoji style; # (6.0 🚇️ ) METRO
+1F68D FE0E ; text style;  # (6.0 🚍︎ ) ONCOMING BUS
+1F68D FE0F ; emoji style; # (6.0 🚍️ ) ONCOMING BUS
+1F691 FE0E ; text style;  # (6.0 🚑︎ ) AMBULANCE
+1F691 FE0F ; emoji style; # (6.0 🚑️ ) AMBULANCE
+1F694 FE0E ; text style;  # (6.0 🚔︎ ) ONCOMING POLICE CAR
+1F694 FE0F ; emoji style; # (6.0 🚔️ ) ONCOMING POLICE CAR
+1F698 FE0E ; text style;  # (6.0 🚘︎ ) ONCOMING AUTOMOBILE
+1F698 FE0F ; emoji style; # (6.0 🚘️ ) ONCOMING AUTOMOBILE
+1F6AD FE0E ; text style;  # (6.0 🚭︎ ) NO SMOKING SYMBOL
+1F6AD FE0F ; emoji style; # (6.0 🚭️ ) NO SMOKING SYMBOL
+1F6B2 FE0E ; text style;  # (6.0 🚲︎ ) BICYCLE
+1F6B2 FE0F ; emoji style; # (6.0 🚲️ ) BICYCLE
+1F6B9 FE0E ; text style;  # (6.0 🚹︎ ) MENS SYMBOL
+1F6B9 FE0F ; emoji style; # (6.0 🚹️ ) MENS SYMBOL
+1F6BA FE0E ; text style;  # (6.0 🚺︎ ) WOMENS SYMBOL
+1F6BA FE0F ; emoji style; # (6.0 🚺️ ) WOMENS SYMBOL
+1F6BC FE0E ; text style;  # (6.0 🚼︎ ) BABY SYMBOL
+1F6BC FE0F ; emoji style; # (6.0 🚼️ ) BABY SYMBOL
+1F6CB FE0E ; text style;  # (7.0 🛋︎ ) COUCH AND LAMP
+1F6CB FE0F ; emoji style; # (7.0 🛋️ ) COUCH AND LAMP
+1F6CD FE0E ; text style;  # (7.0 🛍︎ ) SHOPPING BAGS
+1F6CD FE0F ; emoji style; # (7.0 🛍️ ) SHOPPING BAGS
+1F6CE FE0E ; text style;  # (7.0 🛎︎ ) BELLHOP BELL
+1F6CE FE0F ; emoji style; # (7.0 🛎️ ) BELLHOP BELL
+1F6CF FE0E ; text style;  # (7.0 🛏︎ ) BED
+1F6CF FE0F ; emoji style; # (7.0 🛏️ ) BED
+1F6E0 FE0E ; text style;  # (7.0 🛠︎ ) HAMMER AND WRENCH
+1F6E0 FE0F ; emoji style; # (7.0 🛠️ ) HAMMER AND WRENCH
+1F6E1 FE0E ; text style;  # (7.0 🛡︎ ) SHIELD
+1F6E1 FE0F ; emoji style; # (7.0 🛡️ ) SHIELD
+1F6E2 FE0E ; text style;  # (7.0 🛢︎ ) OIL DRUM
+1F6E2 FE0F ; emoji style; # (7.0 🛢️ ) OIL DRUM
+1F6E3 FE0E ; text style;  # (7.0 🛣︎ ) MOTORWAY
+1F6E3 FE0F ; emoji style; # (7.0 🛣️ ) MOTORWAY
+1F6E4 FE0E ; text style;  # (7.0 🛤︎ ) RAILWAY TRACK
+1F6E4 FE0F ; emoji style; # (7.0 🛤️ ) RAILWAY TRACK
+1F6E5 FE0E ; text style;  # (7.0 🛥︎ ) MOTOR BOAT
+1F6E5 FE0F ; emoji style; # (7.0 🛥️ ) MOTOR BOAT
+1F6E9 FE0E ; text style;  # (7.0 🛩︎ ) SMALL AIRPLANE
+1F6E9 FE0F ; emoji style; # (7.0 🛩️ ) SMALL AIRPLANE
+1F6F0 FE0E ; text style;  # (7.0 🛰︎ ) SATELLITE
+1F6F0 FE0F ; emoji style; # (7.0 🛰️ ) SATELLITE
+1F6F3 FE0E ; text style;  # (7.0 🛳︎ ) PASSENGER SHIP
+1F6F3 FE0F ; emoji style; # (7.0 🛳️ ) PASSENGER SHIP
+
+#Total sequences: 354
+
+#EOF
diff --git a/admin/unidata/emoji-zwj.awk b/admin/unidata/emoji-zwj.awk
index 7d2ff6cb900..4b648aa675e 100644
--- a/admin/unidata/emoji-zwj.awk
+++ b/admin/unidata/emoji-zwj.awk
@@ -106,7 +106,8 @@ END {
 
      for (elt in ch)
     {
-        printf("(#x%s .\n,(eval-when-compile (regexp-opt\n'(\n%s\n))))\n", 
elt, vec[elt])
+        entries = vec[elt] 
sprintf("\n\"\\N{U+%s}\\N{U+FE0E}\"\n\"\\N{U+%s}\\N{U+FE0F}\"", elt, elt)
+        printf("(#x%s .\n,(eval-when-compile (regexp-opt\n'(\n%s\n))))\n", 
elt, entries)
     }
      print "))"
      print "  (set-char-table-range composition-function-table"
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index aacc0d0b0ec..f5f4dff0e18 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -6217,7 +6217,7 @@ method when it is able.  @xref{Programming Answer 8, 8}. 
(@bullet{})
 @cindex Gamma constant, Euler's
 @cindex Euler's gamma constant
 (@bullet{}) @strong{Exercise 9.}  The @dfn{digamma} function
-@texline @math{\psi(z) (``psi'')}
+@texline @math{\psi(z)} (``psi'')
 @infoline @expr{psi(z)}
 is defined as the derivative of
 @texline @math{\ln \Gamma(z)}.
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
index 330fdd1e3a2..be9e8698ab4 100644
--- a/doc/misc/transient.texi
+++ b/doc/misc/transient.texi
@@ -31,7 +31,7 @@ General Public License for more details.
 @finalout
 @titlepage
 @title Transient User and Developer Manual
-@subtitle for version 0.4.0
+@subtitle for version 0.4.1
 @author Jonas Bernoulli
 @page
 @vskip 0pt plus 1filll
@@ -74,7 +74,7 @@ that hurdle is Psionic K's interactive tutorial, available at
 @end quotation
 
 @noindent
-This manual is for Transient version 0.4.0.
+This manual is for Transient version 0.4.1.
 
 @insertcopying
 @end ifnottex
@@ -2150,7 +2150,7 @@ default value of a prefix using the same format as 
returned by
 
 @item
 @code{always-read} For options, whether to read a value on every invocation.
-If this is nil, then options that have a value are simply unset and
+If this is @code{nil}, then options that have a value are simply unset and
 have to be invoked a second time to set a new value.
 
 @item
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index a3457d70340..60aa64b5ede 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -1692,6 +1692,13 @@ the following to your Init file:
 *** New command 'dired-do-eww'.
 This command visits the file on the current line with EWW.
 
+---
+*** 'browse-url-of-dired-file' can now call the secondary browser.
+When invoked with a prefix arg, this will now call
+'browse-url-secondary-browser-function' instead of the default
+browser.  'browse-url-of-dired-file' is bound to 'W' by default in
+dired mode.
+
 ---
 *** New user option 'dired-omit-lines'.
 This is used by 'dired-omit-mode', and now allows you to hide based on
@@ -1769,7 +1776,7 @@ or can take a long time to render.
 +++
 *** New command 'enriched-toggle-markup'.
 This allows you to see the markup in 'enriched-mode' buffers (e.g.,
-the "HELLO" file).
+the "HELLO" file).  Bound to 'M-o m' by default.
 
 ** Shell Script Mode
 
@@ -1879,7 +1886,9 @@ These commands can be useful if the ".elc" files are out 
of date
 +++
 *** New DWIM action on 'x' in "*Packages*" buffer.
 If no packages are marked, 'x' will install the package under point if
-it isn't already, and remove it if it is installed.
+it isn't already, and remove it if it is installed.  Customize the new
+option 'package-menu-use-current-if-no-marks' to the nil value to get
+back the old behavior of signaling an error in that case.
 
 +++
 *** New command 'package-vc-install'.
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index 671210f3ee8..35cac5d7310 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -1985,7 +1985,13 @@ their associated keys and their effects."
                  (setq done-only t)
                  (todo-toggle-view-done-only))
                (if here
-                    (todo-insert-with-overlays new-item)
+                   (progn
+                     ;; Ensure item is inserted where command was invoked.
+                     (unless (= (point) opoint)
+                       (todo-category-number ocat)
+                       (todo-category-select)
+                       (goto-char opoint))
+                      (todo-insert-with-overlays new-item))
                  (todo-set-item-priority new-item cat t))
                (setq item-added t))
            ;; If user cancels before setting priority, restore
@@ -2119,6 +2125,9 @@ the item at point."
          ((or marked (todo-item-string))
           (todo-edit-item--next-key 'todo arg)))))
 
+(defvar todo-edit-item--cat nil)
+(defvar todo-edit-item--pos nil)
+
 (defun todo-edit-item--text (&optional arg)
   "Function providing the text editing facilities of `todo-edit-item'."
   (let ((full-item (todo-item-string)))
@@ -2127,6 +2136,7 @@ the item at point."
     ;; 1+ signals an error, so just make this a noop.
     (when full-item
       (let* ((opoint (point))
+            (ocat (todo-current-category))
             (start (todo-item-start))
             (end (save-excursion (todo-item-end)))
             (item-beg (progn
@@ -2151,8 +2161,7 @@ the item at point."
                         (concat " \\[" (regexp-quote todo-comment-string)
                                 ": \\([^]]+\\)\\]")
                          end t)))
-            (prompt (if comment "Edit comment: " "Enter a comment: "))
-            (buffer-read-only nil))
+            (prompt (if comment "Edit comment: " "Enter a comment: ")))
        ;; When there are marked items, user can invoke todo-edit-item
        ;; even if point is not on an item, but text editing only
        ;; applies to the item at point.
@@ -2170,22 +2179,43 @@ the item at point."
                                      end t)
                  (if comment-delete
                      (when (todo-y-or-n-p "Delete comment? ")
-                       (delete-region (match-beginning 0) (match-end 0)))
-                   (replace-match (save-match-data
-                                     (read-string prompt
-                                                  (cons (match-string 1) 1)))
-                                  nil nil nil 1))
+                       (let ((buffer-read-only nil))
+                         (delete-region (match-beginning 0) (match-end 0))))
+                   (let ((buffer-read-only nil))
+                     (replace-match (save-match-data
+                                      (prog1 (let ((buffer-read-only t))
+                                               (read-string
+                                                prompt
+                                                (cons (match-string 1) 1)))
+                                        ;; If user moved point while editing
+                                        ;; a comment, restore it and ensure
+                                        ;; done items section is displayed.
+                                        (unless (= (point) opoint)
+                                          (todo-category-number ocat)
+                                          (let ((todo-show-with-done t))
+                                            (todo-category-select)
+                                            (goto-char opoint)))))
+                                    nil nil nil 1)))
                (if comment-delete
                    (user-error "There is no comment to delete")
-                 (insert " [" todo-comment-string ": "
-                         (prog1 (read-string prompt)
-                           ;; If user moved point during editing,
-                           ;; make sure it moves back.
-                           (goto-char opoint)
-                           (todo-item-end))
-                         "]")))))
+                 (let ((buffer-read-only nil))
+                   (insert " [" todo-comment-string ": "
+                           (prog1 (let ((buffer-read-only t))
+                                    (read-string prompt))
+                             ;; If user moved point while inserting a
+                             ;; comment, restore it and ensure done items
+                             ;; section is displayed.
+                             (unless (= (point) opoint)
+                               (todo-category-number ocat)
+                               (let ((todo-show-with-done t))
+                                 (todo-category-select)
+                                 (goto-char opoint)))
+                             (todo-item-end))
+                           "]"))))))
           (multiline
            (let ((buf todo-edit-buffer))
+             (setq todo-edit-item--cat ocat)
+             (setq todo-edit-item--pos opoint)
              (set-window-buffer (selected-window)
                                 (set-buffer (make-indirect-buffer
                                              (buffer-name) buf)))
@@ -2208,10 +2238,14 @@ the item at point."
              ;; Ensure lines following hard newlines are indented.
              (setq new (replace-regexp-in-string "\\(\n\\)[^[:blank:]]"
                                                  "\n\t" new nil nil 1))
-             ;; If user moved point during editing, make sure it moves back.
-             (goto-char opoint)
-             (todo-remove-item)
-             (todo-insert-with-overlays new)
+             ;; If user moved point while editing item, restore it.
+             (unless (= (point) opoint)
+               (todo-category-number ocat)
+               (todo-category-select)
+               (goto-char opoint))
+             (let ((buffer-read-only nil))
+               (todo-remove-item)
+               (todo-insert-with-overlays new))
              (move-to-column item-beg)))))))))
 
 (defun todo-edit-quit ()
@@ -2243,6 +2277,9 @@ made in the number or names of categories."
        (kill-buffer)
        (unless (eq (current-buffer) buf)
          (set-window-buffer (selected-window) (set-buffer buf)))
+       (todo-category-number todo-edit-item--cat)
+       (todo-category-select)
+       (goto-char todo-edit-item--pos)
         (if transient-mark-mode (deactivate-mark)))
     ;; We got here via `F e'.
     (when (todo-check-format)
@@ -2315,117 +2352,118 @@ made in the number or names of categories."
            ;; If there are marked items, use only the first to set
            ;; header changes, and apply these to all marked items.
            (when first
-             (cond
-              ((eq what 'date)
-               (setq ndate (todo-read-date)))
-              ((eq what 'calendar)
-               (setq ndate (save-match-data (todo-set-date-from-calendar))))
-              ((eq what 'today)
-               (setq ndate (calendar-date-string (calendar-current-date) t t)))
-              ((eq what 'dayname)
-               (setq ndate (todo-read-dayname)))
-              ((eq what 'time)
-               (setq ntime (save-match-data (todo-read-time)))
-               (when (> (length ntime) 0)
-                 (setq ntime (concat " " ntime))))
-              ;; When date string consists only of a day name,
-              ;; passing other date components is a noop.
-              ((and odayname (memq what '(year month day))))
-              ((eq what 'year)
-               (setq day oday
-                     monthname omonthname
-                     month omonth
-                     year (cond ((not current-prefix-arg)
-                                 (todo-read-date 'year))
-                                ((string= oyear "*")
-                                 (user-error "Cannot increment *"))
-                                (t
-                                 (number-to-string (+ yy inc))))))
-              ((eq what 'month)
-               (setf day oday
-                     year oyear
-                     (if (memq 'month calendar-date-display-form)
-                         month
-                       monthname)
-                     (cond ((not current-prefix-arg)
-                            (todo-read-date 'month))
-                           ((or (string= omonth "*") (= mm 13))
-                            (user-error "Cannot increment *"))
-                           (t
-                            (let* ((mmo mm)
-                                    ;; Change by 12 or more months?
-                                    (bigincp (>= (abs inc) 12))
-                                    ;; Month number is in range 1..12.
-                                    (mminc (+ mm (% inc 12)))
-                                   (mm (% (+ mminc 12) 12))
-                                   ;; 12n mod 12 = 0, so 0 is December.
-                                   (mm (if (= mm 0) 12 mm))
-                                    ;; Does change in month cross year?
-                                    (mmcmp (cond ((< inc 0) (> mm mmo))
-                                                 ((> inc 0) (< mm mmo))))
-                                    (yyadjust (if bigincp
-                                                  (+ (abs (/ inc 12))
-                                                     (if mmcmp 1 0))
-                                                1)))
-                              ;; Adjust year if necessary.
-                               (setq yy (cond ((and (< inc 0)
-                                                    (or mmcmp bigincp))
-                                               (- yy yyadjust))
-                                              ((and (> inc 0)
-                                                    (or mmcmp bigincp))
-                                               (+ yy yyadjust))
-                                              (t yy)))
-                               (setq year (number-to-string yy))
-                              ;; Return the changed numerical month as
-                              ;; a string or the corresponding month name.
-                              (if omonth
-                                  (number-to-string mm)
-                                (aref tma-array (1- mm)))))))
-                ;; Since the number corresponding to the arbitrary
-                ;; month name "*" is out of the range of
-                ;; calendar-last-day-of-month, set it to 1
-                ;; (corresponding to January) to allow 31 days.
-                (let ((mm (if (= mm 13) 1 mm)))
-                 (if (> (string-to-number day)
-                        (calendar-last-day-of-month mm yy))
-                     (user-error "%s %s does not have %s days"
-                            (aref tmn-array (1- mm))
-                            (if (= mm 2) yy "") day))))
-              ((eq what 'day)
-               (setq year oyear
-                     month omonth
-                     monthname omonthname
-                     day (cond
-                          ((not current-prefix-arg)
-                           (todo-read-date 'day mm yy))
-                          ((string= oday "*")
-                           (user-error "Cannot increment *"))
-                          ((or (string= omonth "*") (string= omonthname "*"))
-                           (setq dd (+ dd inc))
-                           (if (> dd 31)
-                               (user-error
-                                "A month cannot have more than 31 days")
-                             (number-to-string dd)))
-                          ;; Increment or decrement day by INC,
-                          ;; adjusting month and year if necessary
-                          ;; (if year is "*" assume current year to
-                          ;; calculate adjustment).
-                          (t
-                           (let* ((yy (or yy (calendar-extract-year
-                                              (calendar-current-date))))
-                                  (date (calendar-gregorian-from-absolute
-                                         (+ (calendar-absolute-from-gregorian
-                                             (list mm dd yy))
-                                             inc)))
-                                  (adjmm (nth 0 date)))
-                             ;; Set year and month(name) to adjusted values.
-                             (unless (string= year "*")
-                               (setq year (number-to-string (nth 2 date))))
-                             (if month
-                                 (setq month (number-to-string adjmm))
-                               (setq monthname (aref tma-array (1- adjmm))))
-                             ;; Return changed numerical day as a string.
-                             (number-to-string (nth 1 date)))))))))
+             (save-match-data
+               (cond
+                ((eq what 'date)
+                 (setq ndate (todo-read-date)))
+                ((eq what 'calendar)
+                 (setq ndate (todo-set-date-from-calendar)))
+                ((eq what 'today)
+                 (setq ndate (calendar-date-string (calendar-current-date) t 
t)))
+                ((eq what 'dayname)
+                 (setq ndate (todo-read-dayname)))
+                ((eq what 'time)
+                 (setq ntime (todo-read-time))
+                 (when (> (length ntime) 0)
+                   (setq ntime (concat " " ntime))))
+                ;; When date string consists only of a day name,
+                ;; passing other date components is a noop.
+                ((and odayname (memq what '(year month day))))
+                ((eq what 'year)
+                 (setq day oday
+                       monthname omonthname
+                       month omonth
+                       year (cond ((not current-prefix-arg)
+                                   (todo-read-date 'year))
+                                  ((string= oyear "*")
+                                   (user-error "Cannot increment *"))
+                                  (t
+                                   (number-to-string (+ yy inc))))))
+                ((eq what 'month)
+                 (setf day oday
+                       year oyear
+                       (if (memq 'month calendar-date-display-form)
+                           month
+                         monthname)
+                       (cond ((not current-prefix-arg)
+                              (todo-read-date 'month))
+                             ((or (string= omonth "*") (= mm 13))
+                              (user-error "Cannot increment *"))
+                             (t
+                              (let* ((mmo mm)
+                                      ;; Change by 12 or more months?
+                                      (bigincp (>= (abs inc) 12))
+                                      ;; Month number is in range 1..12.
+                                      (mminc (+ mm (% inc 12)))
+                                     (mm (% (+ mminc 12) 12))
+                                     ;; 12n mod 12 = 0, so 0 is December.
+                                     (mm (if (= mm 0) 12 mm))
+                                      ;; Does change in month cross year?
+                                      (mmcmp (cond ((< inc 0) (> mm mmo))
+                                                   ((> inc 0) (< mm mmo))))
+                                      (yyadjust (if bigincp
+                                                    (+ (abs (/ inc 12))
+                                                       (if mmcmp 1 0))
+                                                  1)))
+                                ;; Adjust year if necessary.
+                                (setq yy (cond ((and (< inc 0)
+                                                      (or mmcmp bigincp))
+                                                (- yy yyadjust))
+                                               ((and (> inc 0)
+                                                      (or mmcmp bigincp))
+                                                (+ yy yyadjust))
+                                               (t yy)))
+                                (setq year (number-to-string yy))
+                                ;; Return the changed numerical month as
+                                ;; a string or the corresponding month name.
+                                (if omonth
+                                    (number-to-string mm)
+                                  (aref tma-array (1- mm)))))))
+                  ;; Since the number corresponding to the arbitrary
+                  ;; month name "*" is out of the range of
+                  ;; calendar-last-day-of-month, set it to 1
+                  ;; (corresponding to January) to allow 31 days.
+                  (let ((mm (if (= mm 13) 1 mm)))
+                   (if (> (string-to-number day)
+                          (calendar-last-day-of-month mm yy))
+                       (user-error "%s %s does not have %s days"
+                                   (aref tmn-array (1- mm))
+                                   (if (= mm 2) yy "") day))))
+                ((eq what 'day)
+                 (setq year oyear
+                       month omonth
+                       monthname omonthname
+                       day (cond
+                            ((not current-prefix-arg)
+                             (todo-read-date 'day mm yy))
+                            ((string= oday "*")
+                             (user-error "Cannot increment *"))
+                            ((or (string= omonth "*") (string= omonthname "*"))
+                             (setq dd (+ dd inc))
+                             (if (> dd 31)
+                                 (user-error
+                                  "A month cannot have more than 31 days")
+                               (number-to-string dd)))
+                            ;; Increment or decrement day by INC,
+                            ;; adjusting month and year if necessary
+                            ;; (if year is "*" assume current year to
+                            ;; calculate adjustment).
+                            (t
+                             (let* ((yy (or yy (calendar-extract-year
+                                                (calendar-current-date))))
+                                    (date (calendar-gregorian-from-absolute
+                                           (+ (calendar-absolute-from-gregorian
+                                               (list mm dd yy))
+                                               inc)))
+                                    (adjmm (nth 0 date)))
+                               ;; Set year and month(name) to adjusted values.
+                               (unless (string= year "*")
+                                 (setq year (number-to-string (nth 2 date))))
+                               (if month
+                                   (setq month (number-to-string adjmm))
+                                 (setq monthname (aref tma-array (1- adjmm))))
+                               ;; Return changed numerical day as a string.
+                               (number-to-string (nth 1 date))))))))))
            (unless odayname
              ;; If year, month or day date string components were
              ;; changed, rebuild the date string.
diff --git a/lisp/composite.el b/lisp/composite.el
index 06c7c174163..3ae3e64d5b9 100644
--- a/lisp/composite.el
+++ b/lisp/composite.el
@@ -861,7 +861,7 @@ and the second is a glyph for a variation selector."
 ;; handled in font_range, we end up choosing the Emoji presentation
 ;; rather than the Text presentation.
 (let ((elt '([".." 1 compose-gstring-for-variation-glyph])))
-  (set-char-table-range composition-function-table '(#xFE00 . #xFE0E) elt)
+  (set-char-table-range composition-function-table '(#xFE00 . #xFE0D) elt)
   (set-char-table-range composition-function-table '(#xE0100 . #xE01EF) elt))
 
 (defun auto-compose-chars (func from to font-object string direction)
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 69595601bc8..ba0e3618f28 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -3317,6 +3317,18 @@ Values can be interactively added to this list by typing
   :version "25.1"
   :type '(repeat (regexp :tag "Hide packages with name matching")))
 
+(defcustom package-menu-use-current-if-no-marks t
+  "Whether \\<package-menu-mode-map>\\[package-menu-execute] in package menu 
operates on current package if none are marked.
+
+If non-nil, and no packages are marked for installation or
+deletion, \\<package-menu-mode-map>\\[package-menu-execute] will operate on 
the current package at point,
+see `package-menu-execute' for details.
+The default is t.  Set to nil to get back the original behavior
+of having `package-menu-execute' signal an error when no packages
+are marked for installation or deletion."
+  :version "29.1"
+  :type 'boolean)
+
 (defun package-menu--refresh (&optional packages keywords)
   "Re-populate the `tabulated-list-entries'.
 PACKAGES should be nil or t, which means to display all known packages.
@@ -3760,8 +3772,8 @@ object corresponding to the newer version."
         (and avail-pkg
              (version-list-< (package-desc-priority-version pkg-desc)
                              (package-desc-priority-version avail-pkg))
-             (xor (not package-install-upgrade-built-in)
-                  (package--active-built-in-p pkg-desc))
+             (or (not (package--active-built-in-p pkg-desc))
+                 package-install-upgrade-built-in)
              (push (cons name avail-pkg) upgrades))))
     upgrades))
 
@@ -3946,7 +3958,8 @@ invocations."
     ;; Nothing marked.
     (unless (or delete-list install-list)
       ;; Not on a package line.
-      (unless (tabulated-list-get-id)
+      (unless (and (tabulated-list-get-id)
+                   package-menu-use-current-if-no-marks)
         (user-error "No operations specified"))
       (let* ((id (tabulated-list-get-id))
              (status (package-menu-get-status)))
diff --git a/lisp/info-look.el b/lisp/info-look.el
index 7858ed58774..da45e30cd36 100644
--- a/lisp/info-look.el
+++ b/lisp/info-look.el
@@ -733,7 +733,11 @@ Return nil if there is nothing appropriate in the buffer 
near point."
                 (let ((str (string-join str-list " ")))
                   (when (assoc str completions)
                     (throw 'result str))
-                  (nbutlast str-list)))))))
+                  ;; 'nbutlast' will not destructively set its argument
+                  ;; to nil when the argument is a list of 1 element.
+                  (if (= (length str-list) 1)
+                      (setq str-list nil)
+                    (nbutlast str-list))))))))
     (error nil)))
 
 ;;;###autoload
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 36fff1520ac..30d2c24e19e 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2021,11 +2021,14 @@ completions."
 
 (defcustom completions-header-format
   (propertize "%s possible completions:\n" 'face 'shadow)
-  "Format of completions header.
-It may contain one %s to show the total count of completions.
-When nil, no header is shown."
-  :type '(choice (const :tag "No header" nil)
-                 (string :tag "Header format string"))
+  "If non-nil, the format string for completions heading line.
+The heading line is inserted before the completions, and is intended
+to summarize the completions.
+The format string may include one %s, which will be replaced with
+the total count of possible completions.
+If this is nil, no heading line will be shown."
+  :type '(choice (const :tag "No heading line" nil)
+                 (string :tag "Format string for heading line"))
   :version "29.1")
 
 (defun completion--insert-strings (strings &optional group-fun)
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index c2629b69d59..8036bbc8acc 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -829,10 +829,17 @@ If optional arg TEMP-FILE-NAME is non-nil, delete it 
instead."
                  (&optional localp no-error-if-not-filep))
 
 ;;;###autoload
-(defun browse-url-of-dired-file ()
-  "In Dired, ask a WWW browser to display the file named on this line."
-  (interactive)
+(defun browse-url-of-dired-file (&optional secondary)
+  "In Dired, ask a WWW browser to display the file named on this line.
+With prefix arg, use the secondary browser instead (e.g. EWW if
+`browse-url-secondary-browser-function' is set to
+`eww-browse-url'."
+  (interactive "P")
   (let ((tem (dired-get-filename t t))
+        (browse-url-browser-function
+         (if secondary
+             browse-url-secondary-browser-function
+           browse-url-browser-function))
         ;; Some URL handlers open files in Emacs.  We want to always
         ;; open in a browser, so disable those.
         (browse-url-default-handlers nil))
diff --git a/lisp/plstore.el b/lisp/plstore.el
index 0276a752a0f..d18d461d7d1 100644
--- a/lisp/plstore.el
+++ b/lisp/plstore.el
@@ -24,6 +24,14 @@
 
 ;; Plist based data store providing search and partial encryption.
 ;;
+;; By default, this package uses symmetric encryption, which means
+;; that you have to enter the password protecting your store more
+;; often than you probably expect to.  To use public key encryption
+;; with this package, create a GnuPG key and customize user option
+;; `plstore-encrypt-to' to use it.  You can then configure the GnuPG
+;; agent to adjust caching and expiration of the passphrase for your
+;; store.
+;;
 ;; Creating:
 ;;
 ;; ;; Open a new store associated with ~/.emacs.d/auth.plist.
@@ -43,12 +51,16 @@
 ;; ;; Kill the buffer visiting ~/.emacs.d/auth.plist.
 ;; (plstore-close store)
 ;;
+;; Avoid marking one property both as public *and* secret, as the
+;; behavior of this package with respect to such duplicate properties
+;; is not (yet) defined.
+;;
 ;; Searching:
 ;;
 ;; (setq store (plstore-open (expand-file-name "~/.emacs.d/auth.plist")))
 ;;
 ;; ;; As the entry "foo" associated with "foo.example.org" has no
-;; ;; secret properties, no need to decryption.
+;; ;; secret properties, no need for decryption.
 ;; (plstore-find store '(:host ("foo.example.org")))
 ;;
 ;; ;; As the entry "bar" associated with "bar.example.org" has a
@@ -66,17 +78,119 @@
 ;; Editing:
 ;;
 ;; This file also provides `plstore-mode', a major mode for editing
-;; the PLSTORE format file.  Visit a non-existing file and put the
+;; the plstore format file.  Visit a non-existing file and put the
 ;; following line:
 ;;
 ;; (("foo" :host "foo.example.org" :secret-user "user"))
 ;;
 ;; where the prefixing `:secret-' means the property (without
 ;; `:secret-' prefix) is marked as secret.  Thus, when you save the
-;; buffer, the `:secret-user' property is encrypted as `:user'.
+;; buffer, the `:secret-user' property is encrypted as `:user'.  Do
+;; not use a property consisting solely of the prefix, as the behavior
+;; of this package with respect to such properties is not (yet)
+;; defined.
 ;;
 ;; You can toggle the view between encrypted form and the decrypted
 ;; form with C-c C-c.
+;;
+;; If you have opened a plstore with `plstore-open' you should not
+;; edit its underlying buffer in `plstore-mode' or in any other way at
+;; the same time, since your manual changes will be overwritten when
+;; `plstore-save' is called on that plstore.
+;;
+;; Internals:
+;;
+;; This is information on the internal data structure and functions of
+;; this package.  None of it should be necessary to actually use it.
+;; For easier reading, we usually do not distinguish in this internal
+;; documentation between a Lisp object and its printed representation.
+;;
+;; A plstore corresponds to an alist mapping strings to property
+;; lists.  Internally, that alist is organized as two alists, one
+;; mapping to the non-secret properties and placeholders for the
+;; secret properties (called "template alist" with identifier ALIST)
+;; and one mapping to the secret properties ("secret alist",
+;; SECRET-ALIST).  The secret alist is read from and written to file
+;; as pgp-encrypted printed representation of the alist ("encrypted
+;; data", ENCRYPTED-DATA).
+;;
+;; During the lifetime of a plstore, a third type of alist may pop up,
+;; which maps to the merged non-secret properties and plain-text
+;; secret properties ("merged alist", MERGED-ALIST).
+;;
+;; After executing the "foo", "bar", "baz" example from above the
+;; alists described above look like the following:
+;;
+;;   Template Alist:
+;;
+;;     (("foo" :host "foo.example.org" :port 80)
+;;      ("bar" :secret-user t :host "bar.example.org")
+;;      ("baz" :secret-password t :host "baz.example.org"))
+;;
+;;   Secret Alist:
+;;
+;;     (("bar" :user "test")
+;;      ("baz" :password "test"))
+;;
+;;   Merged Alist:
+;;
+;;     (("foo" :host "foo.example.org" :port 80)
+;;      ("bar" :user "test" :host "bar.example.org")
+;;      ("baz" :password "test" :host "baz.example.org"))
+;;
+;; Finally, a plstore requires a buffer ("plstore buffer", BUFFER) for
+;; conversion between its Lisp objects and its file representation.
+;; It is important to note that this buffer is *not* continuously
+;; synchronized as the plstore changes.  During the lifetime of a
+;; plstore, its buffer is read from in function `plstore-open' and
+;; (destructively) written to in `plstore-save', but not touched
+;; otherwise.  We call the file visited by the plstore buffer the
+;; associated file of the plstore.
+;;
+;; With the identifiers defined above a plstore is a vector with the
+;; following elements and accessor functions:
+;;
+;;   [
+;;     BUFFER           ; plstore--get/set-buffer
+;;     ALIST            ; plstore--get/set-alist
+;;     ENCRYPTED-DATA   ; plstore--get/set-encrypted-data
+;;     SECRET-ALIST     ; plstore--get/set-secret-alist
+;;     MERGED-ALIST     ; plstore--get/set-merged-alist
+;;   ]
+;;
+;; When a plstore is created through `plstore-open', its ALIST and
+;; ENCRYPTED-DATA are initialized from the contents of BUFFER without
+;; any decryption taking place, and MERGED-ALIST is initialized as a
+;; copy of ALIST.  (Which means that at that stage the merged alist
+;; still contains the secret property placeholders!)
+;;
+;; During on-demand decryption of a plstore through function
+;; `plstore--decrypt', SECRET-ALIST is populated from ENCRYPTED-DATA,
+;; which is in turn replaced by value nil.  (Which further serves as
+;; an indicator that the plstore has been decrypted already.)  In
+;; addition, MERGED-ALIST is recomputed by function
+;; `plstore--merge-secret' to replace the secret property placeholders
+;; by their plain-text secret property equivalents.
+;;
+;; The file representation of a plstore consists of two Lisp forms plus
+;; markers to introduce them:
+;;
+;;   ;;; public entries
+;;   ALIST
+;;   ;;; secret entries
+;;   ENCRYPTED-DATA
+;;
+;; Both of these are optional, but the first section must be present
+;; if the second one is.  If both sections are missing, the plstore is
+;; empty.  If the second section is missing, it contains only
+;; non-secret data.  If present, the printed representation of the
+;; encrypted data includes the delimiting double quotes.
+;;
+;; The plstore API (`plstore-open', `plstore-put', etc.) and the
+;; plstore mode implemented by `plstore-mode' are orthogonal to each
+;; other and should not be mixed up.  In particular, encoding and
+;; decoding a plstore mode buffer with `plstore-mode-toggle-display'
+;; is not related in any way to the state of the plstore buffer.
 
 ;;; Code:
 
@@ -121,10 +235,13 @@ symmetric encryption will be used."
 
 (put 'plstore-encrypt-to 'permanent-local t)
 
-(defvar plstore-encoded nil)
+(defvar plstore-encoded nil
+  "Non-nil if the current buffer shows the decoded alist.") ; [sic!]
 
 (put 'plstore-encoded 'permanent-local t)
 
+;;; EasyPG callback functions.
+
 (defvar plstore-cache-passphrase-for-symmetric-encryption nil)
 (defvar plstore-passphrase-alist nil)
 
@@ -141,11 +258,11 @@ symmetric encryption will be used."
                      (cons entry
                            plstore-passphrase-alist)))
              (setq passphrase
-                   (read-passwd (format "Passphrase for PLSTORE %s: "
+                   (read-passwd (format "Passphrase for plstore %s: "
                                         (plstore--get-buffer plstore))))
              (setcdr entry (copy-sequence passphrase))
              passphrase)))
-    (read-passwd (format "Passphrase for PLSTORE %s: "
+    (read-passwd (format "Passphrase for plstore %s: "
                         (plstore--get-buffer plstore)))))
 
 (defun plstore-progress-callback-function (_context _what _char current total
@@ -155,6 +272,8 @@ symmetric encryption will be used."
     (message "%s...%d%%" handback
             (if (> total 0) (floor (* (/ current (float total)) 100)) 0))))
 
+;;; Core functions.
+
 (defun plstore--get-buffer (arg)
   (aref arg 0))
 
@@ -193,6 +312,7 @@ symmetric encryption will be used."
   (vector buffer alist encrypted-data secret-alist merged-alist))
 
 (defun plstore--init-from-buffer (plstore)
+  "Parse current buffer and initialize PLSTORE from it."
   (goto-char (point-min))
   (when (looking-at ";;; public entries")
     (forward-line)
@@ -223,16 +343,20 @@ symmetric encryption will be used."
       store)))
 
 (defun plstore-revert (plstore)
-  "Replace current data in PLSTORE with the file on disk."
+  "Replace current data in PLSTORE from its associated file."
   (with-current-buffer (plstore--get-buffer plstore)
     (revert-buffer t t)
     (plstore--init-from-buffer plstore)))
 
 (defun plstore-close (plstore)
-  "Destroy a plstore instance PLSTORE."
+  "Destroy plstore instance PLSTORE."
   (kill-buffer (plstore--get-buffer plstore)))
 
 (defun plstore--merge-secret (plstore)
+  "Determine the merged alist of PLSTORE.
+Create the merged alist as a copy of the template alist with all
+placeholder properties that have corresponding properties in the
+secret alist replaced by their plain-text secret properties."
   (let ((alist (plstore--get-secret-alist plstore))
        modified-alist
        modified-plist
@@ -251,19 +375,26 @@ symmetric encryption will be used."
            modified-entry (assoc (car entry) modified-alist)
            modified-plist (cdr modified-entry))
       (while plist
+        ;; Search for a placeholder property in the merged alist
+        ;; corresponding to the current secret property.
        (setq placeholder
              (plist-member
               modified-plist
               (intern (concat ":secret-"
                               (substring (symbol-name (car plist)) 1)))))
+        ;; Replace its name with the real, secret property name.
        (if placeholder
            (setcar placeholder (car plist)))
+        ;; Update its value to the plain-text secret property value.
        (setq modified-plist
              (plist-put modified-plist (car plist) (car (cdr plist))))
        (setq plist (nthcdr 2 plist)))
       (setcdr modified-entry modified-plist))))
 
 (defun plstore--decrypt (plstore)
+  "Decrypt the encrypted data of PLSTORE.
+Update its internal alists and other data structures
+accordingly."
   (if (plstore--get-encrypted-data plstore)
       (let ((context (epg-make-context 'OpenPGP))
            plain)
@@ -290,6 +421,11 @@ symmetric encryption will be used."
        (plstore--set-encrypted-data plstore nil))))
 
 (defun plstore--match (entry keys skip-if-secret-found)
+  "Return whether plist KEYS matches ENTRY.
+ENTRY should be a key of the merged alist of a PLSTORE.  This
+function returns nil if KEYS do not match ENTRY, t if they match,
+and symbol `secret' if the secret alist needs to be consulted to
+perform a match."
   (let ((result t) key-name key-value prop-value secret-name)
     (while keys
       (setq key-name (car keys)
@@ -311,11 +447,10 @@ symmetric encryption will be used."
     result))
 
 (defun plstore-find (plstore keys)
-  "Perform search on PLSTORE with KEYS.
-KEYS is a plist."
+  "Return all PLSTORE entries matching plist KEYS."
   (let (entries alist entry match decrypt plist)
-    ;; First, go through the merged plist alist and collect entries
-    ;; matched with keys.
+    ;; First, go through the merged alist and collect entries matched
+    ;; by the keys.
     (setq alist (plstore--get-merged-alist plstore))
     (while alist
       (setq entry (car alist)
@@ -331,7 +466,7 @@ KEYS is a plist."
                      plist nil))
            (setq plist (nthcdr 2 plist)))
          (setq entries (cons entry entries)))))
-    ;; Second, decrypt the encrypted plist and try again.
+    ;; Second, decrypt the plstore and try again.
     (when decrypt
       (setq entries nil)
       (plstore--decrypt plstore)
@@ -345,7 +480,8 @@ KEYS is a plist."
     (nreverse entries)))
 
 (defun plstore-get (plstore name)
-  "Get an entry with NAME in PLSTORE."
+  "Return the entry named NAME in PLSTORE.
+Return nil if there is none."
   (let ((entry (assoc name (plstore--get-merged-alist plstore)))
        plist)
     (setq plist (cdr entry))
@@ -359,7 +495,7 @@ KEYS is a plist."
     entry))
 
 (defun plstore-put (plstore name keys secret-keys)
-  "Put an entry with NAME in PLSTORE.
+  "Put an entry named NAME in PLSTORE.
 KEYS is a plist containing non-secret data.
 SECRET-KEYS is a plist containing secret data."
   (let (entry
@@ -398,7 +534,7 @@ SECRET-KEYS is a plist containing secret data."
     (plstore--merge-secret plstore)))
 
 (defun plstore-delete (plstore name)
-  "Delete an entry with NAME from PLSTORE."
+  "Delete the first entry named NAME from PLSTORE."
   (let ((entry (assoc name (plstore--get-alist plstore))))
     (if entry
        (plstore--set-alist
@@ -417,6 +553,8 @@ SECRET-KEYS is a plist containing secret data."
 
 (defvar pp-escape-newlines)
 (defun plstore--insert-buffer (plstore)
+  "Insert the file representation of PLSTORE at point.
+Assumes that PLSTORE has been decrypted."
   (insert ";;; public entries -*- mode: plstore -*- \n"
          (pp-to-string (plstore--get-alist plstore)))
   (if (plstore--get-secret-alist plstore)
@@ -451,13 +589,31 @@ If no one is selected, symmetric encryption will be 
performed.  "
        (insert ";;; secret entries\n" (pp-to-string cipher)))))
 
 (defun plstore-save (plstore)
-  "Save the contents of PLSTORE associated with a FILE."
+  "Save PLSTORE to its associated file."
   (with-current-buffer (plstore--get-buffer plstore)
     (erase-buffer)
     (plstore--insert-buffer plstore)
     (save-buffer)))
 
+;;; plstore mode.
+
+;; The functions related to plstore mode unfortunately introduce yet
+;; another alist format ("decoded alist").  After executing the "foo",
+;; "bar", "baz" example from above the decoded alist of the plstore
+;; would look like the following:
+;;
+;;   (("foo" :host "foo.example.org" :port 80)
+;;    ("bar" :secret-user "test" :host "bar.example.org")
+;;    ("baz" :secret-password "test" :host "baz.example.org"))
+;;
+;; Even more unfortunately, variable and function names of the
+;; following are a bit mixed up IMHO: With the current names, the
+;; result of function `plstore--encode' is used to create what is
+;; presented as "decoded form of a plstore" to the user.  And variable
+;; `plstore-encoded' is non-nil if a buffer shows the decoded form.
+
 (defun plstore--encode (plstore)
+  "Return the printed representation of the decoded alist of PLSTORE."
   (plstore--decrypt plstore)
   (let ((merged-alist (plstore--get-merged-alist plstore)))
     (concat "("
@@ -482,6 +638,9 @@ If no one is selected, symmetric encryption will be 
performed.  "
            ")")))
 
 (defun plstore--decode (string)
+  "Create a plstore instance from STRING.
+STRING should be the printed representation of a decoded alist of
+some plstore."
   (let* ((alist (car (read-from-string string)))
         (pointer alist)
         secret-alist
@@ -489,7 +648,7 @@ If no one is selected, symmetric encryption will be 
performed.  "
         entry)
     (while pointer
       (unless (stringp (car (car pointer)))
-       (error "Invalid PLSTORE format %s" string))
+       (error "Invalid plstore format %s" string))
       (setq plist (cdr (car pointer)))
       (while plist
        (when (string-match "\\`:secret-" (symbol-name (car plist)))
@@ -509,6 +668,10 @@ If no one is selected, symmetric encryption will be 
performed.  "
     (plstore--make nil alist nil secret-alist)))
 
 (defun plstore--write-contents-functions ()
+  "Convert the decoded form of a plstore in the current buffer.
+Convert it to the regular file representation of a plstore if
+needed.  This function is used on hook `write-contents-functions'
+in plstore mode buffers."
   (when plstore-encoded
     (let ((store (plstore--decode (buffer-string)))
          (file (buffer-file-name)))
@@ -546,7 +709,7 @@ If no one is selected, symmetric encryption will be 
performed.  "
       (erase-buffer)
       (insert
        (substitute-command-keys "\
-;;; You are looking at the decoded form of the PLSTORE file.\n\
+;;; You are looking at the decoded form of the plstore file.\n\
 ;;; To see the original form content, do \\[plstore-mode-toggle-display]\n\n"))
       (insert (plstore--encode store))
       (set-buffer-modified-p nil)
@@ -561,7 +724,7 @@ If no one is selected, symmetric encryption will be 
performed.  "
 
 ;;;###autoload
 (define-derived-mode plstore-mode emacs-lisp-mode "PLSTORE"
-  "Major mode for editing PLSTORE files."
+  "Major mode for editing plstore files."
   (make-local-variable 'plstore-encoded)
   (add-hook 'write-contents-functions #'plstore--write-contents-functions)
   (define-key plstore-mode-map "\C-c\C-c" #'plstore-mode-toggle-display)
diff --git a/lisp/progmodes/dockerfile-ts-mode.el 
b/lisp/progmodes/dockerfile-ts-mode.el
index c9125bc6cbd..333158e20f6 100644
--- a/lisp/progmodes/dockerfile-ts-mode.el
+++ b/lisp/progmodes/dockerfile-ts-mode.el
@@ -123,8 +123,9 @@ continuation to the previous entry."
   (let* ((node (treesit-buffer-root-node))
          (stage-tree (treesit-induce-sparse-tree
                       node "from_instruction"
-                      nil 1000)))
-    `(("Stage" . ,(dockerfile-ts-mode--imenu-1 stage-tree)))))
+                      nil 1000))
+         (stage-index (dockerfile-ts-mode--imenu-1 stage-tree)))
+    (when stage-index `(("Stage" . ,stage-index)))))
 
 (defun dockerfile-ts-mode--imenu-1 (node)
   "Helper for `dockerfile-ts-mode--imenu'.
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el
index b8705ecc4d0..32d86f44235 100644
--- a/lisp/progmodes/go-ts-mode.el
+++ b/lisp/progmodes/go-ts-mode.el
@@ -59,6 +59,7 @@
     (modify-syntax-entry ?<   "."      table)
     (modify-syntax-entry ?>   "."      table)
     (modify-syntax-entry ?\\  "\\"     table)
+    (modify-syntax-entry ?\'  "\""     table)
     (modify-syntax-entry ?/   ". 124b" table)
     (modify-syntax-entry ?*   ". 23"   table)
     (modify-syntax-entry ?\n  "> b"    table)
diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el
index 47d87112ffb..8a396a8c977 100644
--- a/lisp/progmodes/java-ts-mode.el
+++ b/lisp/progmodes/java-ts-mode.el
@@ -226,6 +226,9 @@ the available version of Tree-sitter for java."
      (constructor_declaration
       name: (identifier) @font-lock-type-face)
 
+     (compact_constructor_declaration
+      name: (identifier) @font-lock-type-face)
+
      (field_access
       object: (identifier) @font-lock-type-face)
 
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 41a5c976629..56c524bcab5 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -816,8 +816,8 @@ DIRS must contain directory names."
         (push buf bufs)))
     (nreverse bufs)))
 
-(cl-defmethod project-name ((_project (head vc)))
-  (or project-vc-name
+(cl-defmethod project-name ((project (head vc)))
+  (or (project--value-in-dir 'project-vc-name (project-root project))
       (cl-call-next-method)))
 
 
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 8c716ffb313..86bbf51dab7 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -415,7 +415,6 @@ instead."
   "Python mode specialized rx macro.
 This variant of `rx' supports common Python named REGEXPS."
   `(rx-let ((sp-bsnl (or space (and ?\\ ?\n)))
-            (sp-nl (or space (and (? ?\\) ?\n)))
             (block-start       (seq symbol-start
                                     (or "def" "class" "if" "elif" "else" "try"
                                         "except" "finally" "for" "while" "with"
@@ -650,9 +649,9 @@ the {...} holes that appear within f-strings."
              finally return (and result-valid result))))
 
 (defvar python-font-lock-keywords-level-1
-  `((,(python-rx symbol-start "def" (1+ sp-bsnl) (group symbol-name))
+  `((,(python-rx symbol-start "def" (1+ space) (group symbol-name))
      (1 font-lock-function-name-face))
-    (,(python-rx symbol-start "class" (1+ sp-bsnl) (group symbol-name))
+    (,(python-rx symbol-start "class" (1+ space) (group symbol-name))
      (1 font-lock-type-face)))
   "Font lock keywords to use in `python-mode' for level 1 decoration.
 
@@ -792,12 +791,12 @@ sign in chained assignment."
     ;;   [*a] = 5, 6
     ;; are handled separately below
     (,(python-font-lock-assignment-matcher
-        (python-rx (? (or "[" "(") (* sp-nl))
-                   grouped-assignment-target (* sp-nl) ?, (* sp-nl)
-                   (* assignment-target (* sp-nl) ?, (* sp-nl))
-                   (? assignment-target (* sp-nl))
-                   (? ?, (* sp-nl))
-                   (? (or ")" "]") (* sp-bsnl))
+        (python-rx (? (or "[" "(") (* space))
+                   grouped-assignment-target (* space) ?, (* space)
+                   (* assignment-target (* space) ?, (* space))
+                   (? assignment-target (* space))
+                   (? ?, (* space))
+                   (? (or ")" "]") (* space))
                    (group assignment-operator)))
      (1 font-lock-variable-name-face)
      (2 'font-lock-operator-face)
@@ -813,9 +812,9 @@ sign in chained assignment."
     ;;   c: Collection = {1, 2, 3}
     ;;   d: Mapping[int, str] = {1: 'bar', 2: 'baz'}
     (,(python-font-lock-assignment-matcher
-       (python-rx (or line-start ?\;) (* sp-bsnl)
-                  grouped-assignment-target (* sp-bsnl)
-                  (? ?: (* sp-bsnl) (+ not-simple-operator) (* sp-bsnl))
+       (python-rx (or line-start ?\;) (* space)
+                  grouped-assignment-target (* space)
+                  (? ?: (* space) (+ not-simple-operator) (* space))
                   (group assignment-operator)))
      (1 font-lock-variable-name-face)
      (2 'font-lock-operator-face))
@@ -824,10 +823,10 @@ sign in chained assignment."
     ;;   [a] = 5,
     ;;   [*a] = 5, 6
     (,(python-font-lock-assignment-matcher
-       (python-rx (or line-start ?\; ?=) (* sp-bsnl)
-                  (or "[" "(") (* sp-nl)
-                  grouped-assignment-target (* sp-nl)
-                  (or ")" "]") (* sp-bsnl)
+       (python-rx (or line-start ?\; ?=) (* space)
+                  (or "[" "(") (* space)
+                  grouped-assignment-target (* space)
+                  (or ")" "]") (* space)
                   (group assignment-operator)))
      (1 font-lock-variable-name-face)
      (2 'font-lock-operator-face))
@@ -869,22 +868,6 @@ decorators, exceptions, and assignments.")
 Which one will be chosen depends on the value of
 `font-lock-maximum-decoration'.")
 
-(defvar font-lock-beg)
-(defvar font-lock-end)
-(defun python-font-lock-extend-region ()
-  "Extend font-lock region to statement boundaries."
-  (let ((beg font-lock-beg)
-        (end font-lock-end))
-    (goto-char beg)
-    (python-nav-beginning-of-statement)
-    (beginning-of-line)
-    (when (< (point) beg)
-      (setq font-lock-beg (point)))
-    (goto-char end)
-    (python-nav-end-of-statement)
-    (when (< end (point))
-      (setq font-lock-end (point)))
-    (or (/= beg font-lock-beg) (/= end font-lock-end))))
 
 (defconst python-syntax-propertize-function
   (syntax-propertize-rules
@@ -6171,7 +6154,8 @@ Optional argument REGEXP selects variables to clone and 
defaults
 to \"^python-\"."
   (mapc
    (lambda (pair)
-     (and (symbolp (car pair))
+     (and (consp pair)
+          (symbolp (car pair))
           (string-match (or regexp "^python-")
                         (symbol-name (car pair)))
           (set (make-local-variable (car pair))
@@ -6769,8 +6753,6 @@ implementations: `python-mode' and `python-ts-mode'."
                 nil nil nil nil
                 (font-lock-syntactic-face-function
                  . python-font-lock-syntactic-face-function)))
-  (add-hook 'font-lock-extend-region-functions
-            #'python-font-lock-extend-region nil t)
   (setq-local syntax-propertize-function
               python-syntax-propertize-function)
   (setq-local imenu-create-index-function
diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el
index be06acde3e3..c3cf8d0cf44 100644
--- a/lisp/progmodes/rust-ts-mode.el
+++ b/lisp/progmodes/rust-ts-mode.el
@@ -350,7 +350,12 @@ Return nil if there is no name or if NODE is not a defun 
node."
       (treesit-node-child-by-field-name node "name") t))))
 
 (defun rust-ts-mode--syntax-propertize (beg end)
-  "Apply syntax text property to template delimiters between BEG and END.
+  "Apply syntax properties to special characters between BEG and END.
+
+Apply syntax properties to various special characters with
+contextual meaning between BEG and END.
+
+The apostrophe \\=' should be treated as string when used for char literals.
 
 < and > are usually punctuation, e.g., as greater/less-than.  But
 when used for types, they should be considered pairs.
@@ -359,11 +364,18 @@ This function checks for < and > in the changed RANGES 
and apply
 appropriate text property to alter the syntax of template
 delimiters < and >'s."
   (goto-char beg)
+  (while (search-forward "'" end t)
+    (when (string-equal "char_literal"
+                        (treesit-node-type
+                         (treesit-node-at (match-beginning 0))))
+      (put-text-property (match-beginning 0) (match-end 0)
+                         'syntax-table (string-to-syntax "\""))))
+  (goto-char beg)
   (while (re-search-forward (rx (or "<" ">")) end t)
     (pcase (treesit-node-type
             (treesit-node-parent
              (treesit-node-at (match-beginning 0))))
-      ("type_arguments"
+      ((or "type_arguments" "type_parameters")
        (put-text-property (match-beginning 0)
                           (match-end 0)
                           'syntax-table
diff --git a/lisp/progmodes/typescript-ts-mode.el 
b/lisp/progmodes/typescript-ts-mode.el
index 3f198e9f180..8255e82a99e 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -128,7 +128,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
     "case" "catch" "class" "const" "continue" "debugger"
     "declare" "default" "delete" "do" "else" "enum"
     "export" "extends" "finally" "for" "from" "function"
-    "get" "if" "implements" "import" "in" "instanceof" "interface"
+    "get" "if" "implements" "import" "in" "instanceof" "interface" "is"
     "keyof" "let" "namespace" "new" "of" "private" "protected"
     "public" "readonly" "return" "set" "static" "switch"
     "target" "throw" "try" "type" "typeof" "var" "void"
diff --git a/lisp/simple.el b/lisp/simple.el
index d23e2e20c62..5ae92c6e4a0 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1520,7 +1520,8 @@ the actual saved text might be different from what was 
killed."
                        (let ((from (car cmp))
                              (to (cadr cmp)))
                          (cond
-                          ((= (length cmp) 2) ; static composition
+                          ((and (= (length cmp) 3) ; static composition
+                                (booleanp (nth 2 cmp)))
                            to)
                           ;; TO can be at POS, in which case we want
                           ;; to make sure we advance at least by 1
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el
index ec3046decd4..92be5a52bf2 100644
--- a/lisp/textmodes/enriched.el
+++ b/lisp/textmodes/enriched.el
@@ -192,6 +192,7 @@ The value is a list of \(VAR VALUE VAR VALUE...).")
     (define-key map "\C-c[" #'set-left-margin)
     (define-key map "\C-c]" #'set-right-margin)
     (define-key map "\M-o" #'facemenu-keymap)
+    (define-key map "\M-om" #'enriched-toggle-markup)
     map)
   "Keymap for Enriched mode.")
 
diff --git a/lisp/tmm.el b/lisp/tmm.el
index 1f9a877c20b..a4058594622 100644
--- a/lisp/tmm.el
+++ b/lisp/tmm.el
@@ -28,6 +28,7 @@
 ;;; Code:
 
 (require 'electric)
+(require 'text-property-search)
 
 (defgroup tmm nil
   "Text mode access to menu-bar."
@@ -169,9 +170,11 @@ instead of executing it."
        (error "Empty menu reached"))
       (and tmm-km-list
           (let ((index-of-default 0))
-            (if tmm-mid-prompt
-                (setq tmm-km-list (tmm-add-shortcuts tmm-km-list))
-              t)
+             (setq tmm-km-list
+                  (if tmm-mid-prompt
+                       (tmm-add-shortcuts tmm-km-list)
+                     ;; tmm-add-shortcuts reverses tmm-km-list internally.
+                     (reverse tmm-km-list)))
             ;; Find the default item's index within the menu bar.
             ;; We use this to decide the initial minibuffer contents
             ;; and initial history position.
@@ -192,7 +195,11 @@ instead of executing it."
                                     (or (not visible) (eval visible))))))
                         (setq index-of-default (1+ index-of-default)))
                     (setq tail (cdr tail)))))
-             (let ((prompt (concat "^." (regexp-quote tmm-mid-prompt))))
+             (let ((prompt
+                    (concat "^"
+                            (if (stringp tmm-mid-prompt)
+                                (concat "."
+                                        (regexp-quote tmm-mid-prompt))))))
                (setq tmm--history
                      (reverse (delq nil
                                     (mapcar
@@ -320,8 +327,22 @@ Stores a list of all the shortcuts in the free variable 
`tmm-short-cuts'."
 
 (defun tmm-completion-delete-prompt ()
   (with-current-buffer standard-output
-  (goto-char (point-min))
-    (delete-region (point) (search-forward "Possible completions are:\n"))))
+    (goto-char (point-min))
+    (let* (;; First candidate: first string with mouse-face
+           (menu-start-1 (or (and (get-text-property (point) 'mouse-face) 
(point))
+                             (next-single-char-property-change (point) 
'mouse-face)))
+           ;; Second candidate: an inactive menu item with tmm-inactive face
+           (tps-result (save-excursion
+                         (text-property-search-forward 'face 'tmm-inactive t)))
+           (menu-start-2 (and tps-result (prop-match-beginning tps-result))))
+      (or (and (null menu-start-1) (null menu-start-2))
+          (delete-region (point)
+                         ;; Use the smallest position of the two candidates.
+                         (or (and menu-start-1 menu-start-2
+                                  (min menu-start-1 menu-start-2))
+                             ;; Otherwise use the one that is non-nil.
+                             menu-start-1
+                             menu-start-2))))))
 
 (defun tmm-remove-inactive-mouse-face ()
   "Remove the mouse-face property from inactive menu items."
diff --git a/lisp/transient.el b/lisp/transient.el
index 1d763c4ddeb..048554eee13 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -6,7 +6,7 @@
 ;; URL: https://github.com/magit/transient
 ;; Keywords: extensions
 
-;; Package-Version: 0.4.0
+;; Package-Version: 0.4.1
 ;; Package-Requires: ((emacs "26.1"))
 
 ;; SPDX-License-Identifier: GPL-3.0-or-later
@@ -1643,6 +1643,7 @@ of the corresponding object."
   "<transient-history-prev>"      #'transient--do-stay
   "<transient-history-next>"      #'transient--do-stay
   "<universal-argument>"          #'transient--do-stay
+  "<universal-argument-more>"     #'transient--do-stay
   "<negative-argument>"           #'transient--do-minus
   "<digit-argument>"              #'transient--do-stay
   "<top-level>"                   #'transient--do-quit-all
@@ -3043,10 +3044,12 @@ prompt."
         (progn
           (cl-call-next-method obj value)
           (dolist (arg incomp)
-            (when-let ((obj (cl-find-if (lambda (obj)
-                                          (and (slot-boundp obj 'argument)
-                                               (equal (oref obj argument) 
arg)))
-                                        transient--suffixes)))
+            (when-let ((obj (cl-find-if
+                             (lambda (obj)
+                               (and (slot-exists-p obj 'argument)
+                                    (slot-boundp obj 'argument)
+                                    (equal (oref obj argument) arg)))
+                             transient--suffixes)))
               (let ((transient--unset-incompatible nil))
                 (transient-infix-set obj nil)))))
       (cl-call-next-method obj value))))
@@ -3253,6 +3256,8 @@ have a history of their own.")
     (with-current-buffer buf
       (when transient-enable-popup-navigation
         (setq focus (or (button-get (point) 'command)
+                        (and (not (bobp))
+                             (button-get (1- (point)) 'command))
                         (transient--heading-at-point))))
       (erase-buffer)
       (setq window-size-fixed t)
@@ -3384,7 +3389,9 @@ have a history of their own.")
                     (insert ?\n)
                   (insert (propertize " " 'display
                                       `(space :align-to (,(nth (1+ c) cc)))))))
-            (insert (make-string (max 1 (- (nth c cc) (current-column))) ?\s))
+            (when (> c 0)
+              (insert (make-string (max 1 (- (nth c cc) (current-column)))
+                                   ?\s)))
             (when-let ((cell (nth r (nth c columns))))
               (insert cell))
             (when (= c (1- cs))
diff --git a/lisp/treesit.el b/lisp/treesit.el
index cc7ec977851..ea701ce1ff7 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -3033,8 +3033,9 @@ See `treesit-language-source-alist' for details."
 
 Interactively, if `treesit-language-source-alist' doesn't already
 have data for building the grammar for LANG, prompt for its
-repository URL and the C/C++ compiler to use.  Non-interactively,
-signal an error when there's no recipe for LANG.
+repository URL and the C/C++ compiler to use.  The recipe built
+by the prompts are saved for the current session if the
+installation is successful and the grammar is loadable.
 
 This command requires Git, a C compiler and (sometimes) a C++ compiler,
 and the linker to be installed and on PATH.  It also requires that the
@@ -3071,26 +3072,31 @@ nil, the grammar is installed to the standard location, 
the
                    default-out-dir)
                 out-dir)))
     (condition-case err
-        (apply #'treesit--install-language-grammar-1
-               (cons out-dir recipe))
+        (progn
+          (apply #'treesit--install-language-grammar-1
+                 ;; The nil is OUT-DIR.
+                 (cons nil recipe))
+
+          ;; Check that the installed language grammar is loadable.
+          (pcase-let ((`(,available . ,err)
+                       (treesit-language-available-p lang t)))
+            (if (not available)
+                (display-warning
+                 'treesit
+                 (format "The installed language grammar for %s cannot be 
located or has problems (%s): %s"
+                         lang (nth 0 err)
+                         (string-join
+                          (mapcar (lambda (x) (format "%s" x))
+                                  (cdr err))
+                          " ")))
+              ;; If success, Save the recipe for the current session.
+              (setf (alist-get lang treesit-language-source-alist)
+                    recipe))))
       (error
        (display-warning
         'treesit
         (format "Error encountered when installing language grammar: %s"
-                err)))))
-
-  ;; Check that the installed language grammar is loadable.
-  (pcase-let ((`(,available . ,err)
-               (treesit-language-available-p lang t)))
-    (when (not available)
-      (display-warning
-       'treesit
-       (format "The installed language grammar for %s cannot be located or has 
problems (%s): %s"
-               lang (nth 0 err)
-               (string-join
-                (mapcar (lambda (x) (format "%s" x))
-                        (cdr err))
-                " "))))))
+                err))))))
 
 (defun treesit--call-process-signal (&rest args)
   "Run `call-process' with ARGS.
diff --git a/lisp/use-package/use-package-core.el 
b/lisp/use-package/use-package-core.el
index 0d99e270a3f..e0e16134ed3 100644
--- a/lisp/use-package/use-package-core.el
+++ b/lisp/use-package/use-package-core.el
@@ -1619,7 +1619,8 @@ Also see the Info node `(use-package) Creating an 
extension'."
     ;; See `use-package-handler/:ensure' for an explanation.
     (if (bound-and-true-p byte-compile-current-file)
         (funcall #'use-package-vc-install arg local-path)        ; compile time
-      (push `(use-package-vc-install ',arg ,local-path) body)))) ; runtime
+      (push `(use-package-vc-install ',arg ,local-path) body))   ; runtime
+    body))
 
 (defun use-package-normalize--vc-arg (arg)
   "Normalize possible arguments to the `:vc' keyword.
diff --git a/lisp/wdired.el b/lisp/wdired.el
index 9952da71078..5c745cc9aab 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -470,9 +470,8 @@ non-nil means return old filename."
     (insert wdired--old-content)
     (goto-char wdired--old-point))
   (wdired-change-to-dired-mode)
-  ;; Make sure the display is in synch, and all the variables are set
-  ;; correctly.
-  (dired-revert)
+  ;; Update markers in `dired-subdir-alist'
+  (dired-build-subdir-alist)
   (set-buffer-modified-p nil)
   (setq buffer-undo-list nil)
   (message "Changes aborted"))
diff --git a/src/lread.c b/src/lread.c
index 43fa23003ca..eb52329f5a8 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -3647,7 +3647,7 @@ read_bool_vector (Lisp_Object readcharfun)
 
 /* Skip (and optionally remember) a lazily-loaded string
    preceded by "#@".  Return true if this was a normal skip,
-   false if we read #@00 (which skips to EOB).  */
+   false if we read #@00 (which skips to EOB/EOF).  */
 static bool
 skip_lazy_string (Lisp_Object readcharfun)
 {
@@ -4184,7 +4184,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
               and function definitions that can be loaded lazily.  */
            if (skip_lazy_string (readcharfun))
              goto read_obj;
-           obj = Qnil;       /* #@00 skips to EOB and yields nil.  */
+           obj = Qnil;       /* #@00 skips to EOB/EOF and yields nil.  */
            break;
 
          case '$':
diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba
index 1969afdd333..21b69dacacc 100644
--- a/test/infra/Dockerfile.emba
+++ b/test/infra/Dockerfile.emba
@@ -29,7 +29,7 @@ FROM debian:bullseye as emacs-base
 RUN apt-get update && \
     apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
       libc-dev gcc g++ make autoconf automake libncurses-dev gnutls-dev \
-      libdbus-1-dev libacl1-dev acl git texinfo gdb \
+      libdbus-1-dev libacl1-dev acl git texinfo gawk gdb \
     && rm -rf /var/lib/apt/lists/*
 
 FROM emacs-base as emacs-inotify
diff --git a/test/infra/Makefile.in b/test/infra/Makefile.in
index 5d40698541d..1af13a0096a 100644
--- a/test/infra/Makefile.in
+++ b/test/infra/Makefile.in
@@ -100,11 +100,20 @@ endef
 
 $(foreach subdir, $(SUBDIRS), $(eval $(call subdir_template,$(subdir))))
 
+TREE-SITTER-FILES ?= $(shell cd .. ; find lisp -name "*-ts-mode-tests.el" | 
sort | sed s/\\.el/.log/)
+
 all: generate-test-jobs
 
-.PHONY: generate-test-jobs $(FILE) $(SUBDIR_TARGETS)
+.PHONY: generate-test-jobs $(FILE) $(SUBDIR_TARGETS) tree-sitter-files-template
+
+generate-test-jobs: $(FILE) $(SUBDIR_TARGETS) tree-sitter-files-template
 
-generate-test-jobs: $(FILE) $(SUBDIR_TARGETS)
+tree-sitter-files-template:
+       @echo >>$(FILE)
+       @echo '.tree-sitter-files-template:' >>$(FILE)
+       @echo '  variables:' >>$(FILE)
+       @echo '    tree_sitter_files: >-' >>$(FILE)
+       @for name in $(TREE-SITTER-FILES) ; do echo "      $${name}" >>$(FILE) 
; done
 
 $(FILE):
        $(AM_V_GEN)
diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml
index ce2a92620fb..d5b18674c70 100644
--- a/test/infra/gitlab-ci.yml
+++ b/test/infra/gitlab-ci.yml
@@ -58,7 +58,7 @@ variables:
   # across multiple builds.
   BUILD_TAG: ${CI_COMMIT_REF_SLUG}
   # Disable if you don't need it, it can be a security risk.
-  CI_DEBUG_TRACE: "true"
+  # CI_DEBUG_TRACE: "true"
 
 default:
   image: docker:19.03.12
@@ -265,7 +265,14 @@ test-eglot:
   variables:
     target: emacs-eglot
     # This is needed in order to get a JUnit test report.
-    make_params: '-k -C test check-expensive 
LOGFILES="lisp/progmodes/eglot-tests.log"'
+    make_params: >-
+      '-k -C test check-expensive
+        LOGFILES="lisp/progmodes/eglot-tests.log"
+        TEST_HOME="/tmp"
+        EMACS_EXTRAOPT="--eval \(package-reinstall\ \(quote\ company\)\)
+                        --eval \(package-reinstall\ \(quote\ yasnippet\)\)
+                        --eval \(use-package\ company\)
+                        --eval \(use-package\ yasnippet\)"'
 
 build-image-tree-sitter:
   stage: platform-images
@@ -275,22 +282,14 @@ build-image-tree-sitter:
 
 test-tree-sitter:
   stage: platforms
-  extends: [.job-template, .test-template, .tree-sitter-template]
+  extends: [.job-template, .test-template, .tree-sitter-template, 
.tree-sitter-files-template]
   needs:
     - job: build-image-tree-sitter
       optional: true
   variables:
     target: emacs-tree-sitter
     # This is needed in order to get a JUnit test report.
-    files: >-
-      lisp/progmodes/c-ts-mode-tests.log
-      lisp/progmodes/elixir-ts-mode-tests.log
-      lisp/progmodes/go-ts-mode-tests.log
-      lisp/progmodes/heex-ts-mode-tests.log
-      lisp/progmodes/java-ts-mode-tests.log
-      lisp/progmodes/ruby-ts-mode-tests.log
-      lisp/progmodes/typescript-ts-mode-tests.log
-    make_params: '-k -C test check-expensive 
LD_LIBRARY_PATH=/usr/local/lib/tree-sitter LOGFILES="$files"'
+    make_params: '-k -C test check-expensive 
LD_LIBRARY_PATH=/usr/local/lib/tree-sitter LOGFILES="$tree_sitter_files"'
 
 build-image-gnustep:
   stage: platform-images
diff --git a/test/infra/test-jobs.yml b/test/infra/test-jobs.yml
index 4e575d50e9a..21c19c3043e 100644
--- a/test/infra/test-jobs.yml
+++ b/test/infra/test-jobs.yml
@@ -567,3 +567,14 @@ test-src-inotify:
   variables:
     target: emacs-inotify
     make_params: "-k -C test check-src"
+
+.tree-sitter-files-template:
+  variables:
+    tree_sitter_files: >-
+      lisp/progmodes/c-ts-mode-tests.log
+      lisp/progmodes/elixir-ts-mode-tests.log
+      lisp/progmodes/go-ts-mode-tests.log
+      lisp/progmodes/heex-ts-mode-tests.log
+      lisp/progmodes/java-ts-mode-tests.log
+      lisp/progmodes/ruby-ts-mode-tests.log
+      lisp/progmodes/typescript-ts-mode-tests.log
diff --git a/test/lisp/progmodes/python-tests.el 
b/test/lisp/progmodes/python-tests.el
index b916232c4be..9323f72f384 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -136,20 +136,6 @@ STRING, it is skipped so the next STRING occurrence is 
selected."
            while pos
            collect (cons pos (get-text-property pos 'face))))
 
-(defun python-tests-assert-faces-after-change (content faces search replace)
-  "Assert that font faces for CONTENT are equal to FACES after change.
-All occurrences of SEARCH are changed to REPLACE."
-  (python-tests-with-temp-buffer
-   content
-   ;; Force enable font-lock mode without jit-lock.
-   (rename-buffer "*python-font-lock-test*" t)
-   (let (noninteractive font-lock-support-mode)
-     (font-lock-mode))
-   (while
-       (re-search-forward search nil t)
-     (replace-match replace))
-   (should (equal faces (python-tests-get-buffer-faces)))))
-
 (defun python-tests-self-insert (char-or-str)
   "Call `self-insert-command' for chars in CHAR-OR-STR."
   (let ((chars
@@ -297,13 +283,6 @@ p = (1 + 2)
    "def 1func():"
    '((1 . font-lock-keyword-face) (4))))
 
-(ert-deftest python-font-lock-keywords-level-1-3 ()
-  (python-tests-assert-faces
-   "def \\
-        func():"
-   '((1 . font-lock-keyword-face) (4)
-     (15 . font-lock-function-name-face) (19))))
-
 (ert-deftest python-font-lock-assignment-statement-1 ()
   (python-tests-assert-faces
    "a, b, c = 1, 2, 3"
@@ -495,129 +474,6 @@ def f(x: CustomInt) -> CustomInt:
      (136 . font-lock-operator-face) (137)
      (144 . font-lock-keyword-face) (150))))
 
-(ert-deftest python-font-lock-assignment-statement-multiline-1 ()
-  (python-tests-assert-faces-after-change
-   "
-[
-    a,
-    b
-] # (
-    1,
-    2
-)
-"
-   '((1)
-     (8 . font-lock-variable-name-face) (9)
-     (15 . font-lock-variable-name-face) (16)
-     (19 . font-lock-operator-face) (20))
-   "#" "="))
-
-(ert-deftest python-font-lock-assignment-statement-multiline-2 ()
-  (python-tests-assert-faces-after-change
-   "
-[
-    *a
-] # 5, 6
-"
-   '((1)
-     (8 . font-lock-operator-face)
-     (9 . font-lock-variable-name-face) (10)
-     (13 . font-lock-operator-face) (14))
-   "#" "="))
-
-(ert-deftest python-font-lock-assignment-statement-multiline-3 ()
-  (python-tests-assert-faces-after-change
-   "a\\
-    ,\\
-    b\\
-    ,\\
-    c\\
-    #\\
-    1\\
-    ,\\
-    2\\
-    ,\\
-    3"
-   '((1 . font-lock-variable-name-face) (2)
-     (15 . font-lock-variable-name-face) (16)
-     (29 . font-lock-variable-name-face) (30)
-     (36 . font-lock-operator-face) (37))
-   "#" "="))
-
-(ert-deftest python-font-lock-assignment-statement-multiline-4 ()
-  (python-tests-assert-faces-after-change
-   "a\\
-    :\\
-    int\\
-    #\\
-    5"
-   '((1 . font-lock-variable-name-face) (2)
-     (15 . font-lock-builtin-face) (18)
-     (24 . font-lock-operator-face) (25))
-   "#" "="))
-
-(ert-deftest python-font-lock-assignment-statement-multiline-5 ()
-  (python-tests-assert-faces-after-change
-   "(\\
-    a\\
-)\\
-    #\\
-    5\\
-    ;\\
-    (\\
-    b\\
-    )\\
-    #\\
-    6"
-   '((1)
-     (8 . font-lock-variable-name-face) (9)
-     (18 . font-lock-operator-face) (19)
-     (46 . font-lock-variable-name-face) (47)
-     (60 . font-lock-operator-face) (61))
-   "#" "="))
-
-(ert-deftest python-font-lock-assignment-statement-multiline-6 ()
-  (python-tests-assert-faces-after-change
-   "(
-    a
-)\\
-    #\\
-    5\\
-    ;\\
-    (
-    b
-    )\\
-    #\\
-    6"
-   '((1)
-     (7 . font-lock-variable-name-face) (8)
-     (16 . font-lock-operator-face) (17)
-     (43 . font-lock-variable-name-face) (44)
-     (56 . font-lock-operator-face) (57))
-   "#" "="))
-
-(ert-deftest python-font-lock-operator-1 ()
-  (python-tests-assert-faces
-   "1 << 2 ** 3 == +4%-5|~6&7^8%9"
-   '((1)
-     (3 . font-lock-operator-face) (5)
-     (8 . font-lock-operator-face) (10)
-     (13 . font-lock-operator-face) (15)
-     (16 . font-lock-operator-face) (17)
-     (18 . font-lock-operator-face) (20)
-     (21 . font-lock-operator-face) (23)
-     (24 . font-lock-operator-face) (25)
-     (26 . font-lock-operator-face) (27)
-     (28 . font-lock-operator-face) (29))))
-
-(ert-deftest python-font-lock-operator-2 ()
-  "Keyword operators are font-locked as keywords."
-  (python-tests-assert-faces
-   "is_ is None"
-   '((1)
-     (5 . font-lock-keyword-face) (7)
-     (8 . font-lock-constant-face))))
-
 (ert-deftest python-font-lock-escape-sequence-string-newline ()
   (python-tests-assert-faces
    "'\\n'
diff --git a/test/lisp/use-package/use-package-tests.el 
b/test/lisp/use-package/use-package-tests.el
index c8c20fc51cb..9181a8171a7 100644
--- a/test/lisp/use-package/use-package-tests.el
+++ b/test/lisp/use-package/use-package-tests.el
@@ -1991,6 +1991,17 @@
              (use-package-vc-install '(other-name) ,load-path?)
              (require 'foo nil nil)))))
 
+(ert-deftest use-package-test-handler/:vc-6 ()
+  (let ((byte-compile-current-file "use-package-core.el")
+        tried-to-install)
+    (cl-letf (((symbol-function #'use-package-vc-install)
+               (lambda (arg &optional local-path)
+                 (setq tried-to-install arg))))
+      (should (equal
+               (use-package-handler/:vc 'foo nil 'some-pkg '(:init (foo)) nil)
+               '(foo)))
+      (should (eq tried-to-install 'some-pkg)))))
+
 (ert-deftest use-package-test-normalize/:vc ()
   (should (equal '(foo "version-string")
                  (use-package-normalize/:vc 'foo :vc '("version-string"))))



reply via email to

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