all repos — emoji @ cf2567abaf2c0088ccf0492340530c25b6bcef19

A minimalistic emoji package for Go (golang)

internal/generator/emoji.go (view raw)

  1package main
  2
  3import (
  4	"fmt"
  5	"regexp"
  6	"strconv"
  7	"strings"
  8
  9	emojipkg "github.com/enescakir/emoji"
 10	"github.com/enescakir/emoji/internal/strutil"
 11)
 12
 13var (
 14	emojiRegex = regexp.MustCompile(`^(?m)(?P<code>[A-Z\d ]+[A-Z\d])\s+;\s+(fully-qualified|component)\s+#\s+.+\s+E\d+\.\d+ (?P<name>.+)$`)
 15	toneRegex  = regexp.MustCompile(`:\s.*tone,?`)
 16)
 17
 18type groups struct {
 19	Groups []*group
 20}
 21
 22func (g *groups) Append(grpName string) *group {
 23	// fmt.Printf("group: %v\n", grpName)
 24	grp := group{Name: grpName}
 25	g.Groups = append(g.Groups, &grp)
 26
 27	return &grp
 28}
 29
 30type group struct {
 31	Name      string
 32	Subgroups []*subgroup
 33}
 34
 35func (g *group) Append(subgrpName string) *subgroup {
 36	// fmt.Printf("subgroup: %v\n", subgrpName)
 37	subgrp := subgroup{Name: subgrpName, Emojis: make(map[string][]emoji)}
 38	g.Subgroups = append(g.Subgroups, &subgrp)
 39
 40	return &subgrp
 41}
 42
 43type subgroup struct {
 44	Name      string
 45	Emojis    map[string][]emoji
 46	Constants []string
 47}
 48
 49func (s *subgroup) Append(e emoji) {
 50	// fmt.Printf("emoji: %v\n", e)
 51	if _, ok := s.Emojis[e.Constant]; ok {
 52		s.Emojis[e.Constant] = append(s.Emojis[e.Constant], e)
 53	} else {
 54		s.Emojis[e.Constant] = []emoji{e}
 55		s.Constants = append(s.Constants, e.Constant)
 56	}
 57}
 58
 59type emoji struct {
 60	Name     string
 61	Constant string
 62	Code     string
 63	Tones    []string
 64}
 65
 66func (e *emoji) String() string {
 67	return fmt.Sprintf("name:%v, constant:%v, code:%v, tones: %v\n", e.Name, e.Constant, e.Code, e.Tones)
 68}
 69
 70func newEmoji(line string) *emoji {
 71	matches := emojiRegex.FindStringSubmatch(line)
 72	if len(matches) < 4 {
 73		return nil
 74	}
 75	code := matches[1]
 76	name := matches[3]
 77
 78	e := emoji{
 79		Name:     name,
 80		Constant: name,
 81		Code:     code,
 82		Tones:    []string{},
 83	}
 84	e.extractAttr()
 85	e.generateConstant()
 86	e.generateUnicode()
 87
 88	return &e
 89}
 90
 91func (e *emoji) extractAttr() {
 92	parts := strings.Split(e.Constant, ":")
 93	if len(parts) < 2 {
 94		// no attributes
 95		return
 96	}
 97	c := parts[0]
 98	attrs := strings.Split(parts[1], ",")
 99	for _, attr := range attrs {
100		switch {
101		case strings.Contains(attr, "tone"):
102			e.Tones = append(e.Tones, attr)
103		case strings.Contains(attr, "beard"):
104			fallthrough
105		case strings.Contains(attr, "hair"):
106			c += " with " + attr
107		case strings.HasPrefix(c, "flag"):
108			c += " for " + attr
109		default:
110			c += " " + attr
111		}
112	}
113	e.Constant = c
114}
115
116func (e *emoji) generateConstant() {
117	c := e.Constant
118	c = strutil.Clean(c)
119	c = strings.Title(strings.ToLower(c))
120	c = strutil.RemoveSpaces(c)
121	e.Constant = c
122}
123
124func (e *emoji) generateUnicode() {
125	unicodes := []string{}
126	for _, v := range strings.Split(e.Code, " ") {
127		u, err := strconv.ParseInt(v, 16, 32)
128		if err != nil {
129			panic(fmt.Errorf("unknown unicode: %v", v))
130		}
131		unicodes = append(unicodes, string(u))
132	}
133	e.Code = strings.Join(unicodes, "")
134}
135
136func defaultTone(basic, toned string) string {
137	toneInd := strings.IndexRune(toned, []rune(emojipkg.TonePlaceholder)[0])
138	for i, ch := range basic {
139		if i != toneInd {
140			continue
141		}
142		if ch == '\ufe0f' {
143			return "\ufe0f"
144		}
145		break
146	}
147
148	return ""
149}
150
151func replaceTones(code string) string {
152	for _, tone := range []emojipkg.Tone{
153		emojipkg.Light,
154		emojipkg.MediumLight,
155		emojipkg.Medium,
156		emojipkg.MediumDark,
157		emojipkg.Dark,
158	} {
159		code = strings.ReplaceAll(code, tone.String(), emojipkg.TonePlaceholder)
160	}
161
162	return code
163}