afc36e2710c05f031eb0b6449243881e78796de0
- Author
- Robby Russell <robby@planetargon.com>
- Committer
- Robby Russell <robby@planetargon.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/plugins/emoji/README.md b/plugins/emoji/README.md
2new file mode 100644
3index 0000000000000000000000000000000000000000..889e567e6ce8e3689fa57a517fd74ab8bc8732e6
4--- /dev/null
5+++ b/plugins/emoji/README.md
6@@ -0,0 +1,135 @@
7+# emoji plugin
8+
9+Support for conveniently working with Unicode emoji in Zsh.
10+
11+## Features
12+
13diff --git a/plugins/emoji/emoji-char-definitions.zsh b/plugins/emoji/emoji-char-definitions.zsh
14new file mode 100644
15index 0000000000000000000000000000000000000000..7d110603ceb4d7b579acaf8f12f4cea3e2b05833
16--- /dev/null
17+++ b/plugins/emoji/emoji-char-definitions.zsh
18@@ -0,0 +1,1294 @@
19+
20+# emoji-char-definitions.zsh - Emoji character definitions for oh-my-zsh emoji plugin
21+#
22+# This file is auto-generated by update_emoji.pl. Do not edit it manually.
23+#
24+# This contains the definition for:
25+# $emoji - which maps character names to Unicode characters
26+# $emoji_flags - maps country names to Unicode flag characters using region indicators
27+
28+typeset -gAH emoji
29+typeset -gAH emoji_flags
30+
31+emoji[copyright_sign]=$'\U00A9'
32+emoji[registered_sign]=$'\U00AE'
33+emoji[double_exclamation_mark]=$'\U203C'
34+emoji[exclamation_question_mark]=$'\U2049'
35+emoji[trade_mark_sign]=$'\U2122'
36+emoji[information_source]=$'\U2139'
37+emoji[left_right_arrow]=$'\U2194'
38+emoji[up_down_arrow]=$'\U2195'
39+emoji[north_west_arrow]=$'\U2196'
40+emoji[north_east_arrow]=$'\U2197'
41+emoji[south_east_arrow]=$'\U2198'
42+emoji[south_west_arrow]=$'\U2199'
43+emoji[leftwards_arrow_with_hook]=$'\U21A9'
44+emoji[rightwards_arrow_with_hook]=$'\U21AA'
45+emoji[watch]=$'\U231A'
46+emoji[hourglass]=$'\U231B'
47+emoji[keyboard]=$'\U2328'
48+emoji[eject_symbol]=$'\U23CF'
49+emoji[black_right_pointing_double_triangle]=$'\U23E9'
50+emoji[black_left_pointing_double_triangle]=$'\U23EA'
51+emoji[black_up_pointing_double_triangle]=$'\U23EB'
52+emoji[black_down_pointing_double_triangle]=$'\U23EC'
53+emoji[black_right_pointing_double_triangle_with_vertical_bar]=$'\U23ED'
54+emoji[black_left_pointing_double_triangle_with_vertical_bar]=$'\U23EE'
55+emoji[black_right_pointing_triangle_with_double_vertical_bar]=$'\U23EF'
56+emoji[alarm_clock]=$'\U23F0'
57+emoji[stopwatch]=$'\U23F1'
58+emoji[timer_clock]=$'\U23F2'
59+emoji[hourglass_with_flowing_sand]=$'\U23F3'
60+emoji[double_vertical_bar]=$'\U23F8'
61+emoji[black_square_for_stop]=$'\U23F9'
62+emoji[black_circle_for_record]=$'\U23FA'
63+emoji[circled_latin_capital_letter_m]=$'\U24C2'
64+emoji[black_small_square]=$'\U25AA'
65+emoji[white_small_square]=$'\U25AB'
66+emoji[black_right_pointing_triangle]=$'\U25B6'
67+emoji[black_left_pointing_triangle]=$'\U25C0'
68+emoji[white_medium_square]=$'\U25FB'
69+emoji[black_medium_square]=$'\U25FC'
70+emoji[white_medium_small_square]=$'\U25FD'
71+emoji[black_medium_small_square]=$'\U25FE'
72+emoji[black_sun_with_rays]=$'\U2600'
73+emoji[cloud]=$'\U2601'
74+emoji[umbrella]=$'\U2602'
75+emoji[snowman]=$'\U2603'
76+emoji[comet]=$'\U2604'
77+emoji[black_telephone]=$'\U260E'
78+emoji[ballot_box_with_check]=$'\U2611'
79+emoji[umbrella_with_rain_drops]=$'\U2614'
80+emoji[hot_beverage]=$'\U2615'
81+emoji[shamrock]=$'\U2618'
82+emoji[white_up_pointing_index]=$'\U261D'
83+emoji[skull_and_crossbones]=$'\U2620'
84+emoji[radioactive_sign]=$'\U2622'
85+emoji[biohazard_sign]=$'\U2623'
86+emoji[orthodox_cross]=$'\U2626'
87+emoji[star_and_crescent]=$'\U262A'
88+emoji[peace_symbol]=$'\U262E'
89+emoji[yin_yang]=$'\U262F'
90+emoji[wheel_of_dharma]=$'\U2638'
91+emoji[white_frowning_face]=$'\U2639'
92+emoji[white_smiling_face]=$'\U263A'
93+emoji[aries]=$'\U2648'
94+emoji[taurus]=$'\U2649'
95+emoji[gemini]=$'\U264A'
96+emoji[cancer]=$'\U264B'
97+emoji[leo]=$'\U264C'
98+emoji[virgo]=$'\U264D'
99+emoji[libra]=$'\U264E'
100+emoji[scorpius]=$'\U264F'
101+emoji[sagittarius]=$'\U2650'
102+emoji[capricorn]=$'\U2651'
103+emoji[aquarius]=$'\U2652'
104+emoji[pisces]=$'\U2653'
105+emoji[black_spade_suit]=$'\U2660'
106+emoji[black_club_suit]=$'\U2663'
107+emoji[black_heart_suit]=$'\U2665'
108+emoji[black_diamond_suit]=$'\U2666'
109+emoji[hot_springs]=$'\U2668'
110+emoji[black_universal_recycling_symbol]=$'\U267B'
111+emoji[wheelchair_symbol]=$'\U267F'
112+emoji[hammer_and_pick]=$'\U2692'
113+emoji[anchor]=$'\U2693'
114+emoji[crossed_swords]=$'\U2694'
115+emoji[scales]=$'\U2696'
116+emoji[alembic]=$'\U2697'
117+emoji[gear]=$'\U2699'
118diff --git a/plugins/emoji/emoji-data.txt b/plugins/emoji/emoji-data.txt
119new file mode 100644
120index 0000000000000000000000000000000000000000..7b4c015f7afb8ccd82f9b027da43df8c7a8e1ba7
121--- /dev/null
122+++ b/plugins/emoji/emoji-data.txt
123@@ -0,0 +1,1308 @@
124+# DRAFT emoji-data.txt
125+# For details about the format and other information, see /../../../reports/tr51/index.html#Data_Files.
126+#
127+# Format: Code ; Default_Emoji_Style ; Emoji_Level ; Emoji_Modifier_Status ; Emoji_Sources # Comment
128+#
129+# Field 1 — Default_Emoji_Style:
130+# text: default text presentation
131+# emoji: default emoji presentation
132+# Field 2 — Emoji_Level:
133+# L1: level 1 emoji
134+# L2: level 2 emoji
135+# NA: not applicable
136+# Field 3 — Emoji_Modifier_Status:
137+# modifier: an emoji modifier
138+# primary: a primary emoji modifier base
139+# secondary: a secondary emoji modifier base
140+# none: not applicable
141+# Field 4 — Emoji_Sources:
142+# one or more values from {z, a, j, w, x}
143+# see the key in http://www.unicode.org/draft/reports/tr51/tr51.html#Major_Sources
144+# NA: not applicable
145+# Comment — currently contains the version where the character was first encoded,
146+# followed by:
147+# - a character name in uppercase (for a single character),
148+# - a keycap name,
149+# - an associated flag, where is associated with value unicode region code
150+#
151+00A9 ; text ; L1 ; none ; j # V1.1 (©) COPYRIGHT SIGN
152+00AE ; text ; L1 ; none ; j # V1.1 (®) REGISTERED SIGN
153+203C ; text ; L1 ; none ; a j # V1.1 (‼) DOUBLE EXCLAMATION MARK
154+2049 ; text ; L1 ; none ; a j # V3.0 (⁉) EXCLAMATION QUESTION MARK
155+2122 ; text ; L1 ; none ; j # V1.1 (™) TRADE MARK SIGN
156+2139 ; text ; L1 ; none ; j # V3.0 (ℹ) INFORMATION SOURCE
157+2194 ; text ; L1 ; none ; z j # V1.1 (↔) LEFT RIGHT ARROW
158+2195 ; text ; L1 ; none ; z j # V1.1 (↕) UP DOWN ARROW
159+2196 ; text ; L1 ; none ; j # V1.1 (↖) NORTH WEST ARROW
160+2197 ; text ; L1 ; none ; j # V1.1 (↗) NORTH EAST ARROW
161+2198 ; text ; L1 ; none ; j # V1.1 (↘) SOUTH EAST ARROW
162+2199 ; text ; L1 ; none ; j # V1.1 (↙) SOUTH WEST ARROW
163+21A9 ; text ; L1 ; none ; j # V1.1 (↩) LEFTWARDS ARROW WITH HOOK
164+21AA ; text ; L1 ; none ; j # V1.1 (↪) RIGHTWARDS ARROW WITH HOOK
165+231A ; emoji ; L1 ; none ; j # V1.1 (⌚) WATCH
166+231B ; emoji ; L1 ; none ; j # V1.1 (⌛) HOURGLASS
167+2328 ; text ; L2 ; none ; x # V1.1 (⌨) KEYBOARD
168+23CF ; text ; L2 ; none ; x # V4.0 (⏏) EJECT SYMBOL
169+23E9 ; emoji ; L1 ; none ; j w # V6.0 (⏩) BLACK RIGHT-POINTING DOUBLE TRIANGLE
170+23EA ; emoji ; L1 ; none ; j w # V6.0 (⏪) BLACK LEFT-POINTING DOUBLE TRIANGLE
171+23EB ; emoji ; L1 ; none ; j # V6.0 (⏫) BLACK UP-POINTING DOUBLE TRIANGLE
172+23EC ; emoji ; L1 ; none ; j # V6.0 (⏬) BLACK DOWN-POINTING DOUBLE TRIANGLE
173+23ED ; text ; L2 ; none ; w # V6.0 (⏭) BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
174+23EE ; text ; L2 ; none ; w # V6.0 (⏮) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
175+23EF ; text ; L2 ; none ; x # V6.0 (⏯) BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
176+23F0 ; emoji ; L1 ; none ; j # V6.0 (⏰) ALARM CLOCK
177+23F1 ; text ; L2 ; none ; x # V6.0 (⏱) STOPWATCH
178+23F2 ; text ; L2 ; none ; x # V6.0 (⏲) TIMER CLOCK
179+23F3 ; emoji ; L1 ; none ; j w # V6.0 (⏳) HOURGLASS WITH FLOWING SAND
180+23F8 ; text ; L2 ; none ; w # V7.0 (⏸) DOUBLE VERTICAL BAR
181+23F9 ; text ; L2 ; none ; w # V7.0 (⏹) BLACK SQUARE FOR STOP
182+23FA ; text ; L2 ; none ; w # V7.0 (⏺) BLACK CIRCLE FOR RECORD
183+24C2 ; text ; L1 ; none ; j # V1.1 (Ⓜ) CIRCLED LATIN CAPITAL LETTER M
184+25AA ; text ; L1 ; none ; j w # V1.1 (▪) BLACK SMALL SQUARE
185+25AB ; text ; L1 ; none ; j # V1.1 (▫) WHITE SMALL SQUARE
186+25B6 ; text ; L1 ; none ; a j w # V1.1 (▶) BLACK RIGHT-POINTING TRIANGLE
187+25C0 ; text ; L1 ; none ; a j w # V1.1 (◀) BLACK LEFT-POINTING TRIANGLE
188+25FB ; text ; L1 ; none ; j # V3.2 (◻) WHITE MEDIUM SQUARE
189+25FC ; text ; L1 ; none ; j w # V3.2 (◼) BLACK MEDIUM SQUARE
190+25FD ; emoji ; L1 ; none ; j # V3.2 (◽) WHITE MEDIUM SMALL SQUARE
191+25FE ; emoji ; L1 ; none ; j w # V3.2 (◾) BLACK MEDIUM SMALL SQUARE
192+2600 ; text ; L1 ; none ; a j # V1.1 (☀) BLACK SUN WITH RAYS
193+2601 ; text ; L1 ; none ; a j w # V1.1 (☁) CLOUD
194+2602 ; text ; L2 ; none ; a # V1.1 (☂) UMBRELLA
195+2603 ; text ; L2 ; none ; a # V1.1 (☃) SNOWMAN
196+2604 ; text ; L2 ; none ; x # V1.1 (☄) COMET
197+260E ; text ; L1 ; none ; z a j # V1.1 (☎) BLACK TELEPHONE
198+2611 ; text ; L1 ; none ; j w # V1.1 (☑) BALLOT BOX WITH CHECK
199+2614 ; emoji ; L1 ; none ; a j # V4.0 (☔) UMBRELLA WITH RAIN DROPS
200+2615 ; emoji ; L1 ; none ; j # V4.0 (☕) HOT BEVERAGE
201+2618 ; text ; L2 ; none ; x # V4.1 (☘) SHAMROCK
202+261D ; text ; L1 ; secondary ; j w # V1.1 (☝) WHITE UP POINTING INDEX
203+2620 ; text ; L2 ; none ; x # V1.1 (☠) SKULL AND CROSSBONES
204+2622 ; text ; L2 ; none ; x # V1.1 (☢) RADIOACTIVE SIGN
205+2623 ; text ; L2 ; none ; x # V1.1 (☣) BIOHAZARD SIGN
206+2626 ; text ; L2 ; none ; x # V1.1 (☦) ORTHODOX CROSS
207+262A ; text ; L2 ; none ; w # V1.1 (☪) STAR AND CRESCENT
208+262E ; text ; L2 ; none ; x # V1.1 (☮) PEACE SYMBOL
209+262F ; text ; L2 ; none ; w # V1.1 (☯) YIN YANG
210+2638 ; text ; L2 ; none ; w # V1.1 (☸) WHEEL OF DHARMA
211+2639 ; text ; L2 ; secondary ; w # V1.1 (☹) WHITE FROWNING FACE
212+263A ; text ; L1 ; secondary ; j w # V1.1 (☺) WHITE SMILING FACE
213+2648 ; emoji ; L1 ; none ; j w # V1.1 (♈) ARIES
214+2649 ; emoji ; L1 ; none ; j w # V1.1 (♉) TAURUS
215+264A ; emoji ; L1 ; none ; j w # V1.1 (♊) GEMINI
216+264B ; emoji ; L1 ; none ; j w # V1.1 (♋) CANCER
217+264C ; emoji ; L1 ; none ; j w # V1.1 (♌) LEO
218+264D ; emoji ; L1 ; none ; j w # V1.1 (♍) VIRGO
219+264E ; emoji ; L1 ; none ; j w # V1.1 (♎) LIBRA
220+264F ; emoji ; L1 ; none ; j w # V1.1 (♏) SCORPIUS
221+2650 ; emoji ; L1 ; none ; j w # V1.1 (♐) SAGITTARIUS
222+2651 ; emoji ; L1 ; none ; j w # V1.1 (♑) CAPRICORN
223diff --git a/plugins/emoji/emoji.plugin.zsh b/plugins/emoji/emoji.plugin.zsh
224new file mode 100644
225index 0000000000000000000000000000000000000000..a98d0b714c4794bc9a7744108b2a66066bcc3fe2
226--- /dev/null
227+++ b/plugins/emoji/emoji.plugin.zsh
228@@ -0,0 +1,289 @@
229+# emoji plugin
230+#
231+# Makes emoji support available within ZSH
232+#
233+# See the README for documentation.
234+
235+_omz_emoji_plugin_dir="${0:h}"
236+
237+() {
238+
239+local LC_ALL=en_US.UTF-8
240+
241+typeset -gAH emoji_groups
242+typeset -gAH emoji_con
243+typeset -gAH emoji2
244+typeset -gAH emoji_skintone
245+
246+source "$_omz_emoji_plugin_dir/emoji-char-definitions.zsh"
247+unset _omz_emoji_plugin_dir
248+
249+# These additional emoji are not in the definition file, but are useful in conjunction with it
250+
251+# This is a combinin character that can be placed after any other character to surround
252+# it in a "keycap" symbol.
253+# The digits 0-9 are already in the emoji table as keycap_digit_<N>, keycap_ten, etc.
254+# It's unclear whether this should be in the $emoji array, because those characters are all ones
255+# which can be displayed on their own.
256+#emoji[combining_enclosing_keycap]="\U20E3"
257+
258+emoji[regional_indicator_symbol_letter_d_regional_indicator_symbol_letter_e]=$'\xF0\x9F\x87\xA9\xF0\x9F\x87\xAA'
259+emoji[regional_indicator_symbol_letter_g_regional_indicator_symbol_letter_b]=$'\xF0\x9F\x87\xAC\xF0\x9F\x87\xA7'
260+emoji[regional_indicator_symbol_letter_c_regional_indicator_symbol_letter_n]=$'\xF0\x9F\x87\xA8\xF0\x9F\x87\xB3'
261+emoji[regional_indicator_symbol_letter_j_regional_indicator_symbol_letter_p]=$'\xF0\x9F\x87\xAF\xF0\x9F\x87\xB5'
262+emoji[regional_indicator_symbol_letter_k_regional_indicator_symbol_letter_r]=$'\xF0\x9F\x87\xB0\xF0\x9F\x87\xB7'
263+emoji[regional_indicator_symbol_letter_f_regional_indicator_symbol_letter_r]=$'\xF0\x9F\x87\xAB\xF0\x9F\x87\xB7'
264+emoji[regional_indicator_symbol_letter_e_regional_indicator_symbol_letter_s]=$'\xF0\x9F\x87\xAA\xF0\x9F\x87\xB8'
265+emoji[regional_indicator_symbol_letter_i_regional_indicator_symbol_letter_t]=$'\xF0\x9F\x87\xAE\xF0\x9F\x87\xB9'
266+emoji[regional_indicator_symbol_letter_u_regional_indicator_symbol_letter_s]=$'\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8'
267+emoji[regional_indicator_symbol_letter_r_regional_indicator_symbol_letter_u]=$'\xF0\x9F\x87\xB7\xF0\x9F\x87\xBA'
268+
269+# Nonstandard alias names
270+emoji[vulcan_salute]=$'\U1F596'
271+
272+
273+# Emoji combining and auxiliary characters
274+
275+# "Variation Selectors" for controlling text vs emoji style presentation
276+# These apply to the immediately preceding character
277+emoji2[text_style]=$'\UFE0E'
278+emoji2[emoji_style]=$'\UFE0F'
279+# Joiner that indicates a single combined-form glyph (ligature) should be used
280+emoji2[zero_width_joiner]=$'\U200D'
281+# Skin tone modifiers
282+emoji2[emoji_modifier_fitzpatrick_type_1_2]=$'\U1F3FB'
283+emoji2[emoji_modifier_fitzpatrick_type_3]=$'\U1F3FC'
284+emoji2[emoji_modifier_fitzpatrick_type_4]=$'\U1F3FD'
285+emoji2[emoji_modifier_fitzpatrick_type_5]=$'\U1F3FE'
286+emoji2[emoji_modifier_fitzpatrick_type_6]=$'\U1F3FF'
287+# Various other combining characters. (Incomplete list; I selected ones that sound useful)
288+emoji2[combining_enclosing_circle]=$'\U20DD'
289+emoji2[combining_enclosing_square]=$'\U20DE'
290+emoji2[combining_enclosing_diamond]=$'\U20DF'
291+emoji2[combining_enclosing_circle_backslash]=$'\U20E0'
292+emoji2[combining_enclosing_screen]=$'\U20E2'
293+emoji2[combining_enclosing_keycap]=$'\U20E3'
294+emoji2[combining_enclosing_upward_pointing_triangle]=$'\U20E4'
295+
296+# Easier access to skin tone modifiers
297+emoji_skintone[1_2]=$'\U1F3FB'
298+emoji_skintone[3]=$'\U1F3FC'
299+emoji_skintone[4]=$'\U1F3FD'
300+emoji_skintone[5]=$'\U1F3FE'
301+emoji_skintone[6]=$'\U1F3FF'
302+
303+# Emoji groups
304+# These are stored in a single associative array, $emoji_groups, to avoid cluttering up the global
305+# namespace, and to allow adding additional group definitions at run time.
306+# The keys are the group names, and the values are whitespace-separated lists of emoji character names.
307+#
308+# These extra local arrays are used to allow more convenient formatting of the source code.
309+
310+emoji_groups[fruits]="
311+ tomato
312+ aubergine
313+ grapes
314+ melon
315+ watermelon
316+ tangerine
317+ banana
318+ pineapple
319+ red_apple
320+ green_apple
321+ peach
322+ cherries
323+ strawberry
324+ lemon
325+ pear
326+"
327+
328diff --git a/plugins/emoji/update_emoji.pl b/plugins/emoji/update_emoji.pl
329new file mode 100644
330index 0000000000000000000000000000000000000000..d90c6e31622e362038880a64d26c41dc6f860580
331--- /dev/null
332+++ b/plugins/emoji/update_emoji.pl
333@@ -0,0 +1,113 @@
334+#!/usr/bin/perl -w
335+#
336+# update_emoji.pl
337+#
338+# This script generates the emoji.plugin.zsh emoji definitions from the Unicode
339+# character data for the emoji characters.
340+#
341+# The data file can be found at http://unicode.org/Public/emoji/latest/emoji-data.txt
342+# as referenced in Unicode TR51 (http://www.unicode.org/reports/tr51/index.html).
343+#
344+# This is known to work with the data file from version 1.0. It may not work with later
345+# versions if the format changes. In particular, this reads line comments to get the
346+# emoji character name and unicode version.
347+#
348+# Country names have punctuation and other non-letter characters removed from their name,
349+# to avoid possible complications with having to escape the strings when using them as
350+# array subscripts. The definition file seems to use some combining characters like accents
351+# that get stripped during this process.
352+
353+use strict;
354+use warnings;
355+use 5.010;
356+use autodie;
357+
358+use Path::Class;
359+use File::Copy;
360+
361+# Parse definitions out of the data file and convert
362+sub process_emoji_data_file {
363+ my ( $infile, $outfilename ) = @_;
364+ my $file = file($infile);
365+ my $outfile = file($outfilename);
366+ my $outfilebase = $outfile->basename();
367+ my $tempfilename = "$outfilename.tmp";
368+ my $tempfile = file($tempfilename);
369+ my $outfh = $tempfile->openw();
370+ $outfh->print("
371+# $outfilebase - Emoji character definitions for oh-my-zsh emoji plugin
372+#
373+# This file is auto-generated by update_emoji.pl. Do not edit it manually.
374+#
375+# This contains the definition for:
376+# \$emoji - which maps character names to Unicode characters
377+# \$emoji_flags - maps country names to Unicode flag characters using region indicators
378+
379+# Main emoji
380+typeset -gAH emoji
381+# National flags
382+typeset -gAH emoji_flags
383+# Combining modifiers
384+typeset -gAH emoji_mod
385+
386+");
387+
388+ my $fh = $file->openr();
389+ my $line_num = 0;
390+ while ( my $line = $fh->getline() ) {
391+ $line_num++;
392+ $_ = $line;
393+ # Skip all-comment lines (from the header) and blank lines
394+ # (But don't strip comments on normal lines; we need to parse those for
395+ # the emoji names.)
396+ next if /^\s*#/ or /^\s*$/;
397+
398+ if (/^(\S.*?\S)\s*;\s*(\w+)\s*;\s*(\w+)\s*;\s*(\w+)\s*;\s*(\w.*?)\s*#\s*V(\S+)\s\(.*?\)\s*(\w.*\S)\s*$/) {
399+ my ($code, $style, $level, $modifier_status, $sources, $version, $keycap_name)
400+ = ($1, $2, $3, $4, $5, $6, $7);
401+ #print "code=$code style=$style level=$level modifier_status=$modifier_status sources=$sources version=$version name=$keycap_name\n";
402+ my @code_points = split /\s+/, $code;
403+ my @sources = split /\s+/, $sources;
404+
405+ my $flag_country = "";
406+ if ( $keycap_name =~ /^flag for (\S.*?)\s*$/) {
407+ $flag_country = $1;
408+ }
409+
410+ my $zsh_code = join '', map { "\\U$_" } @code_points;
411+ # Convert keycap names to valid associative array names that do not require any
412+ # quoting. Works fine for most stuff, but is clumsy for flags.
413+ my $omz_name = lc($keycap_name);
414+ $omz_name =~ s/[^A-Za-z0-9]/_/g;
415+ my $zsh_flag_country = $flag_country;
416+ $zsh_flag_country =~ s/[^\p{Letter}]/_/g;
417+ if ($flag_country) {
418+ $outfh->print("emoji_flags[$zsh_flag_country]=\$'$zsh_code'\n");
419+ } else {
420+ $outfh->print("emoji[$omz_name]=\$'$zsh_code'\n");
421+ }
422+ # Modifiers are included in both the main set and their separate map,
423+ # because they have a standalone representation as a color swatch.
424+ if ( $modifier_status == "modifier" ) {
425+ $outfh->print("emoji_mod[$omz_name]=\$'$zsh_code'\n");
426+ }
427+ } else {
428+ die "Failed parsing line $line_num: '$_'";
429+ }
430+ }
431+ $fh->close();
432+ $outfh->print("\n");