1
0
mirror of https://github.com/fumiama/emozi.git synced 2026-06-05 00:32:48 +08:00

feat: add cmd

This commit is contained in:
源文雨
2024-02-15 17:14:56 +09:00
parent 96223b1b74
commit 7e641e891e
11 changed files with 712 additions and 488 deletions

View File

@@ -7,7 +7,63 @@
</div> </div>
W.I.P. ## 命令行工具
位于`cmd`文件夹。
```bash
用法: [-h|f|nr] [-db 字.db] [-d 🌹😺‎🐴‫👩] [-e 好] 形声字选择1 形声字选择2 ...
-a string
添加一个汉字到附加库
-d string
解码颜文字为汉字序列
-db string
符合规范的查询数据库位置, 不存在则会自动释放到该路径. (default "字.db")
-e string
编码汉字序列为颜文字
-f 强制解码并非由本程序生成的颜文字序列
-h 显示帮助信息
-i 指定汉字-a和带声调的拼音-p以计算其全局唯一ID
-nr
不随机选取所有读音相近的颜文字
-p string
带声调的拼音
-r string
指定欲编辑的部首
-re string
指定部首对应的颜文字
```
下面是一些用例。
### 编码
> 注意: 可以指定`-nr`参数从而使编解码结果唯一。
```bash
go run cmd/main.go -e 好
编码结果: 🌹😺‎🐴‫👩
```
### 解码
```bash
go run cmd/main.go -d 🌹😺‎🐴‫👩
解码结果: 好
```
### 添加一个字到附加库
```bash
go run cmd/main.go -e 的
编码结果: 的‬🈳⁠🈳⁦🈳
go run cmd/main.go -a 的 -p de -r 日 -re 🌞
已添加汉字: 的 读音: t, ɤ, 轻声 部首: 日 ID: 130309308023300
已添加部首: 日 颜文字: 🌞
go run cmd/main.go -e 的
编码结果: 🔪😋⁦😯‏🌞
```
### 指定多音字
```bash
go run cmd/main.go -e 你好,世界!看看多音字:行。
编码结果: 🥛​👔🐴‮👤🐒🐱🐎👩,🌴☀️😨🌍➖✌️😨👨‍🌾!👖🔐🍉👁️😭🔐🍉👁️🕳️🌀🍉🪩🧂🎵🍉🎵⬅️☀️😨🚼:[🌟🦅🦎⛕|🌷👍🦎⛕]
可选形声: [2]
在参数中指定形声字编号(从0开始)以生成不带中括号的编码结果
go run cmd/main.go -e 你好,世界!看看多音字:行。 1
编码结果: 🥛⁦👔⁢🐴👤🐵🐈‍⬛🐎👩,🪸☀️😨🌍🐓✌️😨👨‍🌾!👖🔐🍉👁️😭🔐🍉👁️🪔🌀🍉🪩💊🎵🍉🎵👈🌅😨🚼:🐅👍🧗‍♂️⛕。
go run cmd/main.go -d 🥛⁦👔⁢🐴👤🐵🐈‍⬛🐎👩,🪸☀️😨🌍🐓✌️😨👨‍🌾!👖🔐🍉👁️😭🔐🍉👁️🪔🌀🍉🪩💊🎵🍉🎵👈🌅😨🚼:🐅👍🧗‍♂️⛕。
解码结果: [|]好,世[|]!看看多音字:行。
```
## 实用工具 ## 实用工具
### 拼音识别拆分 ### 拼音识别拆分

94
cmd/main.go Normal file
View File

