Skip to content

Commit a79d76e

Browse files
feat: cC键计算器 (iDvel#904)
* feat(lua): calculator * fix(calc_translator): 修复若干逻辑错误和添加部分功能 - 修复了函数(英文)未输入完整时造成的 result 为 nil 的错误 - 修复了未写参数时,result 类型错误 - 修复了算式(express)为空时(以及用户错误设置了正则表达式时),意外进入生成候选的逻辑 - 添加:随机数函数添加 random 表达 - 添加:候选默认隐藏插件前缀(via cand.prefix),设置 calculator/show_prefix 可以显示 - 功能:该插件所有候选置顶(via cand.quality) - 功能:从 calculator/prefix 设定项获取前缀,而非自动获取,默认 `cC` * style(calc_translator.lua):format style, rename calc_translator --------- Co-authored-by: mirtlecn <mirtle.cn+github@outlook.com>
1 parent a37e5d0 commit a79d76e

10 files changed

+245
-14
lines changed

default.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ key_binder:
243243
- {accept: KP_8, send: 8, when: composing}
244244
- {accept: KP_9, send: 9, when: composing}
245245
- {accept: KP_Decimal, send: period, when: composing}
246+
# 将小键盘 + - * / 映射到主键盘,使计算器 如 1+2-3*4 可使用小键盘输入
247+
- {accept: KP_Multiply, send: asterisk, when: composing}
248+
- {accept: KP_Add, send: plus, when: composing}
249+
- {accept: KP_Subtract, send: minus, when: composing}
250+
- {accept: KP_Divide, send: slash, when: composing}
246251

247252

248253
# 按键速查

double_pinyin.schema.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ engine:
7979
- table_translator@radical_lookup # 部件拆字反查
8080
- lua_translator@unicode # Unicode
8181
- lua_translator@number_translator # 数字、金额大写
82+
- lua_translator@calc_translator # 计算器
8283
- lua_translator@force_gc # 暴力 GC
8384
filters:
8485
- lua_filter@corrector # 错音错字提示
@@ -285,12 +286,13 @@ radical_reverse_lookup:
285286
# 处理符合特定规则的输入码,如网址、反查
286287

287288
recognizer:
288-
import_preset: default # 从 default.yaml 继承通用的
289-
patterns: # 再增加方案专有的:
289+
import_preset: default # 从 default.yaml 继承通用的
290+
patterns: # 再增加方案专有的:
290291
punct: "^V([0-9]|10|[A-Za-z]+)$" # 响应 symbols_caps_v.yaml 的 symbols
291292
radical_lookup: "^uU[a-z]+$" # 响应部件拆字的反查,与 radical_lookup/prefix 匹配
292293
unicode: "^U[a-f0-9]+" # 脚本将自动获取第 2 个字符 U 作为触发前缀,响应 lua_translator@unicode,输出 Unicode 字符
293294
number: "^R[0-9]+[.]?[0-9]*" # 脚本将自动获取第 2 个字符 R 作为触发前缀,响应 lua_translator@number_translator,数字金额大写
295+
calculator: "^cC.+" # 响应 lua_translator@calc_translator,计算器。前缀设定项 calculator/prefix
294296
gregorian_to_lunar: "^N[0-9]{1,8}" # 脚本将自动获取第 2 个字符 N 作为触发前缀,响应 lua_translator@lunar,公历转农历,输入 N20240115 得到「二〇二三年腊月初五」
295297

296298

double_pinyin_abc.schema.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ engine:
7979
- table_translator@radical_lookup # 部件拆字反查
8080
- lua_translator@unicode # Unicode
8181
- lua_translator@number_translator # 数字、金额大写
82+
- lua_translator@calc_translator # 计算器
8283
- lua_translator@force_gc # 暴力 GC
8384
filters:
8485
- lua_filter@corrector # 错音错字提示
@@ -288,12 +289,13 @@ radical_reverse_lookup:
288289
# 处理符合特定规则的输入码,如网址、反查
289290

290291
recognizer:
291-
import_preset: default # 从 default.yaml 继承通用的
292-
patterns: # 再增加方案专有的:
292+
import_preset: default # 从 default.yaml 继承通用的
293+
patterns: # 再增加方案专有的:
293294
punct: "^V([0-9]|10|[A-Za-z]+)$" # 响应 symbols_caps_v.yaml 的 symbols
294295
radical_lookup: "^uU[a-z]+$" # 响应部件拆字的反查,与 radical_lookup/prefix 匹配
295296
unicode: "^U[a-f0-9]+" # 脚本将自动获取第 2 个字符 U 作为触发前缀,响应 lua_translator@unicode,输出 Unicode 字符
296297
number: "^R[0-9]+[.]?[0-9]*" # 脚本将自动获取第 2 个字符 R 作为触发前缀,响应 lua_translator@number_translator,数字金额大写
298+
calculator: "^cC.+" # 响应 lua_translator@calc_translator,计算器。前缀设定项 calculator/prefix
297299
gregorian_to_lunar: "^N[0-9]{1,8}" # 脚本将自动获取第 2 个字符 N 作为触发前缀,响应 lua_translator@lunar,公历转农历,输入 N20240115 得到「二〇二三年腊月初五」
298300

299301

double_pinyin_flypy.schema.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ engine:
7979
- table_translator@radical_lookup # 部件拆字反查
8080
- lua_translator@unicode # Unicode
8181
- lua_translator@number_translator # 数字、金额大写
82+
- lua_translator@calc_translator # 计算器
8283
- lua_translator@force_gc # 暴力 GC
8384
filters:
8485
- lua_filter@corrector # 错音错字提示
@@ -285,12 +286,13 @@ radical_reverse_lookup:
285286
# 处理符合特定规则的输入码,如网址、反查
286287

287288
recognizer:
288-
import_preset: default # 从 default.yaml 继承通用的
289-
patterns: # 再增加方案专有的:
289+
import_preset: default # 从 default.yaml 继承通用的
290+
patterns: # 再增加方案专有的:
290291
punct: "^V([0-9]|10|[A-Za-z]+)$" # 响应 symbols_caps_v.yaml 的 symbols
291292
radical_lookup: "^uU[a-z]+$" # 响应部件拆字的反查,与 radical_lookup/prefix 匹配
292293
unicode: "^U[a-f0-9]+" # 脚本将自动获取第 2 个字符 U 作为触发前缀,响应 lua_translator@unicode,输出 Unicode 字符
293294
number: "^R[0-9]+[.]?[0-9]*" # 脚本将自动获取第 2 个字符 R 作为触发前缀,响应 lua_translator@number_translator,数字金额大写
295+
calculator: "^cC.+" # 响应 lua_translator@calc_translator,计算器。前缀设定项 calculator/prefix
294296
gregorian_to_lunar: "^N[0-9]{1,8}" # 脚本将自动获取第 2 个字符 N 作为触发前缀,响应 lua_translator@lunar,公历转农历,输入 N20240115 得到「二〇二三年腊月初五」
295297

296298

double_pinyin_mspy.schema.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ engine:
7979
- table_translator@radical_lookup # 部件拆字反查
8080
- lua_translator@unicode # Unicode
8181
- lua_translator@number_translator # 数字、金额大写
82+
- lua_translator@calc_translator # 计算器
8283
- lua_translator@force_gc # 暴力 GC
8384
filters:
8485
- lua_filter@corrector # 错音错字提示
@@ -289,12 +290,13 @@ radical_reverse_lookup:
289290
# 处理符合特定规则的输入码,如网址、反查
290291

291292
recognizer:
292-
import_preset: default # 从 default.yaml 继承通用的
293-
patterns: # 再增加方案专有的:
293+
import_preset: default # 从 default.yaml 继承通用的
294+
patterns: # 再增加方案专有的:
294295
punct: "^V([0-9]|10|[A-Za-z]+)$" # 响应 symbols_caps_v.yaml 的 symbols
295296
radical_lookup: "^uU[a-z;]+$" # 响应部件拆字的反查,与 radical_lookup/prefix 匹配
296297
unicode: "^U[a-f0-9]+" # 脚本将自动获取第 2 个字符 U 作为触发前缀,响应 lua_translator@unicode,输出 Unicode 字符
297298
number: "^R[0-9]+[.]?[0-9]*" # 脚本将自动获取第 2 个字符 R 作为触发前缀,响应 lua_translator@number_translator,数字金额大写
299+
calculator: "^cC.+" # 响应 lua_translator@calc_translator,计算器。前缀设定项 calculator/prefix
298300
gregorian_to_lunar: "^N[0-9]{1,8}" # 脚本将自动获取第 2 个字符 N 作为触发前缀,响应 lua_translator@lunar,公历转农历,输入 N20240115 得到「二〇二三年腊月初五」
299301

300302

double_pinyin_sogou.schema.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ engine:
7979
- table_translator@radical_lookup # 部件拆字反查
8080
- lua_translator@unicode # Unicode
8181
- lua_translator@number_translator # 数字、金额大写
82+
- lua_translator@calc_translator # 计算器
8283
- lua_translator@force_gc # 暴力 GC
8384
filters:
8485
- lua_filter@corrector # 错音错字提示
@@ -289,12 +290,13 @@ radical_reverse_lookup:
289290
# 处理符合特定规则的输入码,如网址、反查
290291

291292
recognizer:
292-
import_preset: default # 从 default.yaml 继承通用的
293-
patterns: # 再增加方案专有的:
293+
import_preset: default # 从 default.yaml 继承通用的
294+
patterns: # 再增加方案专有的:
294295
punct: "^V([0-9]|10|[A-Za-z]+)$" # 响应 symbols_caps_v.yaml 的 symbols
295296
radical_lookup: "^uU[a-z;]+$" # 响应部件拆字的反查,与 radical_lookup/prefix 匹配
296297
unicode: "^U[a-f0-9]+" # 脚本将自动获取第 2 个字符 U 作为触发前缀,响应 lua_translator@unicode,输出 Unicode 字符
297298
number: "^R[0-9]+[.]?[0-9]*" # 脚本将自动获取第 2 个字符 R 作为触发前缀,响应 lua_translator@number_translator,数字金额大写
299+
calculator: "^cC.+" # 响应 lua_translator@calc_translator,计算器。前缀设定项 calculator/prefix
298300
gregorian_to_lunar: "^N[0-9]{1,8}" # 脚本将自动获取第 2 个字符 N 作为触发前缀,响应 lua_translator@lunar,公历转农历,输入 N20240115 得到「二〇二三年腊月初五」
299301

300302

double_pinyin_ziguang.schema.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ engine:
7979
- table_translator@radical_lookup # 部件拆字反查
8080
- lua_translator@unicode # Unicode
8181
- lua_translator@number_translator # 数字、金额大写
82+
- lua_translator@calc_translator # 计算器
8283
- lua_translator@force_gc # 暴力 GC
8384
filters:
8485
- lua_filter@corrector # 错音错字提示
@@ -287,12 +288,13 @@ radical_reverse_lookup:
287288
# 处理符合特定规则的输入码,如网址、反查
288289

289290
recognizer:
290-
import_preset: default # 从 default.yaml 继承通用的
291-
patterns: # 再增加方案专有的:
291+
import_preset: default # 从 default.yaml 继承通用的
292+
patterns: # 再增加方案专有的:
292293
punct: "^V([0-9]|10|[A-Za-z]+)$" # 响应 symbols_caps_v.yaml 的 symbols
293294
radical_lookup: "^uU[a-z;]+$" # 响应部件拆字的反查,与 radical_lookup/prefix 匹配
294295
unicode: "^U[a-f0-9]+" # 脚本将自动获取第 2 个字符 U 作为触发前缀,响应 lua_translator@unicode,输出 Unicode 字符
295296
number: "^R[0-9]+[.]?[0-9]*" # 脚本将自动获取第 2 个字符 R 作为触发前缀,响应 lua_translator@number_translator,数字金额大写
297+
calculator: "^cC.+" # 响应 lua_translator@calc_translator,计算器。前缀设定项 calculator/prefix
296298
gregorian_to_lunar: "^N[0-9]{1,8}" # 脚本将自动获取第 2 个字符 N 作为触发前缀,响应 lua_translator@lunar,公历转农历,输入 N20240115 得到「二〇二三年腊月初五」
297299

298300

lua/calc_translator.lua

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
-- 计算器插件
2+
-- author: https://github.com/ChaosAlphard
3+
local calc = {}
4+
5+
function calc.init( env )
6+
local config = env.engine.schema.config
7+
env.prefix = config:get_string( 'calculator/prefix' ) or 'cC'
8+
env.show_prefix = config:get_bool( 'calculator/show_prefix' ) -- set to true to show prefix in preedit area
9+
-- env.decimalPlaces = config:get_string('calculator/decimalPlaces') or '4'
10+
end
11+
12+
local function startsWith( str, start ) return string.sub( str, 1, string.len( start ) ) == start end
13+
14+
local function truncateFromStart( str, truncateStr ) return string.sub( str, string.len( truncateStr ) + 1 ) end
15+
16+
local function yield_calc_cand( seg, cand_text, cand_comment, cand_preedit, show_prefix )
17+
local cand = Candidate( 'calc', seg.start, seg._end, cand_text, cand_comment )
18+
cand.quality = 99999
19+
if not show_prefix then cand.preedit = cand_preedit end
20+
yield( cand )
21+
end
22+
23+
-- 函数表
24+
local calcPlugin = {
25+
-- e, exp(1) = e^1 = e
26+
e = math.exp( 1 ),
27+
-- π
28+
pi = math.pi,
29+
}
30+
31+
-- random([m [,n ]]) 返回m-n之间的随机数, n为空则返回1-m之间, 都为空则返回0-1之间的小数
32+
local function random( ... ) return math.random( ... ) end
33+
-- 注册到函数表中
34+
calcPlugin['rdm'] = random
35+
calcPlugin['random'] = random
36+
37+
-- 正弦
38+
local function sin( x ) return math.sin( x ) end
39+
calcPlugin['sin'] = sin
40+
41+
-- 双曲正弦
42+
local function sinh( x ) return math.sinh( x ) end
43+
calcPlugin['sinh'] = sinh
44+
45+
-- 反正弦
46+
local function asin( x ) return math.asin( x ) end
47+
calcPlugin['asin'] = asin
48+
49+
-- 余弦
50+
local function cos( x ) return math.cos( x ) end
51+
calcPlugin['cos'] = cos
52+
53+
-- 双曲余弦
54+
local function cosh( x ) return math.cosh( x ) end
55+
calcPlugin['cosh'] = cosh
56+
57+
-- 反余弦
58+
local function acos( x ) return math.acos( x ) end
59+
calcPlugin['acos'] = acos
60+
61+
-- 正切
62+
local function tan( x ) return math.tan( x ) end
63+
calcPlugin['tan'] = tan
64+
65+
-- 双曲正切
66+
local function tanh( x ) return math.tanh( x ) end
67+
calcPlugin['tanh'] = tanh
68+
69+
-- 反正切
70+
-- 返回以弧度为单位的点相对于x轴的逆时针角度。x是点的横纵坐标比值
71+
-- 返回范围从−π到π (以弧度为单位),其中负角度表示向下旋转,正角度表示向上旋转
72+
local function atan( x ) return math.atan( x ) end
73+
calcPlugin['atan'] = atan
74+
75+
-- 反正切
76+
-- atan( y/x ) = atan2(y, x)
77+
-- 返回以弧度为单位的点相对于x轴的逆时针角度。y是点的纵坐标,x是点的横坐标
78+
-- 返回范围从−π到π (以弧度为单位),其中负角度表示向下旋转,正角度表示向上旋转
79+
-- 与 math.atan(y/x) 函数相比,具有更好的数学定义,因为它能够正确处理边界情况(例如x=0)
80+
local function atan2( y, x ) return math.atan2( y, x ) end
81+
calcPlugin['atan2'] = atan2
82+
83+
-- 将角度从弧度转换为度 e.g. deg(π) = 180
84+
local function deg( x ) return math.deg( x ) end
85+
calcPlugin['deg'] = deg
86+
87+
-- 将角度从度转换为弧度 e.g. rad(180) = π
88+
local function rad( x ) return math.rad( x ) end
89+
calcPlugin['rad'] = rad
90+
91+
-- 返回两个值, 无法参与运算后续, 只能单独使用
92+
-- 返回m,e 使得x = m * 2^e
93+
local function frexp( x )
94+
local m, e = math.frexp( x )
95+
return m .. ' * 2^' .. e
96+
end
97+
calcPlugin['frexp'] = frexp
98+
99+
-- 返回 x * 2^y
100+
local function ldexp( x, y ) return math.ldexp( x, y ) end
101+
calcPlugin['ldexp'] = ldexp
102+
103+
-- 返回 e^x
104+
local function exp( x ) return math.exp( x ) end
105+
calcPlugin['exp'] = exp
106+
107+
-- 返回x的平方根 e.g. sqrt(x) = x^0.5
108+
local function sqrt( x ) return math.sqrt( x ) end
109+
calcPlugin['sqrt'] = sqrt
110+
111+
-- y为底x的对数, 使用换底公式实现
112+
local function log( y, x )
113+
-- 不能为负数或0
114+
if x <= 0 or y <= 0 then return nil end
115+
116+
return math.log( x ) / math.log( y )
117+
end
118+
calcPlugin['log'] = log
119+
120+
-- e为底x的对数
121+
local function loge( x )
122+
-- 不能为负数或0
123+
if x <= 0 then return nil end
124+
125+
return math.log( x )
126+
end
127+
calcPlugin['loge'] = loge
128+
129+
-- 10为底x的对数
130+
local function log10( x )
131+
-- 不能为负数或0
132+
if x <= 0 then return nil end
133+
134+
return math.log10( x )
135+
end
136+
calcPlugin['log10'] = log10
137+
138+
-- 平均值
139+
local function avg( ... )
140+
local data = { ... }
141+
local n = select( '#', ... )
142+
-- 样本数量不能为0
143+
if n == 0 then return nil end
144+
145+
-- 计算总和
146+
local sum = 0
147+
for _, value in ipairs( data ) do sum = sum + value end
148+
149+
return sum / n
150+
end
151+
calcPlugin['avg'] = avg
152+
153+
-- 方差
154+
local function variance( ... )
155+
local data = { ... }
156+
local n = select( '#', ... )
157+
-- 样本数量不能为0
158+
if n == 0 then return nil end
159+
160+
-- 计算均值
161+
local sum = 0
162+
for _, value in ipairs( data ) do sum = sum + value end
163+
local mean = sum / n
164+
165+
-- 计算方差
166+
local sum_squared_diff = 0
167+
for _, value in ipairs( data ) do sum_squared_diff = sum_squared_diff + (value - mean) ^ 2 end
168+
169+
return sum_squared_diff / n
170+
end
171+
calcPlugin['var'] = variance
172+
173+
-- 阶乘
174+
local function factorial( x )
175+
-- 不能为负数
176+
if x < 0 then return nil end
177+
if x == 0 or x == 1 then return 1 end
178+
179+
local result = 1
180+
for i = 1, x do result = result * i end
181+
182+
return result
183+
end
184+
calcPlugin['fact'] = factorial
185+
186+
-- 实现阶乘计算(!)
187+
local function replaceToFactorial( str )
188+
-- 替换[0-9]!字符为fact([0-9])以实现阶乘
189+
return str:gsub( '([0-9]+)!', 'fact(%1)' )
190+
end
191+
192+
-- 简单计算器
193+
function calc.func( input, seg, env )
194+
if not seg:has_tag( 'calculator' ) or input == '' then return end
195+
-- 提取算式
196+
local express = truncateFromStart( input, env.prefix )
197+
if express == '' then return end -- 防止用户写错了正则表达式造成错误
198+
local code = replaceToFactorial( express )
199+
local success, result = pcall( load( 'return ' .. code, 'calculate', 't', calcPlugin ) )
200+
if success and result and (type( result ) == 'string' or type( result ) == 'number') and #tostring( result ) > 0 then
201+
yield_calc_cand( seg, result, '', express, env.show_prefix )
202+
yield_calc_cand( seg, express .. '=' .. result, '', express, env.show_prefix )
203+
else
204+
yield_calc_cand( seg, express, '解析失败', express, env.show_prefix )
205+
yield_calc_cand( seg, code, '入参', express, env.show_prefix )
206+
end
207+
end
208+
209+
return calc

rime.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ unicode = require("unicode")
2020
-- 数字、人民币大写,R 开头
2121
number_translator = require("number_translator")
2222

23+
-- 计算器
24+
calc_translator = require("calc_translator")
25+
2326
-- filters:
2427

2528
-- 错音错字提示

rime_ice.schema.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ engine:
6868
- table_translator@radical_lookup # 部件拆字反查
6969
- lua_translator@unicode # Unicode
7070
- lua_translator@number_translator # 数字、金额大写
71+
- lua_translator@calc_translator # 计算器
7172
- lua_translator@force_gc # 暴力 GC
7273
filters:
7374
- lua_filter@corrector # 错音错字提示
@@ -389,12 +390,13 @@ radical_reverse_lookup:
389390

390391
# 处理符合特定规则的输入码,如网址、反查
391392
recognizer:
392-
import_preset: default # 从 default.yaml 继承通用的
393-
patterns: # 再增加方案专有的:
393+
import_preset: default # 从 default.yaml 继承通用的
394+
patterns: # 再增加方案专有的:
394395
punct: "^v([0-9]|10|[A-Za-z]+)$" # 响应 symbols_v.yaml 的 symbols,用 'v' 替换 '/'
395396
radical_lookup: "^uU[a-z]+$" # 响应部件拆字的反查,与 radical_lookup/prefix 匹配
396397
unicode: "^U[a-f0-9]+" # 脚本将自动获取第 2 个字符 U 作为触发前缀,响应 lua_translator@unicode,输出 Unicode 字符
397398
number: "^R[0-9]+[.]?[0-9]*" # 脚本将自动获取第 2 个字符 R 作为触发前缀,响应 lua_translator@number_translator,数字金额大写
399+
calculator: "^cC.+" # 响应 lua_translator@calc_translator,计算器。前缀设定项 calculator/prefix
398400
gregorian_to_lunar: "^N[0-9]{1,8}" # 脚本将自动获取第 2 个字符 N 作为触发前缀,响应 lua_translator@lunar,公历转农历,输入 N20240115 得到「二〇二三年腊月初五」
399401

400402

0 commit comments

Comments
 (0)