2019-11-17 22:01:03 +00:00
|
|
|
// Package emoji terminal output.
|
|
|
|
package emoji
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"regexp"
|
|
|
|
"unicode"
|
|
|
|
)
|
|
|
|
|
2021-04-03 17:16:46 +00:00
|
|
|
//go:generate generateEmojiCodeMap -pkg emoji -o emoji_codemap.go
|
2019-11-17 22:01:03 +00:00
|
|
|
|
|
|
|
// Replace Padding character for emoji.
|
2021-04-03 17:16:46 +00:00
|
|
|
var (
|
|
|
|
ReplacePadding = " "
|
2019-11-17 22:01:03 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// CodeMap gets the underlying map of emoji.
|
|
|
|
func CodeMap() map[string]string {
|
2021-04-03 17:16:46 +00:00
|
|
|
return emojiCode()
|
|
|
|
}
|
|
|
|
|
|
|
|
// RevCodeMap gets the underlying map of emoji.
|
|
|
|
func RevCodeMap() map[string][]string {
|
|
|
|
return emojiRevCode()
|
|
|
|
}
|
|
|
|
|
|
|
|
func AliasList(shortCode string) []string {
|
|
|
|
return emojiRevCode()[emojiCode()[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]
|
2019-11-17 22:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// regular expression that matches :flag-[countrycode]:
|
|
|
|
var flagRegexp = regexp.MustCompile(":flag-([a-z]{2}):")
|
|
|
|
|
2023-03-09 21:48:00 +00:00
|
|
|
// Emojize Converts the string passed as an argument to a emoji. For unsupported emoji, the string passed as an argument is returned as is.
|
|
|
|
func Emojize(x string) string {
|
2021-04-03 17:16:46 +00:00
|
|
|
str, ok := emojiCode()[x]
|
2019-11-17 22:01:03 +00:00
|
|
|
if ok {
|
|
|
|
return str + ReplacePadding
|
|
|
|
}
|
|
|
|
if match := flagRegexp.FindStringSubmatch(x); len(match) == 2 {
|
|
|
|
return regionalIndicator(match[1][0]) + regionalIndicator(match[1][1])
|
|
|
|
}
|
|
|
|
return x
|
|
|
|
}
|
|
|
|
|
|
|
|
// regionalIndicator maps a lowercase letter to a unicode regional indicator
|
|
|
|
func regionalIndicator(i byte) string {
|
|
|
|
return string('\U0001F1E6' + rune(i) - 'a')
|
|
|
|
}
|
|
|
|
|
|
|
|
func replaseEmoji(input *bytes.Buffer) string {
|
|
|
|
emoji := bytes.NewBufferString(":")
|
|
|
|
for {
|
|
|
|
i, _, err := input.ReadRune()
|
|
|
|
if err != nil {
|
|
|
|
// not replase
|
|
|
|
return emoji.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
if i == ':' && emoji.Len() == 1 {
|
|
|
|
return emoji.String() + replaseEmoji(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
emoji.WriteRune(i)
|
|
|
|
switch {
|
|
|
|
case unicode.IsSpace(i):
|
|
|
|
return emoji.String()
|
|
|
|
case i == ':':
|
2023-03-09 21:48:00 +00:00
|
|
|
return Emojize(emoji.String())
|
2019-11-17 22:01:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func compile(x string) string {
|
|
|
|
if x == "" {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
input := bytes.NewBufferString(x)
|
|
|
|
output := bytes.NewBufferString("")
|
|
|
|
|
|
|
|
for {
|
|
|
|
i, _, err := input.ReadRune()
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
switch i {
|
|
|
|
default:
|
|
|
|
output.WriteRune(i)
|
|
|
|
case ':':
|
|
|
|
output.WriteString(replaseEmoji(input))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return output.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print is fmt.Print which supports emoji
|
|
|
|
func Print(a ...interface{}) (int, error) {
|
|
|
|
return fmt.Print(compile(fmt.Sprint(a...)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Println is fmt.Println which supports emoji
|
|
|
|
func Println(a ...interface{}) (int, error) {
|
|
|
|
return fmt.Println(compile(fmt.Sprint(a...)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Printf is fmt.Printf which supports emoji
|
|
|
|
func Printf(format string, a ...interface{}) (int, error) {
|
2021-04-03 17:16:46 +00:00
|
|
|
return fmt.Print(compile(fmt.Sprintf(format, a...)))
|
2019-11-17 22:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fprint is fmt.Fprint which supports emoji
|
|
|
|
func Fprint(w io.Writer, a ...interface{}) (int, error) {
|
|
|
|
return fmt.Fprint(w, compile(fmt.Sprint(a...)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fprintln is fmt.Fprintln which supports emoji
|
|
|
|
func Fprintln(w io.Writer, a ...interface{}) (int, error) {
|
|
|
|
return fmt.Fprintln(w, compile(fmt.Sprint(a...)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fprintf is fmt.Fprintf which supports emoji
|
|
|
|
func Fprintf(w io.Writer, format string, a ...interface{}) (int, error) {
|
|
|
|
return fmt.Fprint(w, compile(fmt.Sprintf(format, a...)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sprint is fmt.Sprint which supports emoji
|
|
|
|
func Sprint(a ...interface{}) string {
|
|
|
|
return compile(fmt.Sprint(a...))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sprintf is fmt.Sprintf which supports emoji
|
|
|
|
func Sprintf(format string, a ...interface{}) string {
|
|
|
|
return compile(fmt.Sprintf(format, a...))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Errorf is fmt.Errorf which supports emoji
|
|
|
|
func Errorf(format string, a ...interface{}) error {
|
|
|
|
return errors.New(compile(Sprintf(format, a...)))
|
|
|
|
}
|