@@ -0,0 +1,94 @@
package main
import (
"flag"
"fmt"
"strconv"
"time"
"github.com/fumiama/emozi"
)
func main() {
dbpath := flag.String("db", emozi.EmoziDatabasePath, "符合规范的查询数据库位置, 不存在则会自动释放到该路径.")
isencode := flag.String("e", "", "编码汉字序列为颜文字")
isdecode := flag.String("d", "", "解码颜文字为汉字序列")
getglobalid := flag.Bool("i", false, "指定汉字-a和带声调的拼音-p以计算其全局唯一ID")
addoverlay := flag.String("a", "", "添加一个汉字到附加库")
pinyinfull := flag.String("p", "", "带声调的拼音")
radical := flag.String("r", "", "指定欲编辑的部首")
radicalemozi := flag.String("re", "", "指定部首对应的颜文字")
noRandom := flag.Bool("nr", false, "不随机选取所有读音相近的颜文字")
showhelp := flag.Bool("h", false, "显示帮助信息")
forcedecode := flag.Bool("f", false, "强制解码并非由本程序生成的颜文字序列")
flag.Parse()
if *showhelp {
fmt.Println("用法: [-h|f|nr] [-db 字.db] [-d 🌹😺‎🐴‫👩] [-e 好] 形声字选择1 形声字选择2 ...")
flag.PrintDefaults()
return
}
emozi.EmoziDatabasePath = *dbpath
coder, err := emozi.NewCoder(time.Minute)
if err != nil {
panic(err)
}
defer coder.Close()
if *isencode != "" {
rem := flag.Args()
lst := make([]int, len(rem))
for i, ns := range rem {
n, err := strconv.Atoi(ns)
if err != nil {
panic("第" + strconv.Itoa(i+1) + "个形声字参数 '" + ns + "' 非法")
}
lst[i] = n
}
es, lst, err := coder.Encode(!*noRandom, *isencode, lst...)
if err != nil {
panic(err)
}
fmt.Println("编码结果:", string(es))
if len(lst) > 0 && len(rem) == 0 {
fmt.Println("可选形声:", lst)
fmt.Println("在参数中指定形声字编号(从0开始)以生成不带中括号的编码结果")
}
}
if *isdecode != "" {
s, err := coder.Decode(emozi.EmoziString(*isdecode), *forcedecode)
switch {
case err == emozi.ErrInvalidEmoziString:
fmt.Println("解码结果: 非本程序直接生成的颜文字序列或序列经过人为修改")
case err != nil:
panic(err)
default:
fmt.Println("解码结果:", s)
}
}
if *addoverlay != "" && *pinyinfull != "" && *radical != "" {
id, desc, err := coder.AddCharOverlay(*addoverlay, *radical, "", *pinyinfull)
if err != nil {
panic(err)
}
fmt.Println("已添加汉字:", *addoverlay, "读音:", desc, "部首:", *radical, "ID:", id)
}
if *radical != "" && *radicalemozi != "" {
rr := []rune(*radical)
if len(rr) != 1 {
panic("非法部首 '" + *radical + "': 长度为" + strconv.Itoa(len(rr)))
}
err = coder.AddRadicalOverlay(rr[0], *radicalemozi)
if err != nil {
panic(err)
}
fmt.Println("已添加部首:", *radical, "颜文字:", *radicalemozi)
}
if *getglobalid && *addoverlay != "" && *pinyinfull != "" {
sm, ym, sd, err := emozi.SplitPinyin(*pinyinfull)
if err != nil {
panic(err)
}
r := []rune(*addoverlay)[0]
id, _ := emozi.CharGlobalID(r, *pinyinfull)
fmt.Println("文字:", string(r), "拼音IPA:", sm, ym, sd, "ID:", id)
}
}

View File

