SquirrelConfig/others/script/rime/emoji.go

218 lines
5.0 KiB
Go
Raw Permalink Normal View History

2024-03-20 03:18:06 +00:00
package rime
import (
"bufio"
"fmt"
mapset "github.com/deckarep/golang-set/v2"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"time"
"unicode/utf8"
)
// CheckAndGenerateEmoji
// 检查 emoji-map.txt 是否合法,检查中文映射是否存在于 base 词库中
// 生成 Rime 格式的 emoji.txt
// 检查 other.txt 中文映射是否存在于 base 词库中
func CheckAndGenerateEmoji() {
// 控制台输出
defer printlnTimeCost("检查、更新 Emoji", time.Now())
checkEmoji()
generateEmoji()
checkOthersTXT()
}
// 检查 emoji-map.txt 是否合法,检查中文映射是否存在于 base 词库中
func checkEmoji() {
// 打开文件
file, err := os.Open(EmojiMapPath)
if err != nil {
log.Fatalln(err)
}
defer file.Close()
// 将 Emoji 加入一个 set为检测差集做准备
emojiSet := mapset.NewSet[string]()
sc := bufio.NewScanner(file)
for sc.Scan() {
line := sc.Text()
// 过滤空行
if line == "" {
continue
}
// 过滤注释
if strings.Contains(line, "#") {
continue
}
// 检查:是否包含 Tab
if strings.Contains(line, "\t") {
fmt.Println("❌ contains Tab", line)
continue
}
// 检查:开头结尾无效的空格
if strings.HasPrefix(line, " ") || strings.HasSuffix(line, " ") {
fmt.Println("❌ unexpected space", line)
continue
}
// 开始分割
parts := strings.Split(line, " ")
if len(parts) < 2 {
fmt.Println("❌ invalid line", line)
continue
}
// 加入 emojiSet顺便用一个 tempSet 查重
tempSet := mapset.NewSet[string]()
for _, text := range parts[1:] {
emojiSet.Add(text)
if tempSet.Contains(text) {
fmt.Println("❌ duplicate mapping", text)
} else {
tempSet.Add(text)
}
}
}
if err := sc.Err(); err != nil {
log.Fatalln(err)
}
// 检查: emoji-map.txt 中的映射是否存在于 base 词库中,有差集即不存在
for _, text := range emojiSet.Difference(BaseSet).ToSlice() {
// 不检查英文
if match, _ := regexp.MatchString(`[a-zA-Z]`, text); match {
continue
}
// 不检查 1 个字的
if utf8.RuneCountInString(text) == 1 {
continue
}
fmt.Println("❌ Emoji 与 base 的差集:", text)
}
}
// 从 emoji-map.txt 生成或更新 emoji.txt
func generateEmoji() {
// 打开文件
file, err := os.Open(EmojiMapPath)
if err != nil {
log.Fatalln(err)
}
defer file.Close()
// 模拟有序字典
OmKeys := make([]string, 0)
OmMap := make(map[string][]string)
// 将映射读取到字典里
sc := bufio.NewScanner(file)
for sc.Scan() {
line := sc.Text()
if strings.HasPrefix(line, "#") && !strings.Contains(line, "井号") { // 井号的 Emoji 被判断为以 # 开头了。。。
continue
}
parts := strings.Split(line, " ")
for _, text := range parts[1:] {
if !contains(OmKeys, text) {
OmKeys = append(OmKeys, text)
}
OmMap[text] = append(OmMap[text], parts[0])
}
}
if err := sc.Err(); err != nil {
log.Fatalln(err)
}
// 写入 emoji.txt
file, err = os.OpenFile(EmojiPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
log.Fatalln(err)
}
defer file.Close()
for _, key := range OmKeys {
line := key + "\t" + key + " " + strings.Join(OmMap[key], " ") + "\n"
_, err := file.WriteString(line)
if err != nil {
log.Fatalln(err)
}
}
if err := file.Sync(); err != nil {
log.Fatalln(err)
}
}
// 检查 others.txt 里的中文映射是否存在于 base 词库中
func checkOthersTXT() {
// 打开文件
file, err := os.Open(filepath.Join(RimeDir, "opencc/others.txt"))
if err != nil {
log.Fatalln(err)
}
defer file.Close()
// 将 Emoji 加入一个 set为检测差集做准备
set := mapset.NewSet[string]()
sc := bufio.NewScanner(file)
for sc.Scan() {
line := sc.Text()
// 不能有空行
if line == "" {
fmt.Println("❌ empty line")
}
// 过滤注释
if strings.HasPrefix(line, "----------") {
continue
}
text := strings.Split(line, "\t")[0]
if set.Contains(text) {
fmt.Println("❌ duplicate key", text)
} else {
set.Add(text)
}
}
// base+cn_dicts/others.dict.yaml
othersDictYamlSet := mapset.NewSet[string]()
othersDictYaml, err := os.Open(filepath.Join(RimeDir, "cn_dicts/others.dict.yaml"))
if err != nil {
log.Fatalln(err)
}
defer othersDictYaml.Close()
sc = bufio.NewScanner(othersDictYaml)
isMark := false
for sc.Scan() {
line := sc.Text()
if !isMark {
if strings.HasPrefix(line, "##### 叠字") {
isMark = true
}
continue
}
if strings.HasPrefix(line, "#") {
continue
}
text := strings.Split(line, "\t")[0]
othersDictYamlSet.Add(text)
}
// 检查: emoji-map.txt 中的映射是否存在于 base+cn_dicts/others.dict.yaml 词库中,有差集即不存在
dictSet := BaseSet.Union(othersDictYamlSet)
for _, text := range set.Difference(dictSet).ToSlice() {
// 不检查英文
if match, _ := regexp.MatchString(`[a-zA-Z]`, text); match {
continue
}
// 不检查 1 个字的
if utf8.RuneCountInString(text) == 1 {
continue
}
fmt.Println("❌ others.txt 与 base 的差集:", text)
}
}