afc36e2710c05f031eb0b6449243881e78796de0

Author
Robby Russell <robby@planetargon.com>
Committer
Robby Russell <robby@planetargon.com>
Date

Message

Merge pull request #2446 from fallwith/emoji_plugin

Emoji plugin

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");