diff --git a/emoji.go b/emoji.go index 11644ec..4e35ef4 100644 --- a/emoji.go +++ b/emoji.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "regexp" + "sort" "unicode" ) @@ -22,6 +23,48 @@ func CodeMap() map[string]string { return emojiCodeMap } +// emojiRevCodeMap maps unicode characters to lists of short codes. +var emojiRevCodeMap = make(map[string][]string, len(emojiCodeMap)) + +func init() { + for shortCode, unicode := range emojiCodeMap { + emojiRevCodeMap[unicode] = append(emojiRevCodeMap[unicode], shortCode) + } + // ensure deterministic ordering for aliases + for _, value := range emojiRevCodeMap { + sort.Slice(value, func(i, j int) bool { + if len(value[i]) == len(value[j]) { + return value[i] < value[j] + } + return len(value[i]) < len(value[j]) + }) + } +} + +// RevCodeMap gets the underlying map of emoji. +func RevCodeMap() map[string][]string { + return emojiRevCodeMap +} + +func AliasList(shortCode string) []string { + return emojiRevCodeMap[emojiCodeMap[shortCode]] +} + +// HasAlias flags if the given `shortCode` has multiple aliases with other +// codes. +func HasAlias(shortCode string) bool { + return len(AliasList(shortCode)) > 1 +} + +// NormalizeShortCode normalizes a given `shortCode` to a deterministic alias. +func NormalizeShortCode(shortCode string) string { + shortLists := AliasList(shortCode) + if len(shortLists) == 0 { + return shortCode + } + return shortLists[0] +} + // regular expression that matches :flag-[countrycode]: var flagRegexp = regexp.MustCompile(":flag-([a-z]{2}):") @@ -99,7 +142,7 @@ func Println(a ...interface{}) (int, error) { // Printf is fmt.Printf which supports emoji func Printf(format string, a ...interface{}) (int, error) { - return fmt.Printf(compile(fmt.Sprintf(format, a...))) + return fmt.Print(compile(fmt.Sprintf(format, a...))) } // Fprint is fmt.Fprint which supports emoji diff --git a/emoji_test.go b/emoji_test.go index 8450764..971441a 100644 --- a/emoji_test.go +++ b/emoji_test.go @@ -59,6 +59,38 @@ func TestCodeMap(t *testing.T) { } } +func TestRevCodeMap(t *testing.T) { + m := RevCodeMap() + if &emojiRevCodeMap == &m { + t.Error("emojiRevCodeMap != EmojiRevCodeMap") + } +} + +func TestHasAlias(t *testing.T) { + hasAlias := HasAlias(":+1:") + if !hasAlias { + t.Error(":+1: doesn't have an alias") + } + hasAlias = HasAlias(":no-good:") + if hasAlias { + t.Error(":no-good: has an alias") + } +} + +func TestNoramlizeShortCode(t *testing.T) { + test := ":thumbs_up:" + expected := ":+1:" + normalized := NormalizeShortCode(test) + if normalized != expected { + t.Errorf("Normalized %q != %q", test, expected) + } + test = ":no-good:" + normalized = NormalizeShortCode(test) + if normalized != test { + t.Errorf("Normalized %q != %q", test, normalized) + } +} + func TestPrint(t *testing.T) { _, err := Print(beerKey, beerText) if err != nil { @@ -154,7 +186,7 @@ func BenchmarkFprint(b *testing.B) { defer putBuffer(buff) Fprint(buff, string(in)) - bc := make([]byte, buff.Len(), buff.Len()) + bc := make([]byte, buff.Len()) copy(bc, buff.Bytes()) return bc }