From 7e641e891ef3a285c30f4a42f5f5acd9d6f181db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 15 Feb 2024 17:14:56 +0900 Subject: [PATCH] feat: add cmd --- README.md | 58 +- cmd/main.go | 94 +++ {preprocess => codegen/preprocess}/main.go | 0 codegen/radical/main.go | 4 +- coder.go | 55 +- coder_test.go | 31 + data.go | 11 + lookup.go | 18 +- pinyin.go | 1 - radical.go | 922 ++++++++++----------- string.go | 6 +- 11 files changed, 712 insertions(+), 488 deletions(-) create mode 100644 cmd/main.go rename {preprocess => codegen/preprocess}/main.go (100%) diff --git a/README.md b/README.md index 537759a..79b6feb 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,63 @@ -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 🥛⁦👔⁢🐴👤🐵🐈‍⬛🐎👩,🪸☀️😨🌍🐓✌️😨👨‍🌾!👖🔐🍉👁️😭🔐🍉👁️🪔🌀🍉🪩💊🎵🍉🎵👈🌅😨🚼:🐅👍🧗‍♂️⛕。 +解码结果: [你|儗]好,世[界|畍]!看看多音字:行。 +``` ## 实用工具 ### 拼音识别拆分 diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..dd33e0f --- /dev/null +++ b/cmd/main.go @@ -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) + } +} diff --git a/preprocess/main.go b/codegen/preprocess/main.go similarity index 100% rename from preprocess/main.go rename to codegen/preprocess/main.go diff --git a/codegen/radical/main.go b/codegen/radical/main.go index 3876063..21fb5d9 100644 --- a/codegen/radical/main.go +++ b/codegen/radical/main.go @@ -13,9 +13,9 @@ const head = `// Code generated by codegen/radical. 已经经过修改, 不要 package emozi -// 部首后备 内嵌的部首到颜文字的映射, 是第二优先查询顺位. 第一顺位是数据库的部首表. 第三位是回落到 🈳️. +// 部首后备 内嵌的部首到颜文字的映射, 是第二优先查询顺位. 第一顺位是数据库的部首表. 第三位是回落到 🈳. var 部首后备 = map[rune]string{ {{range .}} - '{{.R}}': 空,{{end}} + '{{.R}}': string(空),{{end}} } ` diff --git a/coder.go b/coder.go index 0a00058..cf46565 100644 --- a/coder.go +++ b/coder.go @@ -68,20 +68,34 @@ func (c *Coder) Close() error { // Encode 从汉字序列生成 EmoziString 返回 EmoziString 多音字选择数列表 func (c *Coder) Encode(enableRandom bool, s string, selections ...int) (EmoziString, []int, error) { sb := strings.Builder{} - lstbuf := make([]字表, 0, len(s)/2) + buflen := len(s) / 2 + if buflen < 4 { + buflen = 4 + } + lstbuf := make([]字表, 0, buflen) var lst []字表 - write := func(x *字表) { + var write func(x *字表) + randomwrite := func(x *字表) { sb.WriteString(c.声母(enableRandom, x.S)) sb.WriteString(c.韵母(enableRandom, x.Y)) sb.WriteString(c.声调(enableRandom, x.T)) 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 多音字数表 := []int{} var err error for _, ch := range s { // nolint: go-staticcheck lst, lstbuf, err = c.查字(ch, lstbuf) if err != nil || len(lst) == 0 { + //fmt.Println("写入未知字:", string(ch), ch) sb.WriteRune(ch) continue } @@ -121,6 +135,7 @@ func (c *Coder) Decode(es EmoziString, forcedecode bool) (string, error) { } else { s = es.String() } + // fmt.Println(len(s), s) lstbuf := make([]字表, 0, len(s)/8) read := func(s string) (string, int) { sum := 0 @@ -129,21 +144,25 @@ func (c *Coder) Decode(es EmoziString, forcedecode bool) (string, error) { return "", 0 } sum += n + // fmt.Println(n, sm, s[0:sum]) ym, n := c.逆韵母(s[sum:]) if n == 0 { return "", 0 } sum += n + // fmt.Println(n, ym, s[sum-n:sum]) t, n := c.逆声调(s[sum:]) if n == 0 { return "", 0 } sum += n + // fmt.Println(n, t, s[sum-n:sum]) rs, n := c.逆部首(s[sum:]) if n == 0 { return "", 0 } sum += n + // fmt.Println(n, rs, s[sum-n:sum]) var possibles []rune var err error if len(rs) == 0 { // 意符为空 @@ -223,41 +242,49 @@ func (c *Coder) AddChar(w, r, p, f string) error { // AddCharOverlay 向附加库添加一个新字, 覆盖在主库之上 // // 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 == "" { p = 去调(f) } s, y, t, rw, rr, err := 拆音识字(w, r, p, f) if err != nil { - return err + return 0, "", err } 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() err := c.db.InsertUnique(附字表名, &字表{ - ID: 字表ID(rw, s, y, t), + ID: id, W: rw, S: s, Y: y, T: t, R: rr, P: p, F: f, }) c.mu.Unlock() 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 更改附加库的一项 -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) if err != nil { - return err + return 0, "", err } newp := 去调(newf) ns, ny, nt, nrw, nrr, err := 拆音识字(neww, newr, newp, newf) if err != nil { - return err + return 0, "", err } q := "WHERE ID=" + strconv.FormatInt(字表ID(rw, s, y, t), 10) x := 字表{} @@ -265,16 +292,16 @@ func (c *Coder) ChangeCharOverlay(oldw, oldr, oldf, neww, newr, newf string) err err = c.db.Find(附字表名, &x, q) c.mu.RUnlock() if err != nil { - return err + return 0, "", err } if x.R != rr { - return errors.New("提供的旧部首 '" + string(rr) + "' 与记载的 '" + string(x.R) + "' 不符") + return 0, "", errors.New("提供的旧部首 '" + string(rr) + "' 与记载的 '" + string(x.R) + "' 不符") } c.mu.Lock() err = c.db.Del(附字表名, q) c.mu.Unlock() if err != nil { - return err + return 0, "", err } return c.addcharoverlay(neww, newp, newf, ns, ny, nt, nrw, nrr) } diff --git a/coder_test.go b/coder_test.go index 2a9a0ad..bce861f 100644 --- a/coder_test.go +++ b/coder_test.go @@ -32,6 +32,14 @@ func TestEncode(t *testing.T) { if len(lst) != 2 && lst[0] != 2 && lst[1] != 2 { 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) { @@ -66,4 +74,27 @@ func TestDecode(t *testing.T) { if 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) + } } diff --git a/data.go b/data.go index a311fed..195f0ae 100644 --- a/data.go +++ b/data.go @@ -37,6 +37,17 @@ type 字表 struct { 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 { return int64((uint64(w) << 32) | (uint64(s) << 16) | (uint64(y) << 8) | (uint64(t))) } diff --git a/lookup.go b/lookup.go index 3207bbd..b9f3542 100644 --- a/lookup.go +++ b/lookup.go @@ -6,12 +6,12 @@ import ( "strings" ) -var 空 = "🈳️" +const 空 = '🈳' func 随机正查(m [][]string, isRandom bool, i uint8) string { lst := m[i] if len(lst) == 0 { - return 空 + return string(空) } if len(lst) == 1 || !isRandom { return lst[0] @@ -42,7 +42,7 @@ func (c *Coder) 部首(r rune) string { c.mu.Lock() defer c.mu.Unlock() 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 return x.E } @@ -50,8 +50,8 @@ func (c *Coder) 部首(r rune) string { c.部首缓存[r] = e return e } - c.部首缓存[r] = 空 - return 空 + c.部首缓存[r] = string(空) + return string(空) } 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 { lim = 32 } + // fmt.Println("逆部首: recv", s, "len", len(s), "lim", lim) c.mu.RLock() - for i := 1; i < lim; i++ { + for i := 1; i <= lim; i++ { l := c.逆部首缓存[s[:i]] if len(l) > 0 { rs = l @@ -122,7 +123,7 @@ func (c *Coder) 逆部首(s string) (rs []rune, n int) { x := &部首表{} sb := strings.Builder{} sb.WriteString("WHERE ") - for i := 1; i < lim; i++ { + for i := 1; i <= lim; i++ { sb.WriteString("E='") sb.WriteString(s[:i]) sb.WriteString("' OR ") @@ -147,10 +148,11 @@ func (c *Coder) 逆部首(s string) (rs []rune, n int) { c.逆部首缓存[e] = rs return } - for i := 1; i < lim; i++ { + for i := 1; i <= lim; i++ { k := s[:i] innerrs, ok := 逆部首后备[k] c.逆部首缓存[k] = innerrs + // fmt.Println(k, innerrs) if ok && len(innerrs) > 0 { n = i rs = innerrs diff --git a/pinyin.go b/pinyin.go index d9b28a3..20d12f5 100644 --- a/pinyin.go +++ b/pinyin.go @@ -331,6 +331,5 @@ func SplitPinyin(pf string) (sm, ym, sd string, err error) { return } t := 识调(pf) - println(s, y, t) return s.String(), y.String(), t.String(), nil } diff --git a/radical.go b/radical.go index b19b1b1..511b375 100644 --- a/radical.go +++ b/radical.go @@ -2,7 +2,7 @@ package emozi -// 部首后备 内嵌的部首到颜文字的映射, 是第二优先查询顺位. 第一顺位是数据库的部首表. 第三位是回落到 🈳️. +// 部首后备 内嵌的部首到颜文字的映射, 是第二优先查询顺位. 第一顺位是数据库的部首表. 第三位是回落到 🈳. var 部首后备 = map[rune]string{ '一': "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(空), } diff --git a/string.go b/string.go index 3c711d9..194a271 100644 --- a/string.go +++ b/string.go @@ -19,7 +19,11 @@ type EmoziString string func WrapRawEmoziString(s string) EmoziString { rs := []rune(s) 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.Write(base14.StringToBytes(s))