mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-04-26 01:48:27 +02:00
feat: adjust overlays
This commit is contained in:
@@ -0,0 +1,402 @@
|
||||
-- Rime Script >https://github.com/baopaau/rime-lua-collection/blob/master/calculator_translator.lua
|
||||
-- 簡易計算器(執行任何Lua表達式)
|
||||
--
|
||||
-- 格式:=<exp>
|
||||
-- Lambda語法糖:\<arg>.<exp>|
|
||||
--
|
||||
-- 例子:
|
||||
-- =1+1 輸出 2
|
||||
-- =floor(9^(8/7)*cos(deg(6))) 輸出 -3
|
||||
-- =e^pi>pi^e 輸出 true
|
||||
-- =max({1,7,2}) 輸出 7
|
||||
-- =map({1,2,3},\x.x^2|) 輸出 {1, 4, 9}
|
||||
-- =map(range(-5,5),\x.x*pi/4|,deriv(sin)) 輸出 {-0.7071, -1, -0.7071, 0, 0.7071, 1, 0.7071, 0, -0.7071, -1}
|
||||
-- =$(range(-5,5,0.01))(map,\x.-60*x^2-16*x+20|)(max)() 輸出 21.066
|
||||
-- =test(\x.trunc(sin(x),1e-3)==trunc(deriv(cos)(x),1e-3)|,range(-2,2,0.1)) 輸出 true
|
||||
--
|
||||
-- 安装:
|
||||
-- - 將本文件保存至 <rime>/lua/
|
||||
-- - 在 <rime>/rime.lua 新增一行:
|
||||
-- `calculator_translator = require("calculator_translator")`
|
||||
-- - 在 <rime>/<schema>.schema.yaml 新增:
|
||||
-- `engine/translators/@next: lua_translator@calculator_translator`
|
||||
-- `recognizer/patterns/expression: "^=.*$"`
|
||||
-- 註:
|
||||
-- - <rime> 替換爲RIME的共享目錄
|
||||
-- - <schema> 替換爲自己的方案ID
|
||||
-- - 如目錄/文件不存在,請自行創建
|
||||
|
||||
-- 定義全局函數、常數(注意命名空間污染)
|
||||
cos = math.cos
|
||||
sin = math.sin
|
||||
tan = math.tan
|
||||
acos = math.acos
|
||||
asin = math.asin
|
||||
atan = math.atan
|
||||
rad = math.rad
|
||||
deg = math.deg
|
||||
|
||||
abs = math.abs
|
||||
floor = math.floor
|
||||
ceil = math.ceil
|
||||
mod = math.fmod
|
||||
trunc = function (x, dc)
|
||||
if dc == nil then
|
||||
return math.modf(x)
|
||||
end
|
||||
return x - mod(x, dc)
|
||||
end
|
||||
|
||||
round = function (x, dc)
|
||||
dc = dc or 1
|
||||
local dif = mod(x, dc)
|
||||
if abs(dif) > dc / 2 then
|
||||
return x < 0 and x - dif - dc or x - dif + dc
|
||||
end
|
||||
return x - dif
|
||||
end
|
||||
|
||||
random = math.random
|
||||
randomseed = math.randomseed
|
||||
|
||||
inf = math.huge
|
||||
MAX_INT = math.maxinteger
|
||||
MIN_INT = math.mininteger
|
||||
pi = math.pi
|
||||
sqrt = math.sqrt
|
||||
exp = math.exp
|
||||
e = exp(1)
|
||||
ln = math.log
|
||||
log = function (x, base)
|
||||
base = base or 10
|
||||
return ln(x)/ln(base)
|
||||
end
|
||||
|
||||
min = function (arr)
|
||||
local m = inf
|
||||
for k, x in ipairs(arr) do
|
||||
m = x < m and x or m
|
||||
end
|
||||
return m
|
||||
end
|
||||
|
||||
max = function (arr)
|
||||
local m = -inf
|
||||
for k, x in ipairs(arr) do
|
||||
m = x > m and x or m
|
||||
end
|
||||
return m
|
||||
end
|
||||
|
||||
sum = function (t)
|
||||
local acc = 0
|
||||
for k,v in ipairs(t) do
|
||||
acc = acc + v
|
||||
end
|
||||
return acc
|
||||
end
|
||||
|
||||
avg = function (t)
|
||||
return sum(t) / #t
|
||||
end
|
||||
|
||||
isinteger = function (x)
|
||||
return math.fmod(x, 1) == 0
|
||||
end
|
||||
|
||||
-- iterator . array
|
||||
array = function (...)
|
||||
local arr = {}
|
||||
for v in ... do
|
||||
arr[#arr + 1] = v
|
||||
end
|
||||
return arr
|
||||
end
|
||||
|
||||
-- iterator <- [form, to)
|
||||
irange = function (from, to, step)
|
||||
if to == nil then
|
||||
to = from
|
||||
from = 0
|
||||
end
|
||||
step = step or 1
|
||||
local i = from - step
|
||||
to = to - step
|
||||
return function()
|
||||
if i < to then
|
||||
i = i + step
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- array <- [form, to)
|
||||
range = function (from, to, step)
|
||||
return array(irange(from, to, step))
|
||||
end
|
||||
|
||||
-- array . reversed iterator
|
||||
irev = function (arr)
|
||||
local i = #arr + 1
|
||||
return function()
|
||||
if i > 1 then
|
||||
i = i - 1
|
||||
return arr[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- array . reversed array
|
||||
arev = function (arr)
|
||||
return array(irev(arr))
|
||||
end
|
||||
|
||||
test = function (f, t)
|
||||
for k,v in ipairs(t) do
|
||||
if not f(v) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- # Functional
|
||||
map = function (t, ...)
|
||||
local ta = {}
|
||||
for k,v in pairs(t) do
|
||||
local tmp = v
|
||||
for _,f in pairs({...}) do tmp = f(tmp) end
|
||||
ta[k] = tmp
|
||||
end
|
||||
return ta
|
||||
end
|
||||
|
||||
filter = function (t, ...)
|
||||
local ta = {}
|
||||
local i = 1
|
||||
for k,v in pairs(t) do
|
||||
local erase = false
|
||||
for _,f in pairs({...}) do
|
||||
if not f(v) then
|
||||
erase = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not erase then
|
||||
ta[i] = v
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return ta
|
||||
end
|
||||
|
||||
-- e.g: foldr({2,3},\n,x.x^n|,2) = 81
|
||||
foldr = function (t, f, acc)
|
||||
for k,v in pairs(t) do
|
||||
acc = f(acc, v)
|
||||
end
|
||||
return acc
|
||||
end
|
||||
|
||||
-- e.g: foldl({2,3},\n,x.x^n|,2) = 512
|
||||
foldl = function (t, f, acc)
|
||||
for v in irev(t) do
|
||||
acc = f(acc, v)
|
||||
end
|
||||
return acc
|
||||
end
|
||||
|
||||
-- 調用鏈生成函數(HOF for method chaining)
|
||||
-- e.g: chain(range(-5,5))(map,\x.x/5|)(map,sin)(map,\x.e^x*10|)(map,floor)()
|
||||
-- = floor(map(map(map(range(-5,5),\x.x/5|),sin),\x.e^x*10|))
|
||||
-- = {4, 4, 5, 6, 8, 10, 12, 14, 17, 20}
|
||||
-- 可以用 $ 代替 chain
|
||||
chain = function (t)
|
||||
local ta = t
|
||||
local function cf(f, ...)
|
||||
if f ~= nil then
|
||||
ta = f(ta, ...)
|
||||
return cf
|
||||
else
|
||||
return ta
|
||||
end
|
||||
end
|
||||
return cf
|
||||
end
|
||||
|
||||
-- # Statistics
|
||||
fac = function (n)
|
||||
local acc = 1
|
||||
for i = 2,n do
|
||||
acc = acc * i
|
||||
end
|
||||
return acc
|
||||
end
|
||||
|
||||
nPr = function (n, r)
|
||||
return fac(n) / fac(n - r)
|
||||
end
|
||||
|
||||
nCr = function (n, r)
|
||||
return nPr(n,r) / fac(r)
|
||||
end
|
||||
|
||||
MSE = function (t)
|
||||
local ss = 0
|
||||
local s = 0
|
||||
local n = #t
|
||||
for k,v in ipairs(t) do
|
||||
ss = ss + v*v
|
||||
s = s + v
|
||||
end
|
||||
return sqrt((n*ss - s*s) / (n*n))
|
||||
end
|
||||
|
||||
-- # Linear Algebra
|
||||
|
||||
|
||||
-- # Calculus
|
||||
-- Linear approximation
|
||||
lapproxd = function (f, delta)
|
||||
local delta = delta or 1e-8
|
||||
return function (x)
|
||||
return (f(x+delta) - f(x)) / delta
|
||||
end
|
||||
end
|
||||
|
||||
-- Symmetric approximation
|
||||
sapproxd = function (f, delta)
|
||||
local delta = delta or 1e-8
|
||||
return function (x)
|
||||
return (f(x+delta) - f(x-delta)) / delta / 2
|
||||
end
|
||||
end
|
||||
|
||||
-- 近似導數
|
||||
deriv = function (f, delta, dc)
|
||||
dc = dc or 1e-4
|
||||
local fd = sapproxd(f, delta)
|
||||
return function (x)
|
||||
return round(fd(x), dc)
|
||||
end
|
||||
end
|
||||
|
||||
-- Trapezoidal rule
|
||||
trapzo = function (f, a, b, n)
|
||||
local dif = b - a
|
||||
local acc = 0
|
||||
for i = 1, n-1 do
|
||||
acc = acc + f(a + dif * (i/n))
|
||||
end
|
||||
acc = acc * 2 + f(a) + f(b)
|
||||
acc = acc * dif / n / 2
|
||||
return acc
|
||||
end
|
||||
|
||||
-- 近似積分
|
||||
integ = function (f, delta, dc)
|
||||
delta = delta or 1e-4
|
||||
dc = dc or 1e-4
|
||||
return function (a, b)
|
||||
if b == nil then
|
||||
b = a
|
||||
a = 0
|
||||
end
|
||||
local n = round(abs(b - a) / delta)
|
||||
return round(trapzo(f, a, b, n), dc)
|
||||
end
|
||||
end
|
||||
|
||||
-- Runge-Kutta
|
||||
rk4 = function (f, timestep)
|
||||
local timestep = timestep or 0.01
|
||||
return function (start_x, start_y, time)
|
||||
local x = start_x
|
||||
local y = start_y
|
||||
local t = time
|
||||
-- loop until i >= t
|
||||
for i = 0, t, timestep do
|
||||
local k1 = f(x, y)
|
||||
local k2 = f(x + (timestep/2), y + (timestep/2)*k1)
|
||||
local k3 = f(x + (timestep/2), y + (timestep/2)*k2)
|
||||
local k4 = f(x + timestep, y + timestep*k3)
|
||||
y = y + (timestep/6)*(k1 + 2*k2 + 2*k3 + k4)
|
||||
x = x + timestep
|
||||
end
|
||||
return y
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- # System
|
||||
date = os.date
|
||||
time = os.time
|
||||
path = function ()
|
||||
return debug.getinfo(1).source:match("@?(.*/)")
|
||||
end
|
||||
|
||||
|
||||
local function serialize(obj)
|
||||
local type = type(obj)
|
||||
if type == "number" then
|
||||
return isinteger(obj) and floor(obj) or obj
|
||||
elseif type == "boolean" then
|
||||
return tostring(obj)
|
||||
elseif type == "string" then
|
||||
return '"'..obj..'"'
|
||||
elseif type == "table" then
|
||||
local str = "{"
|
||||
local i = 1
|
||||
for k, v in pairs(obj) do
|
||||
if i ~= k then
|
||||
str = str.."["..serialize(k).."]="
|
||||
end
|
||||
str = str..serialize(v)..", "
|
||||
i = i + 1
|
||||
end
|
||||
str = str:len() > 3 and str:sub(0,-3) or str
|
||||
return str.."}"
|
||||
elseif pcall(obj) then -- function類型
|
||||
return "callable"
|
||||
end
|
||||
return obj
|
||||
end
|
||||
|
||||
-- greedy:隨時求值(每次變化都會求值,否則結尾爲特定字符時求值)
|
||||
local greedy = true
|
||||
|
||||
local function calculator_translator(input, seg)
|
||||
if string.sub(input, 1, 1) ~= "=" then return end
|
||||
|
||||
local expfin = greedy or string.sub(input, -1, -1) == ";"
|
||||
local exp = (greedy or not expfin) and string.sub(input, 2, -1) or string.sub(input, 2, -2)
|
||||
|
||||
-- 空格輸入可能
|
||||
exp = exp:gsub("#", " ")
|
||||
|
||||
|
||||
if not expfin then return end
|
||||
|
||||
local expe = exp
|
||||
-- 鏈式調用語法糖
|
||||
expe = expe:gsub("%$", " chain ")
|
||||
-- lambda語法糖
|
||||
do
|
||||
local count
|
||||
repeat
|
||||
expe, count = expe:gsub("\\%s*([%a%d%s,_]-)%s*%.(.-)|", " (function (%1) return %2 end) ")
|
||||
until count == 0
|
||||
end
|
||||
--yield(Candidate("number", seg.start, seg._end, expe, "展開"))
|
||||
|
||||
-- 防止危險操作,禁用os和io命名空間
|
||||
if expe:find("i?os?%.") then return end
|
||||
-- return語句保證了只有合法的Lua表達式才可執行
|
||||
local result = load("return "..expe)()
|
||||
if result == nil then return end
|
||||
|
||||
result = serialize(result)
|
||||
yield(Candidate("number", seg.start, seg._end, exp.."="..result, ""))
|
||||
end
|
||||
|
||||
return calculator_translator
|
||||
Reference in New Issue
Block a user