all repos — emoji @ 84a0a67371e0847129343a1165bdd41e95f5b49d

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)
 11
 12var (
 13	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>.+)$`)
 14	toneRegex  = regexp.MustCompile(`:\s.*tone,?`)
 15)
 16
 17type groups struct {
 18	Groups []*group
 19}
 20
 21func (g *groups) Append(grpName string) *group {
 22	// fmt.Printf("group: %v\n", grpName)
 23	grp := group{Name: grpName}
 24	g.Groups = append(g.Groups, &grp)
 25
 26	return &grp
 27}
 28
 29type group struct {
 30	Name      string
 31	Subgroups []*subgroup
 32}
 33
 34func (g *group) Append(subgrpName string) *subgroup {
 35	// fmt.Printf("subgroup: %v\n", subgrpName)
 36	subgrp := subgroup{Name: subgrpName, Emojis: make(map[string][]emoji)}
 37	g.Subgroups = append(g.Subgroups, &subgrp)
 38
 39	return &subgrp
 40}
 41
 42type subgroup struct {
 43	Name      string
 44	Emojis    map[string][]emoji
 45	Constants []string
 46}
 47
 48func (s *subgroup) Append(e emoji) {
 49	// fmt.Printf("emoji: %v\n", e)
 50	if _, ok := s.Emojis[e.Constant]; ok {
 51		s.Emojis[e.Constant] = append(s.Emojis[e.Constant], e)
 52	} else {
 53		s.Emojis[e.Constant] = []emoji{e}
 54		s.Constants = append(s.Constants, e.Constant)
 55	}
 56}
 57
 58type emoji struct {
 59	Name     string
 60	Constant string
 61	Code     string
 62	Tones    []string
 63}
 64
 65func (e *emoji) String() string {
 66	return fmt.Sprintf("name:%v, constant:%v, code:%v, tones: %v\n", e.Name, e.Constant, e.Code, e.Tones)
 67}
 68
 69func newEmoji(line string) *emoji {
 70	matches := emojiRegex.FindStringSubmatch(line)
 71	if len(matches) < 4 {
 72		return nil
 73	}
 74	code := matches[1]
 75	name := matches[3]
 76
 77	e := emoji{
 78		Name:     name,
 79		Constant: name,
 80		Code:     code,
 81		Tones:    []string{},
 82	}
 83	e.extractAttr()
 84	e.Constant = generateConstant(e.Constant)
 85	e.Code = generateUnicode(e.Code)
 86
 87	return &e
 88}
 89
 90func (e *emoji) extractAttr() {
 91	parts := strings.Split(e.Constant, ":")
 92	if len(parts) < 2 {
 93		// no attributes
 94		return
 95	}
 96	c := parts[0]
 97	attrs := strings.Split(parts[1], ",")
 98	for _, attr := range attrs {
 99		switch {
100		case strings.Contains(attr, "tone"):
101			e.Tones = append(e.Tones, attr)
102		case strings.Contains(attr, "beard"):
103			fallthrough
104		case strings.Contains(attr, "hair"):
105			c += " with " + attr
106		case strings.HasPrefix(c, "flag"):
107			c += " for " + attr
108		default:
109			c += " " + attr
110		}
111	}
112	e.Constant = c
113}
114
115func generateConstant(c string) string {
116	c = clean(c)
117	c = strings.Title(strings.ToLower(c))
118	c = removeSpaces(c)
119
120	return c
121}
122
123func generateUnicode(code string) string {
124	unicodes := []string{}
125	for _, v := range strings.Split(code, " ") {
126		u, err := strconv.ParseInt(v, 16, 32)
127		if err != nil {
128			panic(fmt.Errorf("unknown unicode: %v", v))
129		}
130		unicodes = append(unicodes, string(u))
131	}
132
133	return 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}