emoji: add one-shot candidate search
This commit is contained in:
106
map/mkemoji
106
map/mkemoji
@@ -1,39 +1,71 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/env python3
|
||||
"""Write emoji.dict to stdout from a result-first UTF-8 TSV file."""
|
||||
|
||||
awk '
|
||||
BEGIN { FS = "\t" }
|
||||
/^$/ { next }
|
||||
{
|
||||
key = $1
|
||||
val = $2
|
||||
map[key] = val
|
||||
for(i = 1; i < length(key); i++){
|
||||
p = substr(key, 1, i)
|
||||
if(!(p in map))
|
||||
map[p] = p
|
||||
}
|
||||
}
|
||||
END {
|
||||
for(k in map)
|
||||
print k "\t" map[k]
|
||||
}
|
||||
' $1 | sort -k1,1 > emoji.map
|
||||
import sys
|
||||
import unicodedata
|
||||
from pathlib import Path
|
||||
|
||||
awk '
|
||||
BEGIN { FS = "\t" }
|
||||
/^$/ { next }
|
||||
{
|
||||
key = $1
|
||||
val = $2
|
||||
for(i = 1; i <= length(key); i++){
|
||||
p = substr(key, 1, i)
|
||||
dict[p] = dict[p] " " val
|
||||
}
|
||||
}
|
||||
END {
|
||||
for(p in dict){
|
||||
sub(/^ /, "", dict[p])
|
||||
print p "\t" dict[p]
|
||||
}
|
||||
}
|
||||
' $1 | sort -k1,1 > emoji.dict
|
||||
|
||||
SOURCE = Path(__file__).with_name("emoji.src")
|
||||
|
||||
|
||||
def fold(s):
|
||||
s = "".join(chr(ord(c) + 32) if "A" <= c <= "Z" else c for c in s)
|
||||
return unicodedata.normalize("NFC", s)
|
||||
|
||||
|
||||
def read(path):
|
||||
entries = []
|
||||
with path.open(encoding="utf-8") as src:
|
||||
for lineno, raw in enumerate(src, 1):
|
||||
line = raw.rstrip("\r\n")
|
||||
if not line.strip() or line.lstrip().startswith("#"):
|
||||
continue
|
||||
fields = line.split("\t")
|
||||
if len(fields) < 2:
|
||||
raise ValueError(f"{path}:{lineno}: need a result and an alias")
|
||||
result = unicodedata.normalize("NFC", fields[0])
|
||||
if not result or any(c.isspace() for c in result):
|
||||
raise ValueError(f"{path}:{lineno}: bad result")
|
||||
for field in fields[1:]:
|
||||
alias = fold(field)
|
||||
if not alias or alias != alias.strip():
|
||||
raise ValueError(f"{path}:{lineno}: bad alias")
|
||||
entries.append((result, alias))
|
||||
return entries
|
||||
|
||||
|
||||
def add(table, key, result):
|
||||
values = table.setdefault(key, [])
|
||||
if result not in values:
|
||||
values.append(result)
|
||||
|
||||
|
||||
def build(entries):
|
||||
exact = {}
|
||||
prefix = {}
|
||||
for result, alias in entries:
|
||||
for n in range(1, len(alias) + 1):
|
||||
add(exact if n == len(alias) else prefix, alias[:n], result)
|
||||
for key in sorted(exact.keys() | prefix.keys()):
|
||||
values = exact.get(key, []) + prefix.get(key, [])
|
||||
values = list(dict.fromkeys(values))
|
||||
yield f"{key}\t{' '.join(values)}"
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) > 2:
|
||||
print(f"usage: {sys.argv[0]} [emoji.src]", file=sys.stderr)
|
||||
return 2
|
||||
path = Path(sys.argv[1]) if len(sys.argv) == 2 else SOURCE
|
||||
try:
|
||||
for line in build(read(path)):
|
||||
print(line)
|
||||
except (OSError, UnicodeError, ValueError) as error:
|
||||
print(error, file=sys.stderr)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
||||
Reference in New Issue
Block a user