-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmojimoji.go
113 lines (102 loc) · 2.53 KB
/
mojimoji.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Package mojimoji is a port of mojimoji package to Go.
// Original: https://github.com/studio-ousia/mojimoji
package gomojimoji
import (
"strings"
"unicode/utf8"
)
type options struct {
ascii bool
digit bool
kana bool
}
func (oo *options) apply(opt ...Option) *options {
for _, fn := range opt {
fn(oo)
}
return oo
}
// ASCII enables or disables conversion of ASCII runes (A-Za-z).
func ASCII(enable bool) Option {
return func(o *options) {
o.ascii = enable
}
}
// Digits enables or disables conversion of digit runes (0-9).
func Digits(enable bool) Option {
return func(o *options) {
o.digit = enable
}
}
// Kana enables or disables conversion of Kana runes.
func Kana(enable bool) Option {
return func(o *options) {
o.kana = enable
}
}
// Option is the option function signature.
type Option func(*options)
// ZenToHan converts text to half-width runes. By default all runes are
// converted, optionally caller can switch off rune-set by passing [Option].
func ZenToHan(text string, opt ...Option) string {
var options = options{
ascii: true,
digit: true,
kana: true,
}
options.apply(opt...)
var buf strings.Builder
for _, c := range text {
if r, ok := tabASCIIzh[c]; options.ascii && ok {
buf.WriteRune(r)
} else if r, ok := tabKANAzh[c]; options.kana && ok {
buf.WriteRune(r)
} else if r, ok := tabDIGITzh[c]; options.digit && ok {
buf.WriteRune(r)
} else if r, ok := tabKANATENzh[c]; options.kana && ok {
buf.WriteRune(r)
buf.WriteRune('゙')
} else if r, ok := tabKANAMARUzh[c]; options.kana && ok {
buf.WriteRune(r)
buf.WriteRune('゚')
} else {
buf.WriteRune(c)
}
}
return buf.String()
}
// HanToZen converts text to full-width runes. By default all runes are
// converted, optionally caller can switch off rune-set by passing [Option].
func HanToZen(text string, opt ...Option) string {
var options = options{
ascii: true,
digit: true,
kana: true,
}
options.apply(opt...)
var buf = make([]rune, utf8.RuneCountInString(text))
var (
prev rune
pos int
)
for _, c := range text {
if r, ok := tabASCIIhz[c]; options.ascii && ok {
buf[pos] = r
} else if r, ok := tabDigitHz[c]; options.digit && ok {
buf[pos] = r
} else if r, ok := tabKanaTenHz[prev]; options.kana && c == '゙' && ok {
pos--
buf[pos] = r
} else if r, ok := tabKanaMaruHz[prev]; options.kana && c == '゚' && ok {
pos--
buf[pos] = r
} else if r, ok := tabKanaHz[c]; options.kana && ok {
buf[pos] = r
} else {
buf[pos] = c
}
prev = c
pos++
}
return string(buf[:pos])
}