117 lines
3.1 KiB
Plaintext
117 lines
3.1 KiB
Plaintext
|
(local lume (require :plugins.fennel-xl.lume))
|
||
|
(local json (require :plugins.fennel-xl.dkjson))
|
||
|
(local core (require :core))
|
||
|
|
||
|
(fn string.fromhex [str]
|
||
|
(str:gsub ".." (fn [cc] (string.char (tonumber cc 16)))))
|
||
|
(fn string.tohex [str]
|
||
|
(str:gsub "." (fn [c] (string.format "%02X" (string.byte c)))))
|
||
|
|
||
|
(fn splice [bytes offset str]
|
||
|
(.. (bytes:sub 1 offset)
|
||
|
str
|
||
|
(bytes:sub (+ (length str) offset 1))))
|
||
|
|
||
|
(fn reload [modname]
|
||
|
(tset package.loaded modname nil)
|
||
|
(require modname))
|
||
|
|
||
|
; lume.hotswap really assumes your module is a table
|
||
|
(fn hotswap [modname]
|
||
|
(if (= (type (. package.loaded modname)) :table)
|
||
|
(lume.hotswap modname)
|
||
|
(reload modname)))
|
||
|
|
||
|
(fn mk-swappable-fn [table k]
|
||
|
(fn [...] ((. table k) ...)))
|
||
|
|
||
|
(fn swappable [table]
|
||
|
(local s {})
|
||
|
(each [k v (pairs table)]
|
||
|
(if (= (type v) :function)
|
||
|
(tset s k (mk-swappable-fn table k))
|
||
|
(tset s k v)))
|
||
|
s)
|
||
|
|
||
|
(fn swappable-require [modname]
|
||
|
(swappable (require modname)))
|
||
|
|
||
|
(fn hot-table [modname]
|
||
|
(local tbl {})
|
||
|
(fn find-table []
|
||
|
(let [loaded-pkg (. package.loaded modname)]
|
||
|
(if (= (type loaded-pkg) :table) loaded-pkg tbl)))
|
||
|
(setmetatable {:hot tbl} {
|
||
|
:__index (fn [_ key] (. (find-table) key))
|
||
|
:__newindex (fn [_ key val] (tset (find-table) key val))
|
||
|
}))
|
||
|
|
||
|
(fn readjson [filename]
|
||
|
(local f (io.open filename :r))
|
||
|
(local text (f:read "*a"))
|
||
|
(f:close)
|
||
|
(json.decode text))
|
||
|
|
||
|
(fn writejson [filename value]
|
||
|
(local f (io.open filename :w))
|
||
|
(f:write (json.encode value))
|
||
|
(f:close))
|
||
|
|
||
|
(fn waitfor [pred]
|
||
|
(local coro (coroutine.running))
|
||
|
(core.add_thread
|
||
|
(fn []
|
||
|
(while (not (pred))
|
||
|
(coroutine.yield))
|
||
|
(coroutine.resume coro))
|
||
|
coro)
|
||
|
(coroutine.yield))
|
||
|
|
||
|
(fn in-coro [f ...] (-> (coroutine.create f) (coroutine.resume ...)))
|
||
|
|
||
|
(fn multival-next [multival i]
|
||
|
(when (< i multival.n)
|
||
|
(values (+ i 1) (. multival (+ i 1)))))
|
||
|
|
||
|
(fn multival-ipairs [multival]
|
||
|
(values multival-next multival 0))
|
||
|
|
||
|
(fn multival [...]
|
||
|
(local multival {:n (select :# ...) :ipairs multival-ipairs})
|
||
|
(for [i 1 multival.n]
|
||
|
(tset multival i (select i ...)))
|
||
|
multival)
|
||
|
|
||
|
(fn nested-tset [t keys value]
|
||
|
(let [next-key (. keys 1)]
|
||
|
(if (= (length keys) 1) (tset t next-key value)
|
||
|
(do (when (= (. t next-key) nil)
|
||
|
(tset t next-key {}))
|
||
|
(nested-tset (. t next-key) (lume.slice keys 2) value)))))
|
||
|
|
||
|
(fn file-exists [name]
|
||
|
(let [f (io.open name :r)]
|
||
|
(when (not= f nil) (io.close f))
|
||
|
(not= f nil)))
|
||
|
|
||
|
(fn pairoff [l]
|
||
|
(fn [_ iprev] (let [i (if iprev (+ iprev 2) 1)]
|
||
|
(when (< i (length l)) (values i (. l i) (. l (+ i 1)))))))
|
||
|
|
||
|
(fn countiter [minmax ?max ?step]
|
||
|
(let [min (if ?max minmax 1)
|
||
|
max (or ?max minmax)
|
||
|
step (or ?step 1)]
|
||
|
(fn [_ iprev]
|
||
|
(let [i (if iprev (+ iprev step) min)]
|
||
|
(when (if (> step 0) (<= i max) (>= i max)) i)))))
|
||
|
|
||
|
(fn condlist [...] (let [l []] (lume.push l ...) l))
|
||
|
|
||
|
(fn prototype [base] (setmetatable {} {:__index base}))
|
||
|
|
||
|
{: splice : condlist : prototype
|
||
|
: reload : hotswap : swappable :require swappable-require : hot-table : nested-tset : pairoff : countiter
|
||
|
: readjson : writejson : file-exists : waitfor : in-coro : multival}
|
||
|
|