@@ -13,9 +13,9 @@ const head = `// Code generated by codegen/radical. 已经经过修改, 不要
package emozi package emozi
// 部首后备 内嵌的部首到颜文字的映射, 是第二优先查询顺位. 第一顺位是数据库的部首表. 第三位是回落到 🈳. // 部首后备 内嵌的部首到颜文字的映射, 是第二优先查询顺位. 第一顺位是数据库的部首表. 第三位是回落到 🈳.
var 部首后备 = map[rune]string{ {{range .}} var 部首后备 = map[rune]string{ {{range .}}
'{{.R}}': ,{{end}} '{{.R}}': string(空),{{end}}
} }
` `

View File

@@ -68,20 +68,34 @@ func (c *Coder) Close() error {
// Encode 从汉字序列生成 EmoziString 返回 EmoziString 多音字选择数列表 // Encode 从汉字序列生成 EmoziString 返回 EmoziString 多音字选择数列表
func (c *Coder) Encode(enableRandom bool, s string, selections ...int) (EmoziString, []int, error) { func (c *Coder) Encode(enableRandom bool, s string, selections ...int) (EmoziString, []int, error) {
sb := strings.Builder{} sb := strings.Builder{}
lstbuf := make([]字表, 0, len(s)/2) buflen := len(s) / 2
if buflen < 4 {
buflen = 4
}
lstbuf := make([]字表, 0, buflen)
var lst []字表 var lst []字表
write := func(x *字表) { var write func(x *字表)
randomwrite := func(x *字表) {
sb.WriteString(c.声母(enableRandom, x.S)) sb.WriteString(c.声母(enableRandom, x.S))
sb.WriteString(c.韵母(enableRandom, x.Y)) sb.WriteString(c.韵母(enableRandom, x.Y))
sb.WriteString(c.声调(enableRandom, x.T)) sb.WriteString(c.声调(enableRandom, x.T))
sb.WriteString(c.部首(x.R)) sb.WriteString(c.部首(x.R))
} }
norandomwrite := func(x *字表) {
sb.WriteString(c.声母(false, x.S))
sb.WriteString(c.韵母(false, x.Y))
sb.WriteString(c.声调(false, x.T))
sb.WriteString(c.部首(x.R))
write = randomwrite
}
write = norandomwrite
多音字计数 := 0 多音字计数 := 0
多音字数表 := []int{} 多音字数表 := []int{}
var err error var err error
for _, ch := range s { // nolint: go-staticcheck for _, ch := range s { // nolint: go-staticcheck
lst, lstbuf, err = c.查字(ch, lstbuf) lst, lstbuf, err = c.查字(ch, lstbuf)
if err != nil || len(lst) == 0 { if err != nil || len(lst) == 0 {
//fmt.Println("写入未知字:", string(ch), ch)
sb.WriteRune(ch) sb.WriteRune(ch)
continue continue
} }
@@ -121,6 +135,7 @@ func (c *Coder) Decode(es EmoziString, forcedecode bool) (string, error) {
} else { } else {
s = es.String() s = es.String()
} }
// fmt.Println(len(s), s)
lstbuf := make([]字表, 0, len(s)/8) lstbuf := make([]字表, 0, len(s)/8)
read := func(s string) (string, int) { read := func(s string) (string, int) {
sum := 0 sum := 0
@@ -129,21 +144,25 @@ func (c *Coder) Decode(es EmoziString, forcedecode bool) (string, error) {
return "", 0 return "", 0
} }
sum += n sum += n
// fmt.Println(n, sm, s[0:sum])
ym, n := c.逆韵母(s[sum:]) ym, n := c.逆韵母(s[sum:])
if n == 0 { if n == 0 {
return "", 0 return "", 0
} }
sum += n sum += n
// fmt.Println(n, ym, s[sum-n:sum])
t, n := c.逆声调(s[sum:]) t, n := c.逆声调(s[sum:])
if n == 0 { if n == 0 {
return "", 0 return "", 0
} }
sum += n sum += n
// fmt.Println(n, t, s[sum-n:sum])
rs, n := c.逆部首(s[sum:]) rs, n := c.逆部首(s[sum:])
if n == 0 { if n == 0 {
return "", 0 return "", 0
} }
sum += n sum += n
// fmt.Println(n, rs, s[sum-n:sum])
var possibles []rune var possibles []rune
var err error var err error
if len(rs) == 0 { // 意符为空 if len(rs) == 0 { // 意符为空
@@ -223,41 +242,49 @@ func (c *Coder) AddChar(w, r, p, f string) error {
// AddCharOverlay 向附加库添加一个新字, 覆盖在主库之上 // AddCharOverlay 向附加库添加一个新字, 覆盖在主库之上
// //
// w: 字, r: 部首, p: 不带声调的拼音(可空), f: 带声调的拼音 // w: 字, r: 部首, p: 不带声调的拼音(可空), f: 带声调的拼音
func (c *Coder) AddCharOverlay(w, r, p, f string) error { // 返回: 字表ID, 文字描述, error
func (c *Coder) AddCharOverlay(w, r, p, f string) (int64, string, error) {
if p == "" { if p == "" {
p = 去调(f) p = 去调(f)
} }
s, y, t, rw, rr, err := 拆音识字(w, r, p, f) s, y, t, rw, rr, err := 拆音识字(w, r, p, f)
if err != nil { if err != nil {
return err return 0, "", err
} }
return c.addcharoverlay(w, p, f, s, y, t, rw, rr) return c.addcharoverlay(w, p, f, s, y, t, rw, rr)
} }
func (c *Coder) addcharoverlay(w, p, f string, s 声母枚举, y 韵母枚举, t 声调枚举, rw rune, rr rune) error { func (c *Coder) addcharoverlay(w, p, f string, s 声母枚举, y 韵母枚举, t 声调枚举, rw rune, rr rune) (int64, string, error) {
id := 字表ID(rw, s, y, t)
c.mu.Lock() c.mu.Lock()
err := c.db.InsertUnique(附字表名, &字表{ err := c.db.InsertUnique(附字表名, &字表{
ID: 字表ID(rw, s, y, t), ID: id,
W: rw, S: s, Y: y, T: t, W: rw, S: s, Y: y, T: t,
R: rr, P: p, F: f, R: rr, P: p, F: f,
}) })
c.mu.Unlock() c.mu.Unlock()
if err != nil { if err != nil {
return errors.New("已有同音同形的字 '" + w + "'") return 0, "", errors.New("已有同音同形的字 '" + w + "'")
} }
return nil sb := strings.Builder{}
sb.WriteString(s.String())
sb.WriteString(", ")
sb.WriteString(y.String())
sb.WriteString(", ")
sb.WriteString(t.String())
return id, sb.String(), nil
} }
// ChangeCharOverlay 更改附加库的一项 // ChangeCharOverlay 更改附加库的一项
func (c *Coder) ChangeCharOverlay(oldw, oldr, oldf, neww, newr, newf string) error { func (c *Coder) ChangeCharOverlay(oldw, oldr, oldf, neww, newr, newf string) (int64, string, error) {
s, y, t, rw, rr, err := 拆音识字(oldw, oldr, 去调(oldf), oldf) s, y, t, rw, rr, err := 拆音识字(oldw, oldr, 去调(oldf), oldf)
if err != nil { if err != nil {
return err return 0, "", err
} }
newp := 去调(newf) newp := 去调(newf)
ns, ny, nt, nrw, nrr, err := 拆音识字(neww, newr, newp, newf) ns, ny, nt, nrw, nrr, err := 拆音识字(neww, newr, newp, newf)
if err != nil { if err != nil {
return err return 0, "", err
} }
q := "WHERE ID=" + strconv.FormatInt(字表ID(rw, s, y, t), 10) q := "WHERE ID=" + strconv.FormatInt(字表ID(rw, s, y, t), 10)
x := 字表{} x := 字表{}
@@ -265,16 +292,16 @@ func (c *Coder) ChangeCharOverlay(oldw, oldr, oldf, neww, newr, newf string) err
err = c.db.Find(附字表名, &x, q) err = c.db.Find(附字表名, &x, q)
c.mu.RUnlock() c.mu.RUnlock()
if err != nil { if err != nil {
return err return 0, "", err
} }
if x.R != rr { if x.R != rr {
return errors.New("提供的旧部首 '" + string(rr) + "' 与记载的 '" + string(x.R) + "' 不符") return 0, "", errors.New("提供的旧部首 '" + string(rr) + "' 与记载的 '" + string(x.R) + "' 不符")
} }
c.mu.Lock() c.mu.Lock()
err = c.db.Del(附字表名, q) err = c.db.Del(附字表名, q)
c.mu.Unlock() c.mu.Unlock()
if err != nil { if err != nil {
return err return 0, "", err
} }
return c.addcharoverlay(neww, newp, newf, ns, ny, nt, nrw, nrr) return c.addcharoverlay(neww, newp, newf, ns, ny, nt, nrw, nrr)
} }

View File

@@ -32,6 +32,14 @@ func TestEncode(t *testing.T) {
if len(lst) != 2 && lst[0] != 2 && lst[1] != 2 { if len(lst) != 2 && lst[0] != 2 && lst[1] != 2 {
t.Fail() t.Fail()
} }
es, lst, err = c.Encode(false, "的")
if err != nil {
t.Fatal(err)
}
t.Log(es.String(), lst)
if es.String() != "的🈳🈳🈳" {
t.Fatal("got", es.String())
}
} }
func TestDecode(t *testing.T) { func TestDecode(t *testing.T) {
@@ -66,4 +74,27 @@ func TestDecode(t *testing.T) {
if ds != "[你|儗]好,世[界|畍][指|抧|扺]定多音字:[銀|银]行行。" { if ds != "[你|儗]好,世[界|畍][指|抧|扺]定多音字:[銀|银]行行。" {
t.Fatal("got", ds) t.Fatal("got", ds)
} }
es, lst, err = c.Encode(false, "好啊")
if err != nil {
t.Fatal(err)
}
t.Log(es.String(), lst)
ds, err = c.Decode(es, false)
if err != nil {
t.Fatal(err)
}
t.Log(ds)
if ds != "好啊" {
t.Fatal("got", ds)
}
es = EmoziString("🌹😺‎🐴‫👩") // nolint: go-staticcheck
t.Log(es.String())
ds, err = c.Decode(es, false)
if err != nil {
t.Fatal(err)
}
t.Log(ds)
if ds != "好" {
t.Fatal("got", ds)
}
} }

11
data.go
View File

@@ -37,6 +37,17 @@ type 字表 struct {
F string F string
} }
// CharGlobalID 计算全局唯一字表ID
func CharGlobalID(w rune, f string) (int64, error) {
p := 去调(f)
s, y, err := 拆音(p)
if err != nil {
return 0, err
}
t := 识调(f)
return 字表ID(w, s, y, t), nil
}
func 字表ID(w rune, s 声母枚举, y 韵母枚举, t 声调枚举) int64 { func 字表ID(w rune, s 声母枚举, y 韵母枚举, t 声调枚举) int64 {
return int64((uint64(w) << 32) | (uint64(s) << 16) | (uint64(y) << 8) | (uint64(t))) return int64((uint64(w) << 32) | (uint64(s) << 16) | (uint64(y) << 8) | (uint64(t)))
} }

View File

@@ -6,12 +6,12 @@ import (
"strings" "strings"
) )
var = "🈳️" const = '🈳'
func 随机正查(m [][]string, isRandom bool, i uint8) string { func 随机正查(m [][]string, isRandom bool, i uint8) string {
lst := m[i] lst := m[i]
if len(lst) == 0 { if len(lst) == 0 {
return return string()
} }
if len(lst) == 1 || !isRandom { if len(lst) == 1 || !isRandom {
return lst[0] return lst[0]
@@ -42,7 +42,7 @@ func (c *Coder) 部首(r rune) string {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
err := c.db.Find(部首表名, x, "WHERE R="+strconv.Itoa(int(r))) err := c.db.Find(部首表名, x, "WHERE R="+strconv.Itoa(int(r)))
if err == nil && len(x.E) > 0 && x.E != { if err == nil && len(x.E) > 0 && x.E != string() {
c.部首缓存[r] = x.E c.部首缓存[r] = x.E
return x.E return x.E
} }
@@ -50,8 +50,8 @@ func (c *Coder) 部首(r rune) string {
c.部首缓存[r] = e c.部首缓存[r] = e
return e return e
} }
c.部首缓存[r] = c.部首缓存[r] = string()
return return string()
} }
func 二阶逆查[E ~uint8](lowm map[rune][]string, m map[string]E, s string) (enum E, n int) { func 二阶逆查[E ~uint8](lowm map[rune][]string, m map[string]E, s string) (enum E, n int) {
@@ -107,8 +107,9 @@ func (c *Coder) 逆部首(s string) (rs []rune, n int) {
if lim > 32 { if lim > 32 {
lim = 32 lim = 32
} }
// fmt.Println("逆部首: recv", s, "len", len(s), "lim", lim)
c.mu.RLock() c.mu.RLock()
for i := 1; i < lim; i++ { for i := 1; i <= lim; i++ {
l := c.逆部首缓存[s[:i]] l := c.逆部首缓存[s[:i]]
if len(l) > 0 { if len(l) > 0 {
rs = l rs = l
@@ -122,7 +123,7 @@ func (c *Coder) 逆部首(s string) (rs []rune, n int) {
x := &部首表{} x := &部首表{}
sb := strings.Builder{} sb := strings.Builder{}
sb.WriteString("WHERE ") sb.WriteString("WHERE ")
for i := 1; i < lim; i++ { for i := 1; i <= lim; i++ {
sb.WriteString("E='") sb.WriteString("E='")
sb.WriteString(s[:i]) sb.WriteString(s[:i])
sb.WriteString("' OR ") sb.WriteString("' OR ")
@@ -147,10 +148,11 @@ func (c *Coder) 逆部首(s string) (rs []rune, n int) {
c.逆部首缓存[e] = rs c.逆部首缓存[e] = rs
return return
} }
for i := 1; i < lim; i++ { for i := 1; i <= lim; i++ {
k := s[:i] k := s[:i]
innerrs, ok := 逆部首后备[k] innerrs, ok := 逆部首后备[k]
c.逆部首缓存[k] = innerrs c.逆部首缓存[k] = innerrs
// fmt.Println(k, innerrs)
if ok && len(innerrs) > 0 { if ok && len(innerrs) > 0 {
n = i n = i
rs = innerrs rs = innerrs

View File

@@ -331,6 +331,5 @@ func SplitPinyin(pf string) (sm, ym, sd string, err error) {
return return
} }
t := 识调(pf) t := 识调(pf)
println(s, y, t)
return s.String(), y.String(), t.String(), nil return s.String(), y.String(), t.String(), nil
} }

View File

@@ -2,7 +2,7 @@
package emozi package emozi
// 部首后备 内嵌的部首到颜文字的映射, 是第二优先查询顺位. 第一顺位是数据库的部首表. 第三位是回落到 🈳. // 部首后备 内嵌的部首到颜文字的映射, 是第二优先查询顺位. 第一顺位是数据库的部首表. 第三位是回落到 🈳.
var 部首后备 = map[rune]string{ var 部首后备 = map[rune]string{
'一': "1⃣", '一': "1⃣",
'丄': "☝️", '丄': "☝️",
@@ -40,508 +40,508 @@ var 部首后备 = map[rune]string{
'辵': "🚶", '辵': "🚶",
'彳': "🚦", '彳': "🚦",
'廴': "🚥", '廴': "🚥",
'㢟': , '㢟': string(),
'行': "⛕", '行': "⛕",
'齒': , '齒': string(),
'牙': , '牙': string(),
'足': , '足': string(),
'疋': , '疋': string(),
'品': , '品': string(),
'龠': , '龠': string(),
'冊': , '冊': string(),
'㗊': , '㗊': string(),
'舌': "👅", '舌': "👅",
'干': , '干': string(),
'𧮫': , '𧮫': string(),
'只': , '只': string(),
'㕯': , '㕯': string(),
'句': , '句': string(),
'丩': , '丩': string(),
'古': "🏺", '古': "🏺",
'十': "🔟", '十': "🔟",
'卅': "🌍", '卅': "🌍",
'言': "💬", '言': "💬",
'田': "👨‍🌾", '田': "👨‍🌾",
'誩': , '誩': string(),
'音': "🎵", '音': "🎵",
'䇂': , '䇂': string(),
'丵': , '丵': string(),
'菐': , '菐': string(),
'𠬞': , '𠬞': string(),
'𠬜': , '𠬜': string(),
'共': , '共': string(),
'異': , '異': string(),
'舁': , '舁': string(),
'𦥑': , '𦥑': string(),
'䢅': , '䢅': string(),
'爨': , '爨': string(),
'革': , '革': string(),
'鬲': , '鬲': string(),
'䰜': , '䰜': string(),
'爪': "🤏", '爪': "🤏",
'丮': , '丮': string(),
'鬥': "👊", '鬥': "👊",
'又': , '又': string(),
'𠂇': , '𠂇': string(),
'史': , '史': string(),
'支': , '支': string(),
'𦘒': , '𦘒': string(),
'聿': "✍", '聿': "✍",
'畫': "🎨", '畫': "🎨",
'隶': , '隶': string(),
'臤': , '臤': string(),
'臣': , '臣': string(),
'殳': , '殳': string(),
'殺': "🪚", '殺': "🪚",
'𠘧': , '𠘧': string(),
'寸': , '寸': string(),
'皮': , '皮': string(),
'㼱': , '㼱': string(),
'攴': , '攴': string(),
'女': "👩", '女': "👩",
'教': , '教': string(),
'卜': "🔮", '卜': "🔮",
'用': , '用': string(),
'爻': , '爻': string(),
'㸚': , '㸚': string(),
'𡕥': , '𡕥': string(),
'目': "👁️", '目': "👁️",
'䀠': "👀", '䀠': "👀",
'眉': "🤨", '眉': "🤨",
'盾': , '盾': string(),
'自': "👃", '自': "👃",
'𪞶': , '𪞶': string(),
'鼻': "👃", '鼻': "👃",
'皕': , '皕': string(),
'習': , '習': string(),
'羽': "🪶", '羽': "🪶",
'隹': "🐦", '隹': "🐦",
'奞': , '奞': string(),
'雈': , '雈': string(),
'𦫳': , '𦫳': string(),
'𥄕': , '𥄕': string(),
'羊': "🐑", '羊': "🐑",
'羴': , '羴': string(),
'瞿': , '瞿': string(),
'雔': , '雔': string(),
'雥': , '雥': string(),
'鳥': "🦢", '鳥': "🦢",
'烏': "🐦‍⬛", '烏': "🐦‍⬛",
'𠦒': , '𠦒': string(),
'冓': , '冓': string(),
'幺': , '幺': string(),
'𢆶': , '𢆶': string(),
'叀': , '叀': string(),
'玄': , '玄': string(),
'予': , '予': string(),
'放': , '放': string(),
'𠬪': , '𠬪': string(),
'𣦼': , '𣦼': string(),
'歺': , '歺': string(),
'死': , '死': string(),
'冎': , '冎': string(),
'骨': , '骨': string(),
'肉': , '肉': string(),
'筋': , '筋': string(),
'刀': "🔪", '刀': "🔪",
'刃': "🔪", '刃': "🔪",
'㓞': , '㓞': string(),
'丯': , '丯': string(),
'耒': , '耒': string(),
'角': "🥐", '角': "🥐",
'竹': "🎋", '竹': "🎋",
'箕': , '箕': string(),
'丌': , '丌': string(),
'左': "👈", '左': "👈",
'工': , '工': string(),
'㠭': , '㠭': string(),
'巫': , '巫': string(),
'甘': , '甘': string(),
'曰': , '曰': string(),
'乃': , '乃': string(),
'丂': , '丂': string(),
'可': , '可': string(),
'兮': , '兮': string(),
'号': , '号': string(),
'亏': , '亏': string(),
'旨': , '旨': string(),
'喜': , '喜': string(),
'壴': , '壴': string(),
'鼓': , '鼓': string(),
'豈': , '豈': string(),
'豆': , '豆': string(),
'豊': , '豊': string(),
'豐': , '豐': string(),
'䖒': , '䖒': string(),
'虍': , '虍': string(),
'虎': , '虎': string(),
'虤': , '虤': string(),
'皿': , '皿': string(),
'𠙴': , '𠙴': string(),
'去': , '去': string(),
'血': , '血': string(),
'': , '': string(),
'丹': , '丹': string(),
'青': , '青': string(),
'井': , '井': string(),
'皀': , '皀': string(),
'鬯': , '鬯': string(),
'食': , '食': string(),
'亼': , '亼': string(),
'會': , '會': string(),
'倉': , '倉': string(),
'入': , '入': string(),
'缶': , '缶': string(),
'矢': , '矢': string(),
'高': , '高': string(),
'冂': , '冂': string(),
'𩫖': , '𩫖': string(),
'京': , '京': string(),
'亯': , '亯': string(),
'㫗': , '㫗': string(),
'畗': , '畗': string(),
'㐭': , '㐭': string(),
'嗇': , '嗇': string(),
'來': , '來': string(),
'麥': , '麥': string(),
'夊': , '夊': string(),
'舛': , '舛': string(),
'舜': , '舜': string(),
'韋': , '韋': string(),
'弟': , '弟': string(),
'夂': , '夂': string(),
'久': , '久': string(),
'桀': , '桀': string(),
'木': , '木': string(),
'東': , '東': string(),
'林': , '林': string(),
'才': , '才': string(),
'叒': , '叒': string(),
'之': , '之': string(),
'帀': , '帀': string(),
'出': , '出': string(),
'𣎵': , '𣎵': string(),
'生': , '生': string(),
'乇': , '乇': string(),
'𠂹': , '𠂹': string(),
'𠌶': , '𠌶': string(),
'華': , '華': string(),
'𥝌': , '𥝌': string(),
'稽': , '稽': string(),
'巢': , '巢': string(),
'桼': , '桼': string(),
'束': , '束': string(),
'㯻': , '㯻': string(),
'囗': , '囗': string(),
'員': , '員': string(),
'貝': , '貝': string(),
'邑': , '邑': string(),
'𨛜': , '𨛜': string(),
'日': , '日': string(),
'旦': , '旦': string(),
'倝': , '倝': string(),
'㫃': , '㫃': string(),
'冥': , '冥': string(),
'晶': , '晶': string(),
'月': , '月': string(),
'有': , '有': string(),
'朙': , '朙': string(),
'囧': , '囧': string(),
'夕': "🌇", '夕': "🌇",
'多': "🪩", '多': "🪩",
'毌': , '毌': string(),
'𢎘': , '𢎘': string(),
'𣐺': , '𣐺': string(),
'𠧪': , '𠧪': string(),
'齊': , '齊': string(),
'朿': , '朿': string(),
'片': , '片': string(),
'鼎': , '鼎': string(),
'克': , '克': string(),
'彔': , '彔': string(),
'禾': , '禾': string(),
'秝': , '秝': string(),
'黍': , '黍': string(),
'香': , '香': string(),
'米': , '米': string(),
'毇': , '毇': string(),
'臼': , '臼': string(),
'凶': , '凶': string(),
'朩': , '朩': string(),
'𣏟': , '𣏟': string(),
'麻': , '麻': string(),
'尗': , '尗': string(),
'耑': , '耑': string(),
'韭': , '韭': string(),
'瓜': , '瓜': string(),
'瓠': , '瓠': string(),
'宀': "🏠", '宀': "🏠",
'宮': "🏛", '宮': "🏛",
'呂': "🩻", '呂': "🩻",
'穴': "🕳️", '穴': "🕳️",
'㝱': , '㝱': string(),
'疒': "😷", '疒': "😷",
'冖': "🗃", '冖': "🗃",
'𠔼': , '𠔼': string(),
'冃': , '冃': string(),
'㒳': , '㒳': string(),
'网': , '网': string(),
'襾': , '襾': string(),
'巾': "🧣", '巾': "🧣",
'巿': , '巿': string(),
'帛': , '帛': string(),
'白': "⚪", '白': "⚪",
'㡀': , '㡀': string(),
'黹': , '黹': string(),
'𠤎': , '𠤎': string(),
'匕': , '匕': string(),
'从': , '从': string(),
'比': , '比': string(),
'北': , '北': string(),
'丘': , '丘': string(),
'㐺': , '㐺': string(),
'𡈼': , '𡈼': string(),
'重': , '重': string(),
'臥': , '臥': string(),
'身': , '身': string(),
'㐆': , '㐆': string(),
'衣': , '衣': string(),
'裘': , '裘': string(),
'老': , '老': string(),
'毛': , '毛': string(),
'毳': , '毳': string(),
'尸': , '尸': string(),
'尺': , '尺': string(),
'尾': , '尾': string(),
'履': , '履': string(),
'舟': "🛶", '舟': "🛶",
'方': , '方': string(),
'儿': , '儿': string(),
'兄': , '兄': string(),
'兂': , '兂': string(),
'皃': , '皃': string(),
'𠑹': , '𠑹': string(),
'先': , '先': string(),
'禿': , '禿': string(),
'見': , '見': string(),
'覞': , '覞': string(),
'欠': , '欠': string(),
'㱃': , '㱃': string(),
'㳄': , '㳄': string(),
'旡': , '旡': string(),
'頁': , '頁': string(),
'𦣻': , '𦣻': string(),
'面': , '面': string(),
'丏': , '丏': string(),
'首': , '首': string(),
'𥄉': , '𥄉': string(),
'須': , '須': string(),
'彡': , '彡': string(),
'彣': , '彣': string(),
'文': , '文': string(),
'髟': , '髟': string(),
'后': , '后': string(),
'司': , '司': string(),
'卮': , '卮': string(),
'卩': , '卩': string(),
'印': , '印': string(),
'色': , '色': string(),
'𠨍': , '𠨍': string(),
'辟': , '辟': string(),
'勹': , '勹': string(),
'包': , '包': string(),
'茍': , '茍': string(),
'鬼': , '鬼': string(),
'甶': , '甶': string(),
'厶': , '厶': string(),
'嵬': , '嵬': string(),
'山': , '山': string(),
'屾': , '屾': string(),
'屵': , '屵': string(),
'广': , '广': string(),
'厂': , '厂': string(),
'丸': , '丸': string(),
'危': , '危': string(),
'石': , '石': string(),
'長': , '長': string(),
'勿': , '勿': string(),
'冄': , '冄': string(),
'而': , '而': string(),
'豕': , '豕': string(),
'㣇': , '㣇': string(),
'彑': , '彑': string(),
'豚': , '豚': string(),
'豸': , '豸': string(),
'𤉡': , '𤉡': string(),
'易': , '易': string(),
'象': , '象': string(),
'馬': , '馬': string(),
'𢊁': , '𢊁': string(),
'鹿': , '鹿': string(),
'麤': , '麤': string(),
'㲋': , '㲋': string(),
'兔': , '兔': string(),
'萈': , '萈': string(),
'犬': , '犬': string(),
'㹜': , '㹜': string(),
'鼠': , '鼠': string(),
'能': , '能': string(),
'熊': , '熊': string(),
'火': , '火': string(),
'炎': , '炎': string(),
'黑': , '黑': string(),
'囪': , '囪': string(),
'焱': , '焱': string(),
'炙': , '炙': string(),
'赤': , '赤': string(),
'大': , '大': string(),
'亦': , '亦': string(),
'夨': , '夨': string(),
'夭': , '夭': string(),
'交': , '交': string(),
'尣': , '尣': string(),
'壺': , '壺': string(),
'壹': , '壹': string(),
'㚔': , '㚔': string(),
'奢': , '奢': string(),
'亢': , '亢': string(),
'夲': , '夲': string(),
'夰': , '夰': string(),
'亣': , '亣': string(),
'夫': , '夫': string(),
'立': , '立': string(),
'竝': , '竝': string(),
'囟': , '囟': string(),
'思': , '思': string(),
'心': , '心': string(),
'惢': , '惢': string(),
'水': , '水': string(),
'沝': , '沝': string(),
'瀕': , '瀕': string(),
'𡿨': , '𡿨': string(),
'巜': , '巜': string(),
'川': , '川': string(),
'泉': , '泉': string(),
'灥': , '灥': string(),
'永': , '永': string(),
'𠂢': , '𠂢': string(),
'谷': , '谷': string(),
'仌': , '仌': string(),
'雨': , '雨': string(),
'雲': , '雲': string(),
'魚': , '魚': string(),
'𩺰': , '𩺰': string(),
'燕': , '燕': string(),
'龍': , '龍': string(),
'飛': , '飛': string(),
'非': , '非': string(),
'卂': , '卂': string(),
'𠃉': , '𠃉': string(),
'不': , '不': string(),
'至': , '至': string(),
'西': , '西': string(),
'鹵': , '鹵': string(),
'鹽': , '鹽': string(),
'戶': , '戶': string(),
'門': , '門': string(),
'耳': , '耳': string(),
'𦣞': , '𦣞': string(),
'手': "✋", '手': "✋",
'𠦬': , '𠦬': string(),
'毋': , '毋': string(),
'民': , '民': string(),
'丿': , '丿': string(),
'𠂆': , '𠂆': string(),
'乁': , '乁': string(),
'氏': , '氏': string(),
'氐': , '氐': string(),
'戈': , '戈': string(),
'戉': , '戉': string(),
'我': , '我': string(),
'亅': , '亅': string(),
'珡': , '珡': string(),
'𠃊': , '𠃊': string(),
'亾': , '亾': string(),
'匸': , '匸': string(),
'匚': , '匚': string(),
'曲': , '曲': string(),
'甾': , '甾': string(),
'瓦': , '瓦': string(),
'弓': , '弓': string(),
'弜': , '弜': string(),
'弦': , '弦': string(),
'系': , '系': string(),
'糸': , '糸': string(),
'素': , '素': string(),
'絲': , '絲': string(),
'率': , '率': string(),
'虫': , '虫': string(),
'䖵': , '䖵': string(),
'蟲': , '蟲': string(),
'風': , '風': string(),
'它': , '它': string(),
'龜': , '龜': string(),
'黽': , '黽': string(),
'卵': , '卵': string(),
'二': , '二': string(),
'土': , '土': string(),
'垚': , '垚': string(),
'堇': , '堇': string(),
'里': , '里': string(),
'畕': , '畕': string(),
'黃': , '黃': string(),
'男': , '男': string(),
'力': , '力': string(),
'劦': , '劦': string(),
'金': "💰", '金': "💰",
'幵': , '幵': string(),
'勺': , '勺': string(),
'几': , '几': string(),
'且': , '且': string(),
'斤': , '斤': string(),
'斗': , '斗': string(),
'矛': , '矛': string(),
'車': , '車': string(),
'𠂤': , '𠂤': string(),
'𨸏': , '𨸏': string(),
'𨺅': , '𨺅': string(),
'厽': , '厽': string(),
'四': , '四': string(),
'宁': , '宁': string(),
'叕': , '叕': string(),
'亞': , '亞': string(),
'五': , '五': string(),
'六': , '六': string(),
'七': , '七': string(),
'九': , '九': string(),
'禸': , '禸': string(),
'嘼': , '嘼': string(),
'甲': , '甲': string(),
'乙': , '乙': string(),
'丙': , '丙': string(),
'丁': , '丁': string(),
'戊': , '戊': string(),
'己': , '己': string(),
'巴': , '巴': string(),
'庚': , '庚': string(),
'辛': , '辛': string(),
'辡': , '辡': string(),
'壬': , '壬': string(),
'癸': , '癸': string(),
'子': "🚼", '子': "🚼",
'了': , '了': string(),
'孨': , '孨': string(),
'𠫓': , '𠫓': string(),
'丑': , '丑': string(),
'寅': , '寅': string(),
'戼': , '戼': string(),
'辰': , '辰': string(),
'巳': , '巳': string(),
'午': , '午': string(),
'未': , '未': string(),
'申': , '申': string(),
'酉': , '酉': string(),
'酋': , '酋': string(),
'戌': , '戌': string(),
'亥': , '亥': string(),
} }

View File

@@ -19,7 +19,11 @@ type EmoziString string
func WrapRawEmoziString(s string) EmoziString { func WrapRawEmoziString(s string) EmoziString {
rs := []rune(s) rs := []rune(s)
if len(rs) < 4 { if len(rs) < 4 {
return "" diff := 4 - len(rs)
for i := 0; i < diff; i++ {
rs = append(rs, )
}
s = string(rs)
} }
h := crc32.NewIEEE() h := crc32.NewIEEE()
h.Write(base14.StringToBytes(s)) h.Write(base14.StringToBytes(s))