nix

configuration files that power my machines
Log | Files | Refs | README | LICENSE

commit a1f90ce1213890ad92650f22bebb4f470afae384
parent 5299b9eb60f4b85f7ab6a48332ea6fdefa313d31
Author: mtmn <miro@haravara.org>
Date:   Sat, 25 Apr 2026 15:03:33 +0200

chore: remove lua/std functions

Diffstat:
Dmodules/mixins/dotfiles/config/nvim/lua/std/_base.lua | 204-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/debug.lua | 156-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/functional/_base.lua | 111-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/functional/init.lua | 883-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/functional/operator.lua | 239-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/functional/tuple.lua | 156-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/init.lua | 389-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/io.lua | 322-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/math.lua | 92-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/normalize/init.lua | 1342-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/package.lua | 263-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/string.lua | 504-------------------------------------------------------------------------------
Dmodules/mixins/dotfiles/config/nvim/lua/std/table.lua | 439-------------------------------------------------------------------------------
13 files changed, 0 insertions(+), 5100 deletions(-)

diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/_base.lua b/modules/mixins/dotfiles/config/nvim/lua/std/_base.lua @@ -1,204 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Prevent dependency loops with key function implementations. - - A few key functions are used in several stdlib modules; we implement those - functions in this internal module to prevent dependency loops in the first - instance, and to minimise coupling between modules where the use of one of - these functions might otherwise load a whole selection of other supporting - modules unnecessarily. - - Although the implementations are here for logistical reasons, we re-export - them from their respective logical modules so that the api is not affected - as far as client code is concerned. The functions in this file do not make - use of `argcheck` or similar, because we know that they are only called by - other stdlib functions which have already performed the necessary checking - and neither do we want to slow everything down by recheckng those argument - types here. - - This implies that when re-exporting from another module when argument type - checking is in force, we must export a wrapper function that can check the - user's arguments fully at the API boundary. -]] - - -local _ENV = require 'std.normalize' { - concat = 'table.concat', - dirsep = 'package.dirsep', - find = 'string.find', - gsub = 'string.gsub', - insert = 'table.insert', - min = 'math.min', - shallow_copy = 'table.merge', - sort = 'table.sort', - sub = 'string.sub', - table_maxn = table.maxn, - wrap = 'coroutine.wrap', - yield = 'coroutine.yield', -} - - - ---[[ ============================ ]]-- ---[[ Enhanced Core Lua functions. ]]-- ---[[ ============================ ]]-- - - --- These come as early as possible, because we want the rest of the code --- in this file to use these versions over the core Lua implementation --- (which have slightly varying semantics between releases). - - -local maxn = table_maxn or function(t) - local n = 0 - for k in pairs(t) do - if type(k) == 'number' and k > n then - n = k - end - end - return n -end - - - ---[[ ============================ ]]-- ---[[ Shared Stdlib API functions. ]]-- ---[[ ============================ ]]-- - - --- No need to recurse because functables are second class citizens in --- Lua: --- func = function() print 'called' end --- func() --> 'called' --- functable=setmetatable({}, {__call=func}) --- functable() --> 'called' --- nested=setmetatable({}, {__call=functable}) --- nested() --- --> stdin:1: attempt to call a table value(global 'd') --- --> stack traceback: --- --> stdin:1: in main chunk --- --> [C]: in ? -local function callable(x) - if type(x) == 'function' then - return x - end - return (getmetatable(x) or {}).__call -end - - -local function catfile(...) - return concat({...}, dirsep) -end - - -local function compare(l, m) - local lenl, lenm = len(l), len(m) - for i = 1, min(lenl, lenm) do - local li, mi = tonumber(l[i]), tonumber(m[i]) - if li == nil or mi == nil then - li, mi = l[i], m[i] - end - if li < mi then - return -1 - elseif li > mi then - return 1 - end - end - if lenl < lenm then - return -1 - elseif lenl > lenm then - return 1 - end - return 0 -end - - -local function escape_pattern(s) - return (gsub(s, '[%^%$%(%)%%%.%[%]%*%+%-%?]', '%%%0')) -end - - -local function invert(t) - local i = {} - for k, v in pairs(t) do - i[v] = k - end - return i -end - - -local function leaves(it, tr) - local function visit(n) - if type(n) == 'table' then - for _, v in it(n) do - visit(v) - end - else - yield(n) - end - end - return wrap(visit), tr -end - - -local function split(s, sep) - local r, patt = {} - if sep == '' then - patt = '(.)' - insert(r, '') - else - patt = '(.-)' ..(sep or '%s+') - end - local b, slen = 0, len(s) - while b <= slen do - local e, n, m = find(s, patt, b + 1) - insert(r, m or sub(s, b + 1, slen)) - b = n or slen + 1 - end - return r -end - - ---[[ ============= ]]-- ---[[ Internal API. ]]-- ---[[ ============= ]]-- - - --- For efficient use within stdlib, these functions have no type-checking. --- In debug mode, type-checking wrappers are re-exported from the public- --- facing modules as necessary. --- --- Also, to provide some sanity, we mirror the subtable layout of stdlib --- public API here too, which means everything looks relatively normal --- when importing the functions into stdlib implementation modules. -return { - io = { - catfile = catfile, - }, - - list = { - compare = compare, - }, - - object = { - Module = Module, - mapfields = mapfields, - }, - - string = { - escape_pattern = escape_pattern, - split = split, - }, - - table = { - invert = invert, - maxn = maxn, - }, - - tree = { - leaves = leaves, - }, -} diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/debug.lua b/modules/mixins/dotfiles/config/nvim/lua/std/debug.lua @@ -1,156 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core debug module. - - The module table returned by `std.debug` also contains all of the entries - from the core debug table. An hygienic way to import this module, then, is - simply to override the core `debug` locally: - - local debug = require 'std.debug' - - @corelibrary std.debug -]] - - -local _ENV = require 'std.normalize' { - 'debug', - _debug = require 'std._debug', - concat = 'table.concat', - huge = 'math.huge', - max = 'math.max', - merge = 'table.merge', - stderr = 'io.stderr', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local function say(n, ...) - local level, argt = n, {...} - if type(n) ~= 'number' then - level, argt = 1, {n, ...} - end - if _debug.level ~= huge and - ((type(_debug.level) == 'number' and _debug.level >= level) or level <= 1) - then - local t = {} - for k, v in pairs(argt) do - t[k] = str(v) - end - stderr:write(concat(t, '\t') .. '\n') - end -end - - -local level = 0 - -local function trace(event) - local t = debug.getinfo(3) - local s = ' >>> ' - for i = 1, level do - s = s .. ' ' - end - if t ~= nil and t.currentline >= 0 then - s = s .. t.short_src .. ':' .. t.currentline .. ' ' - end - t = debug.getinfo(2) - if event == 'call' then - level = level + 1 - else - level = max(level - 1, 0) - end - if t.what == 'main' then - if event == 'call' then - s = s .. 'begin ' .. t.short_src - else - s = s .. 'end ' .. t.short_src - end - elseif t.what == 'Lua' then - s = s .. event .. ' ' ..(t.name or '(Lua)') .. ' <' .. - t.linedefined .. ':' .. t.short_src .. '>' - else - s = s .. event .. ' ' ..(t.name or '(C)') .. ' [' .. t.what .. ']' - end - stderr:write(s .. '\n') -end - --- Set hooks according to _debug -if _debug.call then - debug.sethook(trace, 'cr') -end - - - -local M = { - --- Function Environments - -- @section environments - - --- Extend `debug.getfenv` to unwrap functables correctly. - -- @function getfenv - -- @tparam int|function|functable fn target function, or stack level - -- @treturn table environment of *fn* - getfenv = getfenv, - - --- Extend `debug.setfenv` to unwrap functables correctly. - -- @function setfenv - -- @tparam function|functable fn target function - -- @tparam table env new function environment - -- @treturn function *fn* - setfenv = setfenv, - - - --- Functions - -- @section functions - - --- Print a debugging message to `io.stderr`. - -- Display arguments passed through `std.tostring` and separated by tab - -- characters when `std._debug` hinting is `true` and *n* is 1 or less; - -- or `std._debug.level` is a number greater than or equal to *n*. If - -- `std._debug` hinting is false or nil, nothing is written. - -- @function say - -- @int[opt=1] n debugging level, smaller is higher priority - -- @param ... objects to print(as for print) - -- @usage - -- local _debug = require 'std._debug' - -- _debug.level = 3 - -- say(2, '_debug status level:', _debug.level) - say = say, - - --- Trace function calls. - -- Use as debug.sethook(trace, 'cr'), which is done automatically - -- when `std._debug.call` is set. - -- Based on test/trace-calls.lua from the Lua distribution. - -- @function trace - -- @string event event causing the call - -- @usage - -- local _debug = require 'std._debug' - -- _debug.call = true - -- local debug = require 'std.debug' - trace = trace, -} - - ---- Metamethods --- @section metamethods - ---- Equivalent to calling `debug.say(1, ...)` --- @function __call --- @see say --- @usage --- local debug = require 'std.debug' --- debug 'oh noes!' -local metatable = { - __call = function(self, ...) - M.say(1, ...) - end, -} - - -return setmetatable(merge(debug, M), metatable) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/functional/_base.lua b/modules/mixins/dotfiles/config/nvim/lua/std/functional/_base.lua @@ -1,111 +0,0 @@ ---[[ - Functional programming for Lua 5.1, 5.2, 5.3 & 5.4 - Copyright (C) 2002-2022 std.functional authors -]] ---[[-- - Purely to break internal dependency cycles without introducing - multiple copies of base functions used in other modules. - - @module std.functional._base -]] - -local _ENV = require 'std.normalize' { - 'string.format', - 'table.concat', - 'table.keys', - 'table.sort', -} - - -local argscheck -do - local ok, typecheck = pcall(require, 'typecheck') - if ok then - argscheck = typecheck.argscheck - else - argscheck = function(decl, fn) - return fn - end - end -end - - - ---[[ ================= ]]-- ---[[ Shared Functions. ]]-- ---[[ ================= ]]-- - - -local function shallow_copy(t) - local r = {} - for k, v in next, t do - r[k] = v - end - return r -end - - -local function toqstring(x) - if type(x) ~= 'string' then - return tostring(x) - end - return format('%q', x) -end - - -local function keycmp(a, b) - if type(a) == 'number' then - return type(b) ~= 'number' or a < b - else - return type(b) ~= 'number' and tostring(a) < tostring(b) - end -end - - -local function sortedkeys(t, cmp) - local r = keys(t) - sort(r, cmp) - return r -end - - -local function serialize(x, roots) - roots = roots or {} - - local function stop_roots(x) - return roots[x] or serialize(x, shallow_copy(roots)) - end - - if type(x) ~= 'table' or getmetamethod(x, '__tostring') then - return toqstring(x) - - else - local buf = {'{'} -- pre-buffer table open - roots[x] = toqstring(x) -- recursion protection - - local kp -- previous key - for _, k in ipairs(sortedkeys(x, keycmp)) do - if kp ~= nil then - buf[#buf + 1] = ',' - end - buf[#buf + 1] = stop_roots(kp) .. '=' .. stop_roots(x[k]) - kp = k - end - buf[#buf + 1] = '}' -- buffer << table close - - return concat(buf) -- stringify buffer - end -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -return { - argscheck = argscheck, - serialize = serialize, - toqstring = toqstring, -} diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/functional/init.lua b/modules/mixins/dotfiles/config/nvim/lua/std/functional/init.lua @@ -1,883 +0,0 @@ ---[[ - Functional programming for Lua 5.1, 5.2, 5.3 & 5.4 - Copyright (C) 2002-2022 std.functional authors -]] ---[[-- - Functional programming. - - A selection of higher-order functions to enable a functional style of - programming in Lua. - - @module std.functional -]] - - -local _ENV = require 'std.normalize' { - 'coroutine.wrap', - 'coroutine.yield', - 'math.ceil', - 'std.functional._base.argscheck', - 'std.functional._base.serialize', - 'table.concat', - 'table.remove', -} - - - --- FIXME: Figure these two out: - -local function ielems(t) - -- capture ipairs iterator initial state - local fn, istate, ctrl = ipairs(t) - return function(state, _) - local v - ctrl, v = fn(state, ctrl) - if ctrl then - return v - end - end, istate, true -- wrapped initial state -end - - -local function leaves(it, tr) - local function visit(n) - if type(n) == 'table' then - for _, v in it(n) do - visit(v) - end - else - yield(n) - end - end - return wrap(visit), tr -end - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local function any(...) - local fns = pack(...) - - return function(...) - local argt = {n = 0} - for i = 1, fns.n do - argt = pack(fns[i](...)) - if argt[1] ~= nil then - return unpack(argt, 1, argt.n) - end - end - return unpack(argt, 1, argt.n) - end -end - - -local ceil = ceil -- FIXME: specl-14.x breaks function environments here :( - -local function bind(fn, bound) - return function(...) - local argt, unbound = {}, pack(...) - - -- Inline `argt = copy(bound)`... - local n = bound.n or 0 - for k, v in next, bound do - -- ...but only copy integer keys. - if type(k) == 'number' and ceil(k) == k then - argt[k] = v - n = k > n and k or n -- Inline `n = maxn(unbound)` in same pass. - end - end - - -- Bind *unbound* parameters sequentially into *argt* gaps. - local i = 1 - for j = 1, unbound.n do - while argt[i] ~= nil do - i = i + 1 - end - argt[i], i = unbound[j], i + 1 - end - - -- Even if there are gaps remaining above *i*, pass at least *n* args. - if n >= i then - return fn(unpack(argt, 1, n)) - end - - -- Otherwise, we filled gaps beyond *n*, and pass that many args. - return fn(unpack(argt, 1, i - 1)) - end -end - - --- No need to recurse because functables are second class citizens in --- Lua: --- func=function() print 'called' end --- func() --> 'called' --- functable=setmetatable({}, {__call=func}) --- functable() --> 'called' --- nested=setmetatable({}, {__call=functable}) --- nested() --- --> stdin:1: attempt to call a table value(global 'd') --- --> stack traceback: --- --> stdin:1: in main chunk --- --> [C]: in ? -local function callable(x) - if type(x) == 'function' then - return x - end - return (getmetatable(x) or {}).__call -end - - -local function case(with, branches) - local match = branches[with] or branches[1] - if callable(match) then - return match(with) - end - return match -end - - -local function collect(ifn, ...) - local r = {} - if not callable(ifn) then - -- No iterator behaves like npairs, which would collect all integer - -- key values from the first argument table: - local k, v = next(ifn) - repeat - if type(k) == 'number' then - r[k] = v - end - k, v = next(ifn, k) - until k == nil - return r - end - - -- Or else result depends on how many return values from ifn? - local arity = 1 - for e, v in ifn(...) do - if v then - arity, r = 2, {} - break - end - -- Build an arity-1 result table on first pass... - r[#r + 1] = e - end - - if arity == 2 then - -- ...oops, it was arity-2 all along, start again! - for k, v in ifn(...) do - r[k] = v - end - end - - return r -end - - -local function compose(...) - local fns = pack(...) - - return function(...) - local argt = pack(...) - for i = 1, fns.n do - argt = pack(fns[i](unpack(argt, 1, argt.n))) - end - return unpack(argt, 1, argt.n) - end -end - - -local function cond(expr, branch, ...) - if branch == nil and select('#', ...) == 0 then - expr, branch = true, expr - end - if expr then - if callable(branch) then - return branch(expr) - end - return branch - end - return cond(...) -end - - -local function curry(fn, n) - if n <= 1 then - return fn - else - return function(x) - return curry(bind(fn, {x}), n - 1) - end - end -end - - -local function filter(pfn, ifn, ...) - local argt, r = pack(...), {} - if not callable(ifn) then - ifn, argt = pairs, pack(ifn, ...) - end - - local nextfn, state, k = ifn(unpack(argt, 1, argt.n)) - - local t = pack(nextfn(state, k)) -- table of iteration 1 - local arity = #t -- How many return values from ifn? - - if arity == 1 then - local v = t[1] - while v ~= nil do -- until iterator returns nil - if pfn(unpack(t, 1, t.n)) then -- pass all iterator results to p - r[#r + 1] = v - end - - t = pack(nextfn(state, v)) -- maintain loop invariant - v = t[1] - - if #t > 1 then -- unless we discover arity is not 1 after all - arity, r = #t, {} break - end - end - end - - if arity > 1 then - -- No need to start over here, because either: - -- (i) arity was never 1, and the original value of t is correct - -- (ii) arity used to be 1, but we only consumed nil values, so the - -- current t with arity > 1 is the correct next value to use - while t[1] ~= nil do - local k = t[1] - if pfn(unpack(t, 1, t.n)) then - r[k] = t[2] - end - t = pack(nextfn(state, k)) - end - end - - return r -end - - -local function flatten(t) - return collect(leaves, ipairs, t) -end - - -local function reduce(fn, d, ifn, ...) - local argt - if not callable(ifn) then - ifn, argt = pairs, pack(ifn, ...) - else - argt = pack(...) - end - - local nextfn, state, k = ifn(unpack(argt, 1, argt.n)) - local t = pack(nextfn(state, k)) -- table of iteration 1 - - local r = d -- initialise accumulator - while t[1] ~= nil do -- until iterator returns nil - k = t[1] - r = fn(r, unpack(t, 1, t.n)) -- pass all iterator results to fn - t = pack(nextfn(state, k)) -- maintain loop invariant - end - return r -end - - -local function foldl(fn, d, t) - if t == nil then - local tail = {} - for i = 2, len(d) do - tail[#tail + 1] = d[i] - end - d, t = d[1], tail - end - return reduce(fn, d, ielems, t) -end - - --- Be careful to reverse only the valid sequence part of a table. -local function ireverse(t) - local oob = 1 - while t[oob] ~= nil do - oob = oob + 1 - end - - local r = {} - for i = 1, oob - 1 do - r[oob - i] = t[i] - end - return r -end - - -local function foldr(fn, d, t) - if t == nil then - local u, last = {}, len(d) - for i = 1, last - 1 do - u[#u + 1] = d[i] - end - d, t = d[last], u - end - return reduce(function(x, y) return fn(y, x) end, d, ielems, ireverse(t)) -end - - -local function id(...) - return ... -end - - -local function multiserialize(...) - local seq = pack(...) - local buf = {} - for i = 1, seq.n do - buf[i] = serialize(seq[i]) - end - return concat(buf, ',') -end - - -local function memoize(fn, mnemonic) - mnemonic = mnemonic or multiserialize - - return setmetatable({}, { - __call = function(self, ...) - local k = mnemonic(...) - local t = self[k] - if t == nil then - t = pack(fn(...)) - self[k] = t - end - return unpack(t, 1, t.n) - end - }) -end - - -local lambda = memoize(function(s) - local expr - - -- Support '|args|expression' format. - local args, body = s:match '^%s*|%s*([^|]*)|%s*(.+)%s*$' - if args and body then - expr = 'return function(' .. args .. ') return ' .. body .. ' end' - end - - -- Support 'expression' format. - if not expr then - body = s:match '^%s*(_.*)%s*$' or s:match '^=%s*(.+)%s*$' - if body then - expr = [[ - return function(...) - local _1,_2,_3,_4,_5,_6,_7,_8,_9 = ... - local _ = _1 - return ]] .. body .. [[ - end - ]] - end - end - - local ok, fn - if expr then - ok, fn = pcall(load(expr)) - end - - -- Diagnose invalid input. - if not ok then - return nil, "invalid lambda string '" .. s .. "'" - end - - return setmetatable({}, { - __call = function(self, ...) return fn(...) end, - __tostring = function(self) return s end, - }) -end, id) - - -local function map(mapfn, ifn, ...) - local argt, r = pack(...), {} - if not callable(ifn) or argt.n == 0 then - ifn, argt = pairs, pack(ifn, ...) - end - - local nextfn, state, k = ifn(unpack(argt, 1, argt.n)) - local mapargs = pack(nextfn(state, k)) - - local arity = 1 - while mapargs[1] ~= nil do - local d, v = mapfn(unpack(mapargs, 1, mapargs.n)) - if v ~= nil then - arity, r = 2, {} break - end - r[#r + 1] = d - mapargs = {nextfn(state, mapargs[1])} - end - - if arity > 1 then - -- No need to start over here, because either: - -- (i) arity was never 1, and the original value of mapargs is correct - -- (ii) arity used to be 1, but we only consumed nil values, so the - -- current mapargs with arity > 1 is the correct next value to use - while mapargs[1] ~= nil do - local k, v = mapfn(unpack(mapargs, 1, mapargs.n)) - r[k] = v - mapargs = pack(nextfn(state, mapargs[1])) - end - end - return r -end - - -local function map_with(mapfn, tt) - local r = {} - for k, v in next, tt do - r[k] = mapfn(unpack(v, 1, len(v))) - end - return r -end - - -local function _product(x, l) - local r = {} - for v1 in ielems(x) do - for v2 in ielems(l) do - r[#r + 1] = {v1, unpack(v2, 1, len(v2))} - end - end - return r -end - -local function product(...) - local argt = {...} - if not next(argt) then - return argt - else - -- Accumulate a list of products, starting by popping the last - -- argument and making each member a one element list. - local d = map(lambda '={_1}', ielems, remove(argt)) - -- Right associatively fold in remaining argt members. - return foldr(_product, d, argt) - end -end - - -local function shape(dims, t) - t = flatten(t) - -- Check the shape and calculate the size of the zero, if any - local size = 1 - local zero - for i, v in ipairs(dims) do - if v == 0 then - if zero then -- bad shape: two zeros - return nil - else - zero = i - end - else - size = size * v - end - end - if zero then - dims[zero] = ceil(len(t) / size) - end - local function fill(i, d) - if d > len(dims) then - return t[i], i + 1 - else - local r = {} - for j = 1, dims[d] do - local e - e, i = fill(i, d + 1) - r[#r + 1] = e - end - return r, i - end - end - return(fill(1, 1)) -end - - -local function zip(tt) - local r = {} - for outerk, inner in pairs(tt) do - for k, v in pairs(inner) do - r[k] = r[k] or {} - r[k][outerk] = v - end - end - return r -end - - -local function zip_with(fn, tt) - return map_with(fn, zip(tt)) -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck('std.functional.' .. decl, fn) -end - -return { - --- Call a series of functions until one returns non-nil. - -- @function any - -- @func ... functions to call - -- @treturn function to call fn1 .. fnN until one returns non-nil. - -- @usage - -- old_object_type = any(std.object.type, io.type, type) - any = X('any(func...)', any), - - --- Partially apply a function. - -- @function bind - -- @func fn function to apply partially - -- @tparam table argt table of *fn* arguments to bind - -- @return function with *argt* arguments already bound - -- @usage - -- cube = bind(std.functional.operator.pow, {[2] = 3}) - bind = X('bind(func, table)', bind), - - --- Identify callable types. - -- @function callable - -- @param x an object or primitive - -- @return `true` if *x* can be called, otherwise `false` - -- @usage - -- if callable(functable) then functable(args) end - callable = X('callable(?any)', callable), - - --- A rudimentary case statement. - -- Match *with* against keys in *branches* table. - -- @function case - -- @param with expression to match - -- @tparam table branches map possible matches to functions - -- @return the value associated with a matching key, or the first non-key - -- value if no key matches. Function or functable valued matches are - -- called using *with* as the sole argument, and the result of that call - -- returned; otherwise the matching value associated with the matching - -- key is returned directly; or else `nil` if there is no match and no - -- default. - -- @see cond - -- @usage - -- return case(type(object), { - -- table = 'table', - -- string = function() return 'string' end, - -- function(s) error('unhandled type: ' .. s) end, - -- }) - case = X('case(?any, #table)', case), - - --- Collect the results of an iterator. - -- @function collect - -- @func[opt=std.npairs] ifn iterator function - -- @param ... *ifn* arguments - -- @treturn table of results from running *ifn* on *args* - -- @see filter - -- @see map - -- @usage - -- --> {'a', 'b', 'c'} - -- collect {'a', 'b', 'c', x=1, y=2, z=5} - collect = X('collect([func], ?any...)', collect), - - --- Compose functions. - -- @function compose - -- @func ... functions to compose - -- @treturn function composition of fnN .. fn1: note that this is the - -- reverse of what you might expect, but means that code like: - -- - -- compose(function(x) return f(x) end, - -- function(x) return g(x) end)) - -- - -- can be read from top to bottom. - -- @usage - -- vpairs = compose(table.invert, ipairs) - -- for v, i in vpairs {'a', 'b', 'c'} do process(v, i) end - compose = X('compose(func...)', compose), - - --- A rudimentary condition-case statement. - -- If *expr* is 'truthy' return *branch* if given, otherwise *expr* - -- itself. If the return value is a function or functable, then call it - -- with *expr* as the sole argument and return the result; otherwise - -- return it explicitly. If *expr* is 'falsey', then recurse with the - -- first two arguments stripped. - -- @function cond - -- @param expr a Lua expression - -- @param branch a function, functable or value to use if *expr* is - -- 'truthy' - -- @param ... additional arguments to retry if *expr* is 'falsey' - -- @see case - -- @usage - -- -- recursively calculate the nth triangular number - -- function triangle(n) - -- return cond( - -- n <= 0, 0, - -- n == 1, 1, - -- function() return n + triangle(n - 1) end) - -- end - cond = cond, -- any number of any type arguments! - - --- Curry a function. - -- @function curry - -- @func fn function to curry - -- @int n number of arguments - -- @treturn function curried version of *fn* - -- @usage - -- add = curry(function(x, y) return x + y end, 2) - -- incr, decr = add(1), add(-1) - curry = X('curry(func, int)', curry), - - --- Filter an iterator with a predicate. - -- @function filter - -- @tparam predicate pfn predicate function - -- @func[opt=std.pairs] ifn iterator function - -- @param ... iterator arguments - -- @treturn table elements e for which `pfn(e)` is not 'falsey'. - -- @see collect - -- @see map - -- @usage - -- --> {2, 4} - -- filter(lambda '|e|e%2==0', std.elems, {1, 2, 3, 4}) - filter = X('filter(func, [func], ?any...)', filter), - - --- Flatten a nested table into a list. - -- @function flatten - -- @tparam table t a table - -- @treturn table a list of all non-table elements of *t* - -- @usage - -- --> {1, 2, 3, 4, 5} - -- flatten {{1, {{2}, 3}, 4}, 5} - flatten = X('flatten(table)', flatten), - - --- Fold a binary function left associatively. - -- If parameter *d* is omitted, the first element of *t* is used, - -- and *t* treated as if it had been passed without that element. - -- @function foldl - -- @func fn binary function - -- @param[opt=t[1]] d initial left-most argument - -- @tparam table t a table - -- @return result - -- @see foldr - -- @see reduce - -- @usage - -- foldl(operator.quot, {10000, 100, 10}) == (10000 / 100) / 10 - foldl = X('foldl(function, [any], table)', foldl), - - --- Fold a binary function right associatively. - -- If parameter *d* is omitted, the last element of *t* is used, - -- and *t* treated as if it had been passed without that element. - -- @function foldr - -- @func fn binary function - -- @param[opt=t[1]] d initial right-most argument - -- @tparam table t a table - -- @return result - -- @see foldl - -- @see reduce - -- @usage - -- foldr(operator.quot, {10000, 100, 10}) == 10000 / (100 / 10) - foldr = X('foldr(function, [any], table)', foldr), - - --- Identity function. - -- @function id - -- @param ... arguments - -- @return *arguments* - id = id, -- any number of any type arguments! - - --- Return a new sequence with element order reversed. - -- - -- Apart from the order of the elements returned, this function follows - -- the same rules as @{ipairs} for determining first and last elements. - -- @function ireverse - -- @tparam table t a table - -- @treturn table a new table with integer keyed elements in reverse - -- order with respect to *t* - -- @see ipairs - -- @usage - -- local rielems = compose(ireverse, std.ielems) - -- --> bar - -- --> foo - -- map(print, rielems, {'foo', 'bar', [4]='baz', d=5}) - ireverse = X('ireverse(table)', ireverse), - - --- Compile a lambda string into a Lua function. - -- - -- A valid lambda string takes one of the following forms: - -- - -- 1. `'=expression'`: equivalent to `function(...) return expression end` - -- 1. `'|args|expression'`: equivalent to `function(args) return expression end` - -- - -- The first form (starting with `'='`) automatically assigns the first - -- nine arguments to parameters `'_1'` through `'_9'` for use within the - -- expression body. The parameter `'_1'` is aliased to `'_'`, and if the - -- first non-whitespace of the whole expression is `'_'`, then the - -- leading `'='` can be omitted. - -- - -- The results are memoized, so recompiling a previously compiled - -- lambda string is extremely fast. - -- @function lambda - -- @string s a lambda string - -- @treturn functable compiled lambda string, can be called like a function - -- @usage - -- -- The following are equivalent: - -- lambda '= _1 < _2' - -- lambda '|a,b| a<b' - lambda = X('lambda(string)', lambda), - - --- Map a function over an iterator. - -- @function map - -- @func fn map function - -- @func[opt=std.pairs] ifn iterator function - -- @param ... iterator arguments - -- @treturn table results - -- @see filter - -- @see map_with - -- @see zip - -- @usage - -- --> {1, 4, 9, 16} - -- map(lambda '=_1*_1', std.ielems, {1, 2, 3, 4}) - map = X('map(func, [func], ?any...)', map), - - --- Map a function over a table of argument lists. - -- @function map_with - -- @func fn map function - -- @tparam table tt a table of *fn* argument lists - -- @treturn table new table of *fn* results - -- @see map - -- @see zip_with - -- @usage - -- --> {'123', '45'}, {a='123', b='45'} - -- conc = bind(map_with, {lambda '|...|table.concat {...}'}) - -- conc {{1, 2, 3}, {4, 5}}, conc {a={1, 2, 3, x='y'}, b={4, 5, z=6}} - map_with = X('map_with(function, table of tables)', map_with), - - --- Memoize a function, by wrapping it in a functable. - -- - -- To ensure that memoize always returns the same results for the same - -- arguments, it passes arguments to *fn*. You can specify a more - -- sophisticated function if memoize should handle complicated argument - -- equivalencies. - -- @function memoize - -- @func fn pure function: a function with no side effects - -- @tparam[opt=std.tostring] mnemonic mnemonicfn how to remember the arguments - -- @treturn functable memoized function - -- @usage - -- local fast = memoize(function(...) --[[ slow code ]] end) - memoize = X('memoize(func, ?func)', memoize), - - --- No operation. - -- This function ignores all arguments, and returns no values. - -- @function nop - -- @see id - -- @usage - -- if unsupported then vtable['memrmem'] = nop end - nop = function() end, - - --- Functional list product. - -- - -- Return a list of each combination possible by taking a single - -- element from each of the argument lists. - -- @function product - -- @param ... operands - -- @return result - -- @usage - -- --> {'000', '001', '010', '011', '100', '101', '110', '111'} - -- map(table.concat, ielems, product({0,1}, {0, 1}, {0, 1})) - product = X('product(list...)', product), - - --- Fold a binary function into an iterator. - -- @function reduce - -- @func fn reduce function - -- @param d initial first argument - -- @func[opt=std.pairs] ifn iterator function - -- @param ... iterator arguments - -- @return result - -- @see foldl - -- @see foldr - -- @usage - -- --> 2 ^ 3 ^ 4 ==> 4096 - -- reduce(operator.pow, 2, std.ielems, {3, 4}) - reduce = X('reduce(func, any, [func], ?any...)', reduce), - - --- Shape a table according to a list of dimensions. - -- - -- Dimensions are given outermost first and items from the original - -- list are distributed breadth first; there may be one 0 indicating - -- an indefinite number. Hence, `{0}` is a flat list, - -- `{1}` is a singleton, `{2, 0}` is a list of - -- two lists, and `{0, 2}` is a list of pairs. - -- - -- Algorithm: turn shape into all positive numbers, calculating - -- the zero if necessary and making sure there is at most one; - -- recursively walk the shape, adding empty tables until the bottom - -- level is reached at which point add table items instead, using a - -- counter to walk the flattened original list. - -- - -- @todo Use ileaves instead of flatten (needs a while instead of a - -- for in fill function) - -- @function shape - -- @tparam table dims table of dimensions `{d1, ..., dn}` - -- @tparam table t a table of elements - -- @return reshaped list - -- @usage - -- --> {{'a', 'b'}, {'c', 'd'}, {'e', 'f'}} - -- shape({3, 2}, {'a', 'b', 'c', 'd', 'e', 'f'}) - shape = X('shape(table, table)', shape), - - --- Zip a table of tables. - -- Make a new table, with lists of elements at the same index in the - -- original table. This function is effectively its own inverse. - -- @function zip - -- @tparam table tt a table of tables - -- @treturn table new table with lists of elements of the same key - -- from *tt* - -- @see map - -- @see zip_with - -- @usage - -- --> {{1, 3, 5}, {2, 4}}, {a={x=1, y=3, z=5}, b={x=2, y=4}} - -- zip {{1, 2}, {3, 4}, {5}}, zip {x={a=1, b=2}, y={a=3, b=4}, z={a=5}} - zip = X('zip(table of tables)', zip), - - --- Zip a list of tables together with a function. - -- @function zip_with - -- @tparam function fn function - -- @tparam table tt table of tables - -- @treturn table a new table of results from calls to *fn* with arguments - -- made from all elements the same key in the original tables; effectively - -- the 'columns' in a simple list - -- of lists. - -- @see map_with - -- @see zip - -- @usage - -- --> {'135', '24'}, {a='1', b='25'} - -- conc = bind(zip_with, {lambda '|...|table.concat {...}'}) - -- conc {{1, 2}, {3, 4}, {5}}, conc {{a=1, b=2}, x={a=3, b=4}, {b=5}} - zip_with = X('zip_with(function, table of tables)', zip_with), -} - - ---- Types --- @section Types - - ---- Signature of a @{memoize} argument normalization callback function. --- @function mnemonic --- @param ... arguments --- @treturn string stable serialized arguments --- @usage --- local mnemonic = function(name, value, props) return name end --- local intern = memoize(mksymbol, mnemonic) - - ---- Signature of a @{filter} predicate callback function. --- @function predicate --- @param ... arguments --- @treturn boolean 'truthy' if the predicate condition succeeds, --- 'falsey' otherwise --- @usage --- local predicate = lambda '|k,v|type(v)=="string"' --- local strvalues = filter(predicate, std.pairs, {name='Roberto', id=12345}) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/functional/operator.lua b/modules/mixins/dotfiles/config/nvim/lua/std/functional/operator.lua @@ -1,239 +0,0 @@ ---[[ - Functional programming for Lua 5.1, 5.2, 5.3 & 5.4 - Copyright (C) 2002-2022 std.functional authors -]] ---[[-- - Functional forms of Lua operators. - - @module std.functional.operator -]] - - -local _ENV = require 'std.normalize' { - 'std.functional._base.serialize', -} - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local function eqv(a, b) - -- If they are the same primitive value, or they share a metatable - -- with an __eq metamethod that says they are equivalent, we're done! - if a == b then - return true - end - - -- Unless we now have two tables, the previous line ensures a ~= b. - if type(a) ~= 'table' or type(b) ~= 'table' then - return false - end - - -- Otherwise, compare serializations of each. - return serialize(a) == serialize(b) -end - - -return { - --- Stringify and concatenate arguments. - -- @param a an argument - -- @param b another argument - -- @return concatenation of stringified arguments. - -- @usage - -- --> '=> 1000010010' - -- foldl(concat, '=> ', {10000, 100, 10}) - concat = function(a, b) - return tostring(a) .. tostring(b) - end, - - --- Equivalent to `#` operation, but respecting `__len` even on Lua 5.1. - -- @function len - -- @tparam object|string|table x operand - -- @treturn int length of list part of *t* - -- @usage - -- for i = 1, len(t) do process(t[i]) end - len = len, - - --- Dereference a table. - -- @tparam table t a table - -- @param k a key to lookup in *t* - -- @return value stored at *t[k]* if any, otherwise `nil` - -- @usage - -- --> 4 - -- foldl(get, {1, {{2, 3, 4}, 5}}, {2, 1, 3}) - get = function(t, k) - return t and t[k] or nil - end, - - --- Set a table element, honoring metamethods. - -- @tparam table t a table - -- @param k a key to lookup in *t* - -- @param v a value to set for *k* - -- @treturn table *t* - -- @usage - -- -- destructive table merge: - -- --> {'one', bar='baz', two=5} - -- reduce(set, {'foo', bar='baz'}, {'one', two=5}) - set = function(t, k, v) - t[k]=v - return t - end, - - --- Return the sum of the arguments. - -- @param a an argument - -- @param b another argument - -- @return the sum of the *a* and *b* - -- @usage - -- --> 10110 - -- foldl(sum, {10000, 100, 10}) - sum = function(a, b) - return a + b - end, - - --- Return the difference of the arguments. - -- @param a an argument - -- @param b another argument - -- @return the difference between *a* and *b* - -- @usage - -- --> 890 - -- foldl(diff, {10000, 100, 10}) - diff = function(a, b) - return a - b - end, - - --- Return the product of the arguments. - -- @param a an argument - -- @param b another argument - -- @return the product of *a* and *b* - -- @usage - -- --> 10000000 - -- foldl(prod, {10000, 100, 10}) - prod = function(a, b) - return a * b - end, - - --- Return the quotient of the arguments. - -- @param a an argument - -- @param b another argument - -- @return the quotient *a* and *b* - -- @usage - -- --> 1000 - -- foldr(quot, {10000, 100, 10}) - quot = function(a, b) - return a / b - end, - - --- Return the modulus of the arguments. - -- @param a an argument - -- @param b another argument - -- @return the modulus of *a* and *b* - -- @usage - -- --> 3 - -- foldl(mod, {65536, 100, 11}) - mod = function(a, b) - return a % b - end, - - --- Return the exponent of the arguments. - -- @param a an argument - -- @param b another argument - -- @return the *a* to the power of *b* - -- @usage - -- --> 4096 - -- foldl(pow, {2, 3, 4}) - pow = function(a, b) - return a ^ b - end, - - --- Return the logical conjunction of the arguments. - -- @param a an argument - -- @param b another argument - -- @return logical *a* and *b* - -- @usage - -- --> true - -- foldl(conj, {true, 1, 'false'}) - conj = function(a, b) - return a and b - end, - - --- Return the logical disjunction of the arguments. - -- @param a an argument - -- @param b another argument - -- @return logical *a* or *b* - -- @usage - -- --> true - -- foldl(disj, {true, 1, false}) - disj = function(a, b) - return a or b - end, - - --- Return the logical negation of the arguments. - -- @param a an argument - -- @return not *a* - -- @usage - -- --> {true, false, false, false} - -- bind(map, {std.ielems, neg}) {false, true, 1, 0} - neg = function(a) - return not a - end, - - --- Recursive table equivalence. - -- @param a an argument - -- @param b another argument - -- @treturn boolean whether *a* and *b* are recursively equivalent - eqv = eqv, - - --- Return the equality of the arguments. - -- @param a an argument - -- @param b another argument - -- @return `true` if *a* is *b*, otherwise `false` - eq = function(a, b) - return a == b - end, - - --- Return the inequality of the arguments. - -- @param a an argument - -- @param b another argument - -- @return `false` if *a* is *b*, otherwise `true` - -- @usage - -- --> true - -- local f = require 'std.functional' - -- table.empty(f.filter (f.bind(neq, {6}), std.ielems, {6, 6, 6}) - neq = function(a, b) - return a ~= b - end, - - --- Return whether the arguments are in ascending order. - -- @param a an argument - -- @param b another argument - -- @return `true` if *a* is less then *b*, otherwise `false` - lt = function(a, b) - return a < b - end, - - --- Return whether the arguments are not in descending order. - -- @param a an argument - -- @param b another argument - -- @return `true` if *a* is not greater then *b*, otherwise `false` - lte = function(a, b) - return a <= b - end, - - --- Return whether the arguments are in descending order. - -- @param a an argument - -- @param b another argument - -- @return `true` if *a* is greater then *b*, otherwise `false` - gt = function(a, b) - return a > b - end, - - --- Return whether the arguments are not in ascending order. - -- @param a an argument - -- @param b another argument - -- @return `true` if *a* is not greater then *b*, otherwise `false` - gte = function(a, b) - return a >= b - end, -} diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/functional/tuple.lua b/modules/mixins/dotfiles/config/nvim/lua/std/functional/tuple.lua @@ -1,156 +0,0 @@ ---[[ - Functional programming for Lua 5.1, 5.2, 5.3 & 5.4 - Copyright (C) 2002-2022 std.functional authors -]] ---[[-- - Tuple container. - - An interned, immutable, nil-preserving tuple object. - - Like Lua strings, tuples with the same elements can be quickly compared - with a straight-forward `==` comparison. - - The immutability guarantees only work if you don't change the contents - of tables after adding them to a tuple. Don't do that! - - @module std.functional.tuple -]] - - -local _ENV = require 'std.normalize' { - 'std.functional._base.toqstring', - 'string.format', - 'table.concat', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - --- We maintain a weak table of all distinct Tuples, where each value is --- the tuple object itself, and the associated key is the stringified --- list of elements contained by the tuple, e.g the 0-tuple: --- --- intern[''] = setmetatable({n = 0}, Tuple) --- --- In order to make a tuple immutable, it needs to have a __newindex --- metamethod that diagnoses attempts to insert new elements, which in --- turn means that the actual elements need to be kept in a proxy table --- (because if we stored the first element in the tuple table, then --- __newindex would not fire when the first element was written to). --- Rather that using metamethods to access a wholly separate proxy --- table, we use the proxey table as a key in the tuple object proper --- (it would be impossible to accidentally assign to a unique table --- address key, so __newindex will still work) and use a copy of the --- intern stringified elements key as the associated value there, e.g. --- for the 0-tuple again: --- --- { [{n = 0}] = '' } --- --- This means we have a pleasant property to enable fast stringification --- of any tuple we hold: --- --- proxy_table, stringified_element_list = next(tuple) - - ---- Immutable Tuple container. --- @object Tuple --- @string[opt='Tuple'] _type object name --- @int n number of tuple elements --- @usage --- local Tuple = require 'std.functional.tuple' --- function count(...) --- argtuple = Tuple(...) --- return argtuple.n --- end --- count() --> 0 --- count(nil) --> 1 --- count(false) --> 1 --- count(false, nil, true, nil) --> 4 -local Tuple = { - _type = 'Tuple', - - --- Metamethods - -- @section metamethods - - --- Unpack tuple values between index *i* and *j*, inclusive. - -- @function __call - -- @int[opt=1] i first index to unpack - -- @int[opt=self.n] j last index to unpack - -- @return ... values at indices *i* through *j*, inclusive - -- @usage - -- tup = Tuple(1, 3, 2, 5) - -- --> 3, 2, 5 - -- tup(2) - __call = function(self, i, j) - return unpack(next(self), tonumber(i) or 1, tonumber(j) or self.n) - end, - - __index = function(self, k) - return next(self)[k] - end, - - --- Return the length of this tuple. - -- @function prototype:__len - -- @treturn int number of elements in *tup* - -- @usage - -- -- Only works on Lua 5.2 or newer: - -- #Tuple(nil, 2, nil) --> 3 - -- -- For compatibility with Lua 5.1, use @{operator.len} - -- len(Tuple(nil, 2, nil) - __len = function(self) - return self.n - end, - - --- Prevent mutation of *tup*. - -- @function prototype:__newindex - -- @param k tuple key - -- @param v tuple value - -- @raise cannot change immutable tuple object - __newindex = function(self, k, v) - error('cannot change immutable tuple object', 2) - end, - - --- Return a string representation of *tup* - -- @function prototype:__tostring - -- @treturn string representation of *tup* - -- @usage - -- -- "Tuple('nil', nil, false)" - -- print(Tuple('nil', nil, false)) - __tostring = function(self) - local _, argstr = next(self) - return format('%s(%s)', getmetatable(self)._type, argstr) - end, -} - - --- Maintain a weak functable of all interned tuples. --- @function intern --- @int n number of elements in *t*, including trailing `nil`s --- @tparam table t table of elements --- @treturn table interned *n*-tuple *t* -local intern = setmetatable({}, { - __mode = 'kv', - - __call = function(self, k, t) - if self[k] == nil then - self[k] = setmetatable({[t] = k}, Tuple) - end - return self[k] - end, -}) - - --- Call the value returned from requiring this module with a list of --- elements to get an interned tuple made with those elements. -return function(...) - local n = select('#', ...) - local buf, tup = {}, {n = n, ...} - for i = 1, n do - buf[i] = toqstring(tup[i]) - end - return intern(concat(buf, ', '), tup) -end diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/init.lua b/modules/mixins/dotfiles/config/nvim/lua/std/init.lua @@ -1,389 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Enhanced Lua core functions, and others. - - After requiring this module, simply referencing symbols in the submodule - hierarchy will load the necessary modules on demand. There are no - changes to any global symbols, or monkey patching of core module tables - and metatables. - - @todo Write a style guide(indenting/wrapping, capitalisation, - function and variable names); library functions should call - error, not die; OO vs non-OO(a thorny problem). - @todo pre-compile. - @corefunction std -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck -local compare = _.list.compare -local maxn = _.table.maxn -local split = _.string.split - -_ = nil - - -local _ENV = require 'std.normalize' { - format = 'string.format', - match = 'string.match', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local M - - -local function _assert(expect, fmt, arg1, ...) - local msg =(arg1 ~= nil) and format(fmt, arg1, ...) or fmt or '' - return expect or error(msg, 2) -end - - -local function elems(t) - -- capture pairs iterator initial state - local fn, istate, ctrl = pairs(t) - return function(state, _) - local v - ctrl, v = fn(state, ctrl) - if ctrl then - return v - end - end, istate, true -- wrapped initial state -end - - -local function eval(s) - return load('return ' .. s)() -end - - -local function ielems(t) - -- capture pairs iterator initial state - local fn, istate, ctrl = ipairs(t) - return function(state, _) - local v - ctrl, v = fn(state, ctrl) - if ctrl then - return v - end - end, istate, true -- wrapped initial state -end - - -local function npairs(t) - local m = getmetamethod(t, '__len') - local i, n = 0, m and m(t) or maxn(t) - return function(t) - i = i + 1 - if i <= n then - return i, t[i] - end - end, - t, i -end - - -local function ripairs(t) - local oob = 1 - while t[oob] ~= nil do - oob = oob + 1 - end - - return function(t, n) - n = n - 1 - if n > 0 then - return n, t[n] - end - end, t, oob -end - - -local function rnpairs(t) - local m = getmetamethod(t, '__len') - local oob =(m and m(t) or maxn(t)) + 1 - - return function(t, n) - n = n - 1 - if n > 0 then - return n, t[n] - end - end, t, oob -end - - -local vconvert = setmetatable({ - string = function(x) - return split(x, '%.') - end, - number = function(x) - return {x} - end, - table = function(x) - return x - end, -}, { - __call = function(self, x) - local fn = self[type(x)] or function() - return 0 - end - return fn(x) - end, -}) - - -local function vcompare(a, b) - return compare(vconvert(a), vconvert(b)) -end - - -local function _require(module, min, too_big, pattern) - pattern = pattern or '([%.%d]+)%D*$' - - local s, m = '', require(module) - if type(m) == 'table' then - s = tostring(m.version or m._VERSION or '') - end - local v = match(s, pattern) or 0 - if min then - _assert(vcompare(v, min) >= 0, "require '" .. module .. - "' with at least version " .. min .. ', but found version ' .. v) - end - if too_big then - _assert(vcompare(v, too_big) < 0, "require '" .. module .. - "' with version less than " .. too_big .. ', but found version ' .. v) - end - return m -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.' .. decl, fn) or fn -end - -M = { - --- Release version string. - -- @field version - - - --- Core Functions - -- @section corefuncs - - --- Enhance core `assert` to also allow formatted arguments. - -- @function assert - -- @param expect expression, expected to be *truthy* - -- @string[opt=''] f format string - -- @param[opt] ... arguments to format - -- @return value of *expect*, if *truthy* - -- @usage - -- std.assert(expect == nil, '100% unexpected!') - -- std.assert(expect == 'expect', '%s the unexpected!', expect) - assert = X('assert(?any, ?string, [any...])', _assert), - - --- Evaluate a string as Lua code. - -- @function eval - -- @string s string of Lua code - -- @return result of evaluating `s` - -- @usage - -- --> 2 - -- std.eval 'math.min(2, 10)' - eval = X('eval(string)', eval), - - --- Return named metamethod, if any, otherwise `nil`. - -- The value found at the given key in the metatable of *x* must be a - -- function or have its own `__call` metamethod to qualify as a - -- callable. Any other value found at key *n* will cause this function - -- to return `nil`. - -- @function getmetamethod - -- @param x item to act on - -- @string n name of metamethod to lookup - -- @treturn callable|nil callable metamethod, or `nil` if no metamethod - -- @usage - -- clone = std.getmetamethod(std.object.prototype, '__call') - getmetamethod = X('getmetamethod(?any, string)', getmetamethod), - - - --- Module Functions - -- @section modulefuncs - - --- Enhance core `require` to assert version number compatibility. - -- By default match against the last substring of(dot-delimited) - -- digits in the module version string. - -- @function require - -- @string module module to require - -- @string[opt] min lowest acceptable version - -- @string[opt] too_big lowest version that is too big - -- @string[opt] pattern to match version in `module.version` or - -- `module._VERSION`(default: `'([%.%d]+)%D*$'`) - -- @usage - -- -- posix.version == 'posix library for Lua 5.2 / 32' - -- posix = require('posix', '29') - require = X('require(string, ?string, ?string, ?string)', _require), - - --- Iterator Functions - -- @section iteratorfuncs - - --- An iterator over all values of a table. - -- If *t* has a `__pairs` metamethod, use that to iterate. - -- @function elems - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @return *key*, the previous iteration key - -- @see ielems - -- @see pairs - -- @usage - -- --> foo - -- --> bar - -- --> baz - -- --> 5 - -- std.functional.map(print, std.ielems, {'foo', 'bar', [4]='baz', d=5}) - elems = X('elems(table)', elems), - - --- An iterator over the integer keyed elements of a table. - -- - -- If *t* has a `__len` metamethod, iterate up to the index it - -- returns, otherwise up to the first `nil`. - -- - -- This function does **not** support the Lua 5.2 `__ipairs` metamethod. - -- @function ielems - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @treturn int *index*, the previous iteration index - -- @see elems - -- @see ipairs - -- @usage - -- --> foo - -- --> bar - -- std.functional.map(print, std.ielems, {'foo', 'bar', [4]='baz', d=5}) - ielems = X('ielems(table)', ielems), - - --- An iterator over integer keyed pairs of a sequence. - -- - -- Like Lua 5.1 and 5.3, this iterator returns successive key-value - -- pairs with integer keys starting at 1, up to the first `nil` valued - -- pair. - -- - -- If there is a `_len` metamethod, keep iterating up to and including - -- that element, regardless of any intervening `nil` values. - -- - -- This function does **not** support the Lua 5.2 `__ipairs` metamethod. - -- @function ipairs - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @treturn int *index*, the previous iteration index - -- @see ielems - -- @see npairs - -- @see pairs - -- @usage - -- --> 1 foo - -- --> 2 bar - -- std.functional.map(print, std.ipairs, {'foo', 'bar', [4]='baz', d=5}) - ipairs = X('ipairs(table)', ipairs), - - --- Ordered iterator for integer keyed values. - -- Like ipairs, but does not stop until the __len or maxn of *t*. - -- @function npairs - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table t - -- @see ipairs - -- @see rnpairs - -- @usage - -- --> 1 foo - -- --> 2 bar - -- --> 3 nil - -- --> 4 baz - -- std.functional.map(print, std.npairs, {'foo', 'bar', [4]='baz', d=5}) - npairs = X('npairs(table)', npairs), - - --- Enhance core `pairs` to respect `__pairs` even in Lua 5.1. - -- @function pairs - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @return *key*, the previous iteration key - -- @see elems - -- @see ipairs - -- @usage - -- --> 1 foo - -- --> 2 bar - -- --> 4 baz - -- --> d 5 - -- std.functional.map(print, std.pairs, {'foo', 'bar', [4]='baz', d=5}) - pairs = X('pairs(table)', pairs), - - --- An iterator like ipairs, but in reverse. - -- Apart from the order of the elements returned, this function follows - -- the same rules as @{ipairs} for determining first and last elements. - -- @function ripairs - -- @tparam table t any table - -- @treturn function iterator function - -- @treturn table *t* - -- @treturn number `#t + 1` - -- @see ipairs - -- @see rnpairs - -- @usage - -- --> 2 bar - -- --> 1 foo - -- std.functional.map(print, std.ripairs, {'foo', 'bar', [4]='baz', d=5}) - ripairs = X('ripairs(table)', ripairs), - - --- An iterator like npairs, but in reverse. - -- Apart from the order of the elements returned, this function follows - -- the same rules as @{npairs} for determining first and last elements. - -- @function rnpairs - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table t - -- @see npairs - -- @see ripairs - -- @usage - -- --> 4 baz - -- --> 3 nil - -- --> 2 bar - -- --> 1 foo - -- std.functional.map(print, std.rnpairs, {'foo', 'bar', [4]='baz', d=5}) - rnpairs = X('rnpairs(table)', rnpairs), -} - - ---- Metamethods --- @section Metamethods - -return setmetatable(M, { - --- Lazy loading of stdlib modules. - -- Don't load everything on initial startup, wait until first attempt - -- to access a submodule, and then load it on demand. - -- @function __index - -- @string name submodule name - -- @treturn table|nil the submodule that was loaded to satisfy the missing - -- `name`, otherwise `nil` if nothing was found - -- @usage - -- local std = require 'std' - -- local Object = std.object.prototype - __index = function(self, name) - local ok, t = pcall(require, 'std.' .. name) - if ok then - rawset(self, name, t) - return t - end - end, -}) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/io.lua b/modules/mixins/dotfiles/config/nvim/lua/std/io.lua @@ -1,322 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core io module. - - The module table returned by `std.io` also contains all of the entries from - the core `io` module table. An hygienic way to import this module, then, - is simply to override core `io` locally: - - local io = require 'std.io' - - @corelibrary std.io -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck -local catfile = _.io.catfile -local leaves = _.tree.leaves -local split = _.string.split - -_ = nil - - -local _ENV = require 'std.normalize' { - 'io', - _G = _G, -- FIXME: don't use the host _G as an API! - concat = 'table.concat', - dirsep = 'package.dirsep', - format = 'string.format', - gsub = 'string.gsub', - input = 'io.input', - insert = 'table.insert', - io_type = 'io.type', - merge = 'table.merge', - open = 'io.open', - output = 'io.output', - popen = 'io.popen', - stderr = 'io.stderr', - stdin = 'io.stdin', - write = 'io.write', -} - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local M - - -local function input_handle(h) - if h == nil then - return input() - elseif type(h) == 'string' then - return open(h) - end - return h -end - - -local function slurp(file) - local h, err = input_handle(file) - if h == nil then - argerror('std.io.slurp', 1, err, 2) - end - - if h then - local s = h:read('*a') - h:close() - return s - end -end - - -local function readlines(file) - local h, err = input_handle(file) - if h == nil then - argerror('std.io.readlines', 1, err, 2) - end - - local l = {} - for line in h:lines() do - l[#l + 1] = line - end - h:close() - return l -end - - -local function writelines(h, ...) - if io_type(h) ~= 'file' then - write(h, '\n') - h = output() - end - for v in leaves(ipairs, {...}) do - h:write(v, '\n') - end -end - - -local function process_files(fn) - -- N.B. 'arg' below refers to the global array of command-line args - if len(arg) == 0 then - insert(arg, '-') - end - for i, v in ipairs(arg) do - if v == '-' then - input(stdin) - else - input(v) - end - fn(v, i) - end -end - - -local function warnfmt(msg, ...) - local prefix = '' - local prog = rawget(_G, 'prog') or {} - local opts = rawget(_G, 'opts') or {} - if prog.name then - prefix = prog.name .. ':' - if prog.line then - prefix = prefix .. str(prog.line) .. ':' - end - elseif prog.file then - prefix = prog.file .. ':' - if prog.line then - prefix = prefix .. str(prog.line) .. ':' - end - elseif opts.program then - prefix = opts.program .. ':' - if opts.line then - prefix = prefix .. str(opts.line) .. ':' - end - end - if #prefix > 0 then - prefix = prefix .. ' ' - end - return prefix .. format(msg, ...) -end - - -local function warn(msg, ...) - writelines(stderr, warnfmt(msg, ...)) -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.io.' .. decl, fn) or fn -end - - -M = { - --- Diagnostic functions - -- @section diagnosticfuncs - - --- Die with error. - -- This function uses the same rules to build a message prefix - -- as @{warn}. - -- @function die - -- @string msg format string - -- @param ... additional arguments to plug format string specifiers - -- @see warn - -- @usage - -- die('oh noes!(%s)', tostring(obj)) - die = X('die(string, [any...])', function(...) - error(warnfmt(...), 0) - end), - - --- Give warning with the name of program and file(if any). - -- If there is a global `prog` table, prefix the message with - -- `prog.name` or `prog.file`, and `prog.line` if any. Otherwise - -- if there is a global `opts` table, prefix the message with - -- `opts.program` and `opts.line` if any. - -- @function warn - -- @string msg format string - -- @param ... additional arguments to plug format string specifiers - -- @see die - -- @usage - -- local OptionParser = require 'std.optparse' - -- local parser = OptionParser 'eg 0\nUsage: eg\n' - -- _G.arg, _G.opts = parser:parse(_G.arg) - -- if not _G.opts.keep_going then - -- require 'std.io'.warn 'oh noes!' - -- end - warn = X('warn(string, [any...])', warn), - - - --- Path Functions - -- @section pathfuncs - - --- Concatenate directory names into a path. - -- @function catdir - -- @string ... path components - -- @return path without trailing separator - -- @see catfile - -- @usage - -- dirpath = catdir('', 'absolute', 'directory') - catdir = X('catdir(string...)', function(...) - return(gsub(concat({...}, dirsep), '^$', dirsep)) - end), - - --- Concatenate one or more directories and a filename into a path. - -- @function catfile - -- @string ... path components - -- @treturn string path - -- @see catdir - -- @see splitdir - -- @usage - -- filepath = catfile('relative', 'path', 'filename') - catfile = X('catfile(string...)', catfile), - - --- Remove the last dirsep delimited element from a path. - -- @function dirname - -- @string path file path - -- @treturn string a new path with the last dirsep and following - -- truncated - -- @usage - -- dir = dirname '/base/subdir/filename' - dirname = X('dirname(string)', function(path) - return(gsub(path, catfile('', '[^', ']*$'), '')) - end), - - --- Split a directory path into components. - -- Empty components are retained: the root directory becomes `{'', ''}`. - -- @function splitdir - -- @param path path - -- @return list of path components - -- @see catdir - -- @usage - -- dir_components = splitdir(filepath) - splitdir = X('splitdir(string)', function(path) - return split(path, dirsep) - end), - - - --- IO Functions - -- @section iofuncs - - --- Process files specified on the command-line. - -- Each filename is made the default input source with `io.input`, and - -- then the filename and argument number are passed to the callback - -- function. In list of filenames, `-` means `io.stdin`. If no - -- filenames were given, behave as if a single `-` was passed. - -- @todo Make the file list an argument to the function. - -- @function process_files - -- @tparam fileprocessor fn function called for each file argument - -- @usage - -- #! /usr/bin/env lua - -- -- minimal cat command - -- local io = require 'std.io' - -- io.process_files(function() io.write(io.slurp()) end) - process_files = X('process_files(function)', process_files), - - --- Read a file or file handle into a list of lines. - -- The lines in the returned list are not `\n` terminated. - -- @function readlines - -- @tparam[opt=io.input()] file|string file file handle or name; - -- if file is a file handle, that file is closed after reading - -- @treturn list lines - -- @usage - -- list = readlines '/etc/passwd' - readlines = X('readlines(?file|string)', readlines), - - --- Perform a shell command and return its output. - -- @function shell - -- @string c command - -- @treturn string output, or nil if error - -- @see os.execute - -- @usage - -- users = shell [[cat /etc/passwd | awk -F: '{print $1;}']] - shell = X('shell(string)', function(c) return slurp(popen(c)) end), - - --- Slurp a file handle. - -- @function slurp - -- @tparam[opt=io.input()] file|string file file handle or name; - -- if file is a file handle, that file is closed after reading - -- @return contents of file or handle, or nil if error - -- @see process_files - -- @usage - -- contents = slurp(filename) - slurp = X('slurp(?file|string)', slurp), - - --- Write values adding a newline after each. - -- @function writelines - -- @tparam[opt=io.output()] file h open writable file handle; - -- the file is **not** closed after writing - -- @tparam string|number ... values to write(as for write) - -- @usage - -- writelines(io.stdout, 'first line', 'next line') - writelines = X('writelines(?file|string|number, [string|number...])', writelines), -} - - -return merge(io, M) - - - ---- Types --- @section Types - ---- Signature of @{process_files} callback function. --- @function fileprocessor --- @string filename filename --- @int i argument number of *filename* --- @usage --- local fileprocessor = function(filename, i) --- io.write(tostring(i) .. ':\n===\n' .. io.slurp(filename) .. '\n') --- end --- io.process_files(fileprocessor) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/math.lua b/modules/mixins/dotfiles/config/nvim/lua/std/math.lua @@ -1,92 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core math module. - - The module table returned by `std.math` also contains all of the entries from - the core math table. An hygienic way to import this module, then, is simply - to override the core `math` locally: - - local math = require 'std.math' - - @corelibrary std.math -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck - -_ = nil - - -local _ENV = require 'std.normalize' { - 'math', - merge = 'table.merge', -} - - - ---[[ ================= ]]-- ---[[ Implementatation. ]]-- ---[[ ================= ]]-- - - -local M - - -local _floor = math.floor - -local function floor(n, p) - if(p or 0) == 0 then - return _floor(n) - end - local e = 10 ^ p - return _floor(n * e) / e -end - - -local function round(n, p) - local e = 10 ^(p or 0) - return _floor(n * e + 0.5) / e -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.math.' .. decl, fn) or fn -end - - -M = { - --- Core Functions - -- @section corefuncs - - --- Extend `math.floor` to take the number of decimal places. - -- @function floor - -- @number n number - -- @int[opt=0] p number of decimal places to truncate to - -- @treturn number `n` truncated to `p` decimal places - -- @usage - -- tenths = floor(magnitude, 1) - floor = X('floor(number, ?int)', floor), - - --- Round a number to a given number of decimal places. - -- @function round - -- @number n number - -- @int[opt=0] p number of decimal places to round to - -- @treturn number `n` rounded to `p` decimal places - -- @usage - -- roughly = round(exactly, 2) - round = X('round(number, ?int)', round), -} - - -return merge(math, M) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/normalize/init.lua b/modules/mixins/dotfiles/config/nvim/lua/std/normalize/init.lua @@ -1,1342 +0,0 @@ ---[[ - Normalized Lua API for Lua 5.1, 5.2, 5.3 & 5.4 - Copyright (C) 2002-2023 std.normalize authors -]] ---[[-- - Normalize API differences between supported Lua implementations. - - Respecting the values set in the `std._debug` settings module, inject - deterministic identically behaving cross-implementation low-level - functions into the callers environment. - - Writing Lua libraries that target several Lua implementations can be a - frustrating exercise in working around lots of small differences in APIs - and semantics they share (or rename, or omit). _normalize_ provides the - means to simply access deterministic implementations of those APIs that - have the the same semantics across all supported host Lua - implementations. Each function is as thin and fast an implementation as - is possible within that host Lua environment, evaluating to the Lua C - implementation with no overhead where host semantics allow. - - The core of this module is to transparently set the environment up with - a single API (as opposed to requiring caching functions from a module - table into module locals): - - local _ENV = require 'std.normalize' { - 'package', - 'std.prototype', - strict = 'std.strict', - } - - It is not yet complete, and in contrast to the kepler project - lua-compat libraries, neither does it attempt to provide you with as - nearly compatible an API as is possible relative to some specific Lua - implementation - rather it provides a variation of the "lowest common - denominator" that can be implemented relatively efficiently in the - supported Lua implementations, all in pure Lua. - - At the moment, only the functionality used by stdlib is implemented. - - @module std.normalize -]] - - ---[[ ====================== ]]-- ---[[ Load optional modules. ]]-- ---[[ ====================== ]]-- - - -local _debug = (function() - local ok, r = pcall(require, 'std._debug') - if not ok then - r = setmetatable({ - -- If this module was required, but there's no std._debug, safe to - -- assume we do want runtime argchecks! - argcheck = true, - -- Similarly, if std.strict is available, but there's no _std.debug, - -- then apply strict global symbol checks to this module! - strict = true, - }, { - __call = function(self, x) - self.argscheck = (x ~= false) - end, - }) - end - - return r -end)() - - -local strict = (function() - local setfenv = rawget(_G, 'setfenv') or function() end - - -- No strict global symbol checks with no std.strict module, even - -- if we found std._debug and requested that! - local r = function(env, level) - setfenv(1 + (level or 1), env) - return env - end - - if _debug.strict then - -- Specify `.init` submodule to make sure we only accept - -- lua-stdlib/strict, and not the old strict module from - -- lua-stdlib/lua-stdlib. - local ok, m = pcall(require, 'std.strict.init') - if ok then - r = m - end - end - return r -end)() - - -local typecheck = (function() - local format = string.format - - local ok, r = pcall(require, 'typecheck') - if ok then - return r - end - - return { - ARGCHECK_FRAME = 0, - - -- Return `inner` untouched, for no runtime overhead! - argscheck = function(decl, inner) - return inner or setmetatable({}, { - __concat = function(_, inner) - return inner - end, - }) - end, - - argerror = function(name, i, extramsg, level) - level = level or 1 - local s = format("bad argument #%d to '%s'", i, name) - if extramsg ~= nil then - s = s .. ' (' .. extramsg .. ')' - end - error(s, level > 0 and level + 2 or 0) - end, - } -end)() - - -local _ENV = strict(_G) - - -local ARGCHECK_FRAME = typecheck.ARGCHECK_FRAME -local argerror = typecheck.argerror -local argscheck = typecheck.argscheck -local concat = table.concat -local config = package.config -local debug_getfenv = debug.getfenv or false -local debug_getinfo = debug.getinfo -local debug_getupvalue = debug.getupvalue -local debug_setfenv = debug.setfenv or false -local debug_setupvalue = debug.setupvalue -local debug_upvaluejoin = debug.upvaluejoin -local exit = os.exit -local format = string.format -local getfenv = rawget(_G, 'getfenv') or false -local gmatch = string.gmatch -local gsub = string.gsub -local loadstring = rawget(_G, 'loadstring') or load -local match = string.match -local open = io.open -local remove = table.remove -local searchpath = package.searchpath or false -local setfenv = rawget(_G, 'setfenv') or false -local sort = table.sort -local unpack = table.unpack or unpack -local upper = string.upper - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - --- At this point, only the locals imported above are visible (even in --- Lua 5.1). If 'std.strict' is available, we'll also get a runtime --- error if any of the code below tries to use an undeclared variable. - - -local dirsep, pathsep, pathmark, execdir, igmark = - match(config, '^([^\n]+)\n([^\n]+)\n([^\n]+)\n([^\n]+)\n([^\n]+)') - - -local function callable(x) - -- Careful here! - -- Most versions of Lua don't recurse functables, so make sure you - -- always put a real function in __call metamethods. Consequently, - -- no reason to recurse here. - -- func=function() print 'called' end - -- func() --> 'called' - -- functable=setmetatable({}, {__call=func}) - -- functable() --> 'called' - -- nested=setmetatable({}, {__call=function(self, ...) return functable(...)end}) - -- nested() -> 'called' - -- notnested=setmetatable({}, {__call=functable}) - -- notnested() - -- --> stdin:1: attempt to call global 'nested' (a table value) - -- --> stack traceback: - -- --> stdin:1: in main chunk - -- --> [C]: in ? - if type(x) == 'function' or (getmetatable(x) or {}).__call then - return x - end -end - - -local tointeger = (function(f) - if f == nil then - -- No host tointeger implementationm use our own. - local floor = math.floor - return function(x) - if type(x) == 'number' and x - floor(x) == 0.0 then - return x - end - end - - elseif f '1' ~= nil then - -- Don't perform implicit string-to-number conversion! - return function(x) - if type(x) == 'number' then - return f(x) - end - end - end - - -- Host tointeger is good! - return f -end)(math.tointeger) - - --- It's hard to test at require-time whether the host `os.exit` handles --- boolean argument properly (ostensibly to defer to it in that case). --- We're shutting down anyway, so sacrifice a bit of speed for timely --- diagnosis of float and nil valued argument (with the argscheck --- annotation, later in the file), since that probably indicates a bug --- in your code! -local _exit = exit -local function exit(...) - local n, status = select('#', ...), ... - if tointeger(n) == 0 or status == true then - _exit(0) - elseif status == false then - _exit(1) - end - _exit(status) -end - - -local normalize_getfenv -if debug_getfenv then - - normalize_getfenv = function(fn) - local n = tointeger(fn or 1) - if n then - if n > 0 then - -- Adjust for this function's stack frame, if fn is non-zero. - n = n + 1 + ARGCHECK_FRAME - end - - -- Return an additional nil result to defeat tail call elimination - -- which would remove a stack frame and break numeric *fn* count. - return getfenv(n), nil - end - - if type(fn) ~= 'function' then - -- Unwrap functors: - -- No need to recurse because Lua doesn't support nested functors. - -- __call can only (sensibly) be a function, so no need to adjust - -- stack frame offset either. - fn =(getmetatable(fn) or {}).__call or fn - end - - -- In Lua 5.1, only debug.getfenv works on C functions; but it - -- does not work on stack counts. - return debug_getfenv(fn) - end - -else - - -- Thanks to http://lua-users.org/lists/lua-l/2010-06/msg00313.html - normalize_getfenv = function(fn) - if fn == 0 then - return _G - end - local n = tointeger(fn or 1) - if n then - fn = debug_getinfo(n + 1 + ARGCHECK_FRAME, 'f').func - elseif type(fn) ~= 'function' then - fn = (getmetatable(fn) or {}).__call or fn - end - - local name, env - local up = 0 - repeat - up = up + 1 - name, env = debug_getupvalue(fn, up) - until name == '_ENV' or name == nil - return env - end - -end - - -local function getmetamethod(x, n) - return callable((getmetatable(x) or {})[n]) -end - - -local function rawlen(x) - -- Lua 5.1 does not implement rawlen, and while # operator ignores - -- __len metamethod, `nil` in sequence is handled inconsistently. - if type(x) ~= 'table' then - return #x - end - - local n = #x - for i = 1, n do - if x[i] == nil then - return i -1 - end - end - return n -end - - -local function len(x) - return (getmetamethod(x, '__len') or rawlen)(x) -end - - -local function ipairs(l) - if getmetamethod(l, '__len') then - -- Use a closure to capture len metamethod result if necessary. - local n = len(l) - return function(l, i) - i = i + 1 - if i <= n then - return i, l[i] - end - end, l, 0 - end - - -- ...otherwise, find the last item as we go without calling `len()`. - return function(l, i) - i = i + 1 - if l[i] ~= nil then - return i, l[i] - end - end, l, 0 -end - - -local load = (function(ok) - if not ok then - return function(...) - if type(...) == 'string' then - return loadstring(...) - end - return _G.load(...) - end - end - - return _G.load -end)(pcall(load, '_=1')) - - -local function normalize_load(chunk, chunkname) - local m = getmetamethod(chunk, '__call') - if m then - chunk = m - elseif getmetamethod(chunk, '__tostring') then - chunk = tostring(chunk) - end - if getmetamethod(chunkname, '__tostring') then - chunkname = tostring(chunkname) - end - return load(chunk, chunkname) -end - - -local function merge(t, r) - r = r or {} - for k, v in next, t do - r[k] = r[k] or v - end - return r -end - - -local pack = (function(f) - local pack_mt = { - __len = function(self) - return self.n - end, - } - - local pack_fn = f or function(...) - return {n=select('#', ...), ...} - end - - return function(...) - return setmetatable(pack_fn(...), pack_mt) - end -end)(rawget(_G, "pack")) - - -local pairs = (function(b) - if b then - -- Add support for __pairs when missing. - return function (t) - return (getmetamethod(t, '__pairs') or pairs)(t) - end - end - - return _G.pairs -end)(not not pairs(setmetatable({},{__pairs=function() return false end}))) - - -local function keys(t) - local r = {} - for k in pairs(t) do - r[#r + 1] = k - end - return r -end - - -local pathmatch_patt = '[^' .. pathsep .. ']+' - -local searchpath = searchpath or function(name, path, sep, rep) - name = gsub(name, sep or '%.', rep or dirsep) - - local errbuf = {} - for template in gmatch(path, pathmatch_patt) do - local filename = gsub(template, pathmark, name) - local fh = open(filename, 'r') - if fh then - fh:close() - return filename - end - errbuf[#errbuf + 1] = "\tno file '" .. filename .. "'" - end - return nil, concat(errbuf, '\n') -end - - -local normalize_setfenv -if debug_setfenv then - - normalize_setfenv = function(fn, env) - local n = tointeger(fn or 1) - if n then - if n > 0 then - n = n + 1 + ARGCHECK_FRAME - end - return setfenv(n, env), nil - end - if type(fn) ~= 'function' then - fn =(getmetatable(fn) or {}).__call or fn - end - return debug_setfenv(fn, env) - end - -else - - -- Thanks to http://lua-users.org/lists/lua-l/2010-06/msg00313.html - normalize_setfenv = function(fn, env) - local n = tointeger(fn or 1) - if n then - if n > 0 then - n = n + 1 + ARGCHECK_FRAME - end - fn = debug_getinfo(n, 'f').func - elseif type(fn) ~= 'function' then - fn =(getmetatable(fn) or {}).__call or fn - end - - local up, name = 0 - repeat - up = up + 1 - name = debug_getupvalue(fn, up) - until name == '_ENV' or name == nil - if name then - debug_upvaluejoin(fn, up, function() return name end, 1) - debug_setupvalue(fn, up, env) - end - return n ~= 0 and fn or nil - end - -end - - -local shallow_copy = merge - - -local function render(x, vfns, roots) - if vfns.term(x) then - return vfns.elem(x) - end - - roots = roots or {} - - local function stop_roots(x) - return roots[x] or render(x, vfns, shallow_copy(roots)) - end - - local buf, pair, sep = {vfns.open(x)}, vfns.pair, vfns.sep - roots[x] = vfns.elem(x) -- recursion protection - - local seqp, kp, vp -- proper sequence?, previous key and value - local keylist = vfns.sort(keys(x)) - for i, k in ipairs(keylist) do - local v = x[k] - buf[#buf + 1] = sep(x, kp, vp, k, v, seqp) -- buffer << separator - if k == 1 then - seqp = true - else - seqp = seqp and type(kp) == 'number' and k == kp + 1 - end - buf[#buf + 1] = pair(x, kp, vp, k, v, stop_roots(k), stop_roots(v), seqp) - kp, vp = k, v - end - buf[#buf + 1] = sep(x, kp, vp) -- buffer << trailing separator - buf[#buf + 1] = vfns.close(x) -- buffer << table close - return concat(buf) -- stringify buffer -end - - -local function always(x) - return function(...) return x end -end - - -local function keysort(a, b) - if type(a) == 'number' then - return type(b) ~= 'number' or a < b - else - return type(b) ~= 'number' and tostring(a) < tostring(b) - end -end - - -local strvtable = { - open = always '{', - close = always '}', - - elem = setmetatable({ - ['\a'] = [[\a]], - ['\b'] = [[\b]], - ['\t'] = [[\t]], - ['\n'] = [[\n]], - ['\v'] = [[\v]], - ['\f'] = [[\f]], - ['\r'] = [[\r]], - ['\\'] = [[\\]], - }, { - __call = function(map, x) - return gsub(tostring(x), '[\a\b\t\n\v\f\r]', function(c) - return map[c] - end) - end, - }), - - pair = function(x, kp, vp, k, v, kstr, vstr, seqp) - if seqp then - return vstr - end - return kstr .. '=' .. vstr - end, - - sep = function(x, kp, vp, k, v, seqp) - if kp == nil or k == nil then - return '' - elseif seqp and type(kp) == 'number' and k ~= kp + 1 then - return '; ' - end - return ', ' - end, - - sort = function(keys) - sort(keys, keysort) - return keys - end, - - term = function(x) - return type(x) ~= 'table' or getmetamethod(x, '__tostring') - end, -} - - -local function str(x) - return render(x, strvtable) -end - - -local function math_type(x) - if type(x) ~= 'number' then - return nil - end - return tointeger(x) and 'integer' or 'float' -end - - -local _unpack = unpack -local function unpack(t, i, j) - return _unpack(t, tointeger(i) or 1, tointeger(j) or len(t)) -end - - -do - local have_xpcall_args = false - local function catch(arg) have_xpcall_args = arg end - xpcall(catch, function() end, true) - - if not have_xpcall_args then - local _xpcall = xpcall - xpcall = function(fn, errh, ...) - local argu = pack(...) - return _xpcall(function() - return fn(unpack(argu, 1, argu.n)) - end, errh) - end - end -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local F = { - _VERSION = _G._VERSION, - arg = _G.arg, - - --- Raise a bad argument error. - -- Equivalent to luaL_argerror in the Lua C API. This function does not - -- return. The `level` argument behaves just like the core `error` - -- function. - -- @function argerror - -- @string name function to callout in error message - -- @int i argument number - -- @string[opt] extramsg additional text to append to message inside - -- parentheses - -- @int[opt=1] level call stack level to blame for the error - -- @usage - -- local function slurp(file) - -- local h, err = input_handle(file) - -- if h == nil then - -- argerror('std.io.slurp', 1, err, 2) - -- end - -- ... - argerror = argerror, - - assert = _G.assert, - collectgarbage = _G.collectgarbage, - dofile = _G.dofile, - error = _G.error, - - --- Get a function or functor environment. - -- - -- This version of getfenv works on all supported Lua versions, and - -- knows how to unwrap functors (table's with a function valued - -- `__call` metamethod). - -- @function getfenv - -- @tparam[opt=1] function|int fn stack level, C or Lua function or - -- functor to act on - -- @treturn table the execution environment of *fn* - -- @usage - -- callers_environment = getfenv(1) - getfenv = argscheck 'getfenv([callable|integer])' - .. normalize_getfenv, - - --- Return named metamethod, if callable, otherwise `nil`. - -- @function getmetamethod - -- @param x item to act on - -- @string n name of metamethod to look up - -- @treturn function|nil metamethod function, or `nil` if no - -- metamethod - -- @usage - -- normalize = getmetamethod(require 'std.normalize', '__call') - getmetamethod = argscheck 'getmetamethod(?any, string)' - .. getmetamethod, - - getmetatable = _G.getmetatable, - - --- Iterate over elements of a sequence, until the first `nil` value. - -- - -- Returns successive key-value pairs with integer keys starting at 1, - -- up to the index returned by the `__len` metamethod if any, or else - -- up to last non-`nil` value. - -- - -- Unlike Lua 5.1, any `__index` metamethod is respected. - -- - -- Unlike Lua 5.2+, any `__ipairs` metamethod is **ignored**! - -- @function ipairs - -- @tparam table t table to iterate on - -- @treturn function iterator function - -- @treturn table *t* the table being iterated over - -- @treturn int the previous iteration index - -- @usage - -- t, u = {}, {} - -- for i, v in ipairs {1, 2, nil, 4} do t[i] = v end - -- assert(len(t) == 2) - -- - -- for i, v in ipairs(pack(1, 2, nil, 4)) do u[i] = v end - -- assert(len(u) == 4) - ipairs = argscheck 'ipairs(table)' - .. ipairs, - - --- Deterministic, functional version of core Lua `#` operator. - -- - -- Respects `__len` metamethod (like Lua 5.2+), or else if there is - -- a `__tostring` metamethod return the length of the string it - -- returns. Otherwise, always return one less than the lowest - -- integer index with a `nil` value in *x*, where the `#` operator - -- implementation might return the size of the array part of a table. - -- @function len - -- @param x item to act on - -- @treturn int the length of *x* - -- @usage - -- x = {1, 2, 3, nil, 5} - -- --> 5 3 - -- print(#x, len(x)) - len = argscheck 'len(string|table)' - .. len, - - --- Load a string or a function, just like Lua 5.2+. - -- @function load - -- @tparam string|function ld chunk to load - -- @string source name of the source of *ld* - -- @treturn function a Lua function to execute *ld* in global scope. - -- @usage - -- assert(load 'print "woo"')() - load = argscheck 'load(callable|string, [string])' - .. normalize_load, - - loadfile = _G.loadfile, - next = _G.next, - - --- Return a list of given arguments, with field `n` set to the length. - -- - -- The returned table also has a `__len` metamethod that returns `n`, so - -- `ipairs` and `unpack` behave sanely when there are `nil` valued elements. - -- @function pack - -- @param ... tuple to act on - -- @treturn table packed list of *...* values, with field `n` set to - -- number of tuple elements (including any explicit `nil` elements) - -- @see unpack - -- @usage - -- --> 5 - -- len(pack(nil, 2, 5, nil, nil)) - pack = pack, - - --- Like Lua `pairs` iterator, but respect `__pairs` even in Lua 5.1. - -- @function pairs - -- @tparam table t table to act on - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @return the previous iteration key - -- @usage - -- for k, v in pairs {'a', b='c', foo=42} do process(k, v) end - pairs = argscheck 'pairs(table)' - .. pairs, - - pcall = _G.pcall, - print = _G.print, - rawequal = _G.rawequal, - rawget = _G.rawget, - - --- Length of a string or table object without using any metamethod. - -- @function rawlen - -- @tparam string|table x object to act on - -- @treturn int raw length of *x* - -- @usage - -- --> 0 - -- rawlen(setmetatable({}, {__len=function() return 42})) - rawlen = argscheck 'rawlen(string|table)' - .. rawlen, - - rawset = _G.rawset, - select = _G.select, - - --- Set a function or functor environment. - -- - -- This version of setfenv works on all supported Lua versions, and - -- knows how to unwrap functors. - -- @function setfenv - -- @tparam function|int fn stack level, C or Lua function or functor - -- to act on - -- @tparam table env new execution environment for *fn* - -- @treturn function function acted upon - -- @usage - -- function clearenv(fn) return setfenv(fn, {}) end - setfenv = argscheck 'setfenv(integer|callable, table)' - .. normalize_setfenv, - - setmetatable = _G.setmetatable, - - --- Return a compact stringified representation of argument. - -- @function str - -- @param x item to act on - -- @treturn string compact string representing *x* - -- @usage - -- -- {baz,5,foo=bar} - -- print(str{foo='bar','baz', 5}) - str = str, - - tonumber = _G.tonumber, - tostring = _G.tostring, - type = _G.type, - - --- Either `table.unpack` in newer-, or `unpack` in older Lua implementations. - -- @function unpack - -- @tparam table t table to act on - -- @int[opt=1] i first index to unpack - -- @int[opt=len(t)] j last index to unpack - -- @return ... values of numeric indices of *t* - -- @see pack - -- @usage - -- local a, b, c = unpack(pack(nil, 2, nil)) - -- assert(a == nil and b == 2 and c == nil) - unpack = argscheck'unpack(table, [?integer], [integer])' - .. unpack, - - --- Support arguments to a protected function call, even on Lua 5.1. - -- @function xpcall - -- @tparam function f protect this function call - -- @tparam function errh error object handler callback if *f* raises - -- an error - -- @param ... arguments to pass to *f* - -- @treturn[1] boolean `false` when `f(...)` raised an error - -- @treturn[1] string error message - -- @treturn[2] boolean `true` when `f(...)` succeeded - -- @return ... all return values from *f* follow - -- @usage - -- -- Use errh to get a backtrack after curses exits abnormally - -- xpcall(main, errh, arg, opt) - xpcall = argscheck 'xpcall(callable, callable, [?any...])' - .. xpcall, -} - -local G = { - coroutine = { - create = _G.coroutine.create, - resume = _G.coroutine.resume, - running = _G.coroutine.running, - status = _G.coroutine.status, - wrap = _G.coroutine.wrap, - yield = _G.coroutine.yield, - }, - debug = { - debug = _G.debug.debug, - gethook = _G.debug.gethook, - getinfo = _G.debug.getinfo, - getlocal = _G.debug.getlocal, - getmetatable = _G.debug.getmetatable, - getregistry = _G.debug.getregistry, - getupvalue = _G.debug.getupvalue, - getuservalue = _G.debug.getuservalue, - sethook = _G.debug.sethook, - setmetatable = _G.debug.setmetatable, - setupvalue = _G.debug.setupvalue, - setuservalue = _G.debug.setuservalue, - traceback = _G.debug.traceback, - upvalueid = _G.debug.upvalueid, - upvaluejoin = _G.debug.upvaluejoin, - }, - io = { - close = _G.io.close, - flush = _G.io.flush, - input = _G.io.input, - lines = _G.io.lines, - open = _G.io.open, - output = _G.io.output, - popen = _G.io.popen, - read = _G.io.read, - stderr = _G.io.stderr, - stdin = _G.io.stdin, - stdout = _G.io.stdout, - tmpfile = _G.io.tmpfile, - type = _G.io.type, - write = _G.io.write, - }, - math = { - abs = _G.math.abs, - acos = _G.math.acos, - asin = _G.math.asin, - atan = _G.math.atan, - ceil = _G.math.ceil, - cos = _G.math.cos, - deg = _G.math.deg, - exp = _G.math.exp, - floor = _G.math.floor, - fmod = _G.math.fmod, - huge = _G.math.huge, - log = _G.math.log, - max = _G.math.max, - min = _G.math.min, - modf = _G.math.modf, - pi = _G.math.pi, - rad = _G.math.rad, - random = _G.math.random, - randomseed = _G.math.randomseed, - sin = _G.math.sin, - sqrt = _G.math.sqrt, - tan = _G.math.tan, - - --- Convert to an integer and return if possible, otherwise `nil`. - -- @function math.tointeger - -- @param x object to act on - -- @treturn[1] integer *x* converted to an integer if possible - -- @return[2] `nil` otherwise - tointeger = argscheck 'math.tointeger(?any)' - .. tointeger, - - --- Return 'integer', 'float' or `nil` according to argument type. - -- - -- To ensure the same behaviour on all host Lua implementations, - -- this function returns 'float' for integer-equivalent floating - -- values, even on Lua 5.3. - -- @function math.type - -- @param x object to act on - -- @treturn[1] string 'integer', if *x* is a whole number - -- @treturn[2] string 'float', for other numbers - -- @return[3] `nil` otherwise - type = argscheck 'math.type(?any)' - .. math_type, - }, - os = { - clock = _G.os.clock, - date = _G.os.date, - difftime = _G.os.difftime, - execute = _G.os.execute, - - --- Exit the program. - -- @function os.exit - -- @tparam bool|number[opt=true] status report back to parent process - -- @usage - -- exit(len(records.processed) > 0) - exit = argscheck 'os.exit([boolean|integer])' - .. exit, - - getenv = _G.os.getenv, - remove = _G.os.remove, - rename = _G.os.rename, - setlocale = _G.os.setlocale, - time = _G.os.time, - tmpname = _G.os.tmpname, - }, - package = { - config = _G.package.config, - cpath = _G.package.cpath, - - --- Package module constants for `package.config` substrings. - -- @table package - -- @string dirsep directory separator in path elements - -- @string execdir replaced by the executable's directory in a path - -- @string igmark ignore everything before this when building - -- `luaopen_` function name - -- @string pathmark mark substitution points in a path template - -- @string pathsep element separator in a path template - dirsep = dirsep, - execdir = execdir, - igmark = igmark, - pathmark = pathmark, - pathsep = pathsep, - - loadlib = _G.package.loadlib, - path = _G.package.path, - preload = _G.package.preload, - searchers = _G.package.searchers or _G.package.loaders, - - --- Searches for a named file in a given path. - -- - -- For each `package.pathsep` delimited template in the given path, - -- search for an readable file made by first substituting for *sep* - -- with `package.dirsep`, and then replacing any - -- `package.pathmark` with the result. The first such file, if any - -- is returned. - -- @function package.searchpath - -- @string name name of search file - -- @string path `package.pathsep` delimited list of full path templates - -- @string[opt='.'] sep *name* component separator - -- @string[opt=`package.dirsep`] rep *sep* replacement in template - -- @treturn[1] string first template substitution that names a file - -- that can be opened in read mode - -- @return[2] `nil` - -- @treturn[2] string error message listing all failed paths - searchpath = argscheck( - 'package.searchpath(string, string, [?string], [string])' - ) .. searchpath, - }, - string = { - byte = _G.string.byte, - char = _G.string.char, - dump = _G.string.dump, - find = _G.string.find, - format = _G.string.format, - gmatch = _G.string.gmatch, - gsub = _G.string.gsub, - lower = _G.string.lower, - match = _G.string.match, - rep = _G.string.rep, - - --- Low-level recursive data to string rendering. - -- @function string.render - -- @param x data to be renedered - -- @tparam RenderFns vfns table of virtual functions to control rendering - -- @tparam[opt] table roots used internally for cycle detection - -- @treturn string a text recursive rendering of *x* using *vfns* - -- @usage - -- function printarray(x) - -- return render(x, arrayvfns) - -- end - render = argscheck 'string.render(?any, table, [table])' - .. render, - - reverse = _G.string.reverse, - sub = _G.string.sub, - upper = _G.string.upper, - }, - table = { - concat = _G.table.concat, - insert = _G.table.insert, - - --- Return an unordered list of all keys in a table. - -- @function table.keys - -- @tparam table t table to operate on - -- @treturn table an unorderd list of keys in *t* - -- @usage - -- --> {'key2', 1, 42, 2, 'key1'} - -- keys{'a', 'b', key1=1, key2=2, [42]=3} - keys = argscheck 'table.keys(table)' - .. keys, - - --- Destructively merge keys and values from one table into another. - -- @function table.merge - -- @tparam table t take fields from this table - -- @tparam[opt={}] table u and copy them into here, unless they are set already - -- @treturn table *u* - -- @usage - -- --> {'a', 'b', d='d'} - -- merge({'a', 'b'}, {'c', d='d'}) - merge = argscheck 'table.merge(table, [table])' - .. merge, - - remove = _G.table.remove, - sort = _G.table.sort, - }, -} -F._G = G -G.package.loaded = { - _G = G, - coroutine = G.coroutine, - debug = G.debug, - io = G.io, - math = G.math, - os = G.os, - package = G.package, - string = G.string, - table = G.table, -} -for k, v in next, _G.package.loaded do - G.package.loaded[k] = G.package.loaded[k] or v -end -F.require = function(modname) - return G.package.loaded[modname] or _G.require(modname) -end -for k, v in next, F do - G[k] = G[k] or v -end - - -local function split(s, matching) - local r = {} - gsub(s, matching, function(segment) - r[#r + 1] = segment - end) - return r -end - - --- Dereference table *env* with *keylist* making missing subtables as we go. --- The last element of *keylist* is assumed to be the final key at which --- some value will be loaded, and is not followed, but is the second return --- value. --- @tparam table env environment table to start from --- @tparam table keylist a list of subtables to recursively walk from *env* --- @treturn table innermost table having followed *keylist* from *env* --- @treturn string the last element of *keylist* -local function mksubtables(env, keylist) - while #keylist > 1 do - local subkey = remove(keylist, 1) - env[subkey] = env[subkey] or {} - env = env[subkey] - end - keylist = remove(keylist, 1) - return env, keylist -end - - --- Return dot-delimited segments of elements of t between indexes i and j. --- @tparam table t a list of segments --- @int i first element to return --- @int j last element to return --- @treturn string selected segments of *t* concatenated with '.'s between -local function slice(t, i, j) - return concat({unpack(t, i, j)}, '.') -end - - --- Convert a string into a loadable module, optionally followed by table keys. --- Initially with the whole of *spec* as a module name, then splitting *spec* --- at each dot from right to left, search for a module named after the left --- half and containing nested keys named after the right half, and return --- that. --- @string spec dot delimited symbol name to import --- @int level call depth for error message stack traces --- @return value of a module, after dereferencing optional following --- table keys -local function stringimport(spec, level) - local v = split(spec, '[^%.]+') - local vlen, err = #v, {} - - for i = vlen, 1, -1 do - local module, j = slice(v, 1, i), i + 1 - local ok, pkg = pcall(G.require, module) - if not ok then - err[#err + 1] = pkg - else - while pkg ~= nil and j <= vlen do - local subkey = v[j] - pkg, j = pkg[subkey], j + 1 - end - if pkg == nil then - err[#err + 1] = format( - "\tno entry for '%s' in module '%s'", slice(v, i + 1, vlen), module - ) - else - return pkg - end - end - end - error(concat(err, '\n'), level + 1) -end - - --- Import value into name key of env table. --- String values are replaced by the equivalent symbol they name in the --- normalized module table, except that strings assigned to ALLCAPS names --- are treated as string constants and not looked up as module symbols. --- @tparam table env environment table --- @string name key to index into *env* --- @param value value to store at *name* in *env* --- @int level call depth for error message stack traces --- @treturn table modified *env* -local function import(env, name, value, level) - local i = tointeger(name) - if i and type(value) == 'string' then - name = match(value, '[^%.]+$') - if name == nil then - error( - "could not infer name from module '" .. value .. "' at #" .. i, - level + 1 - ) - end - end - - local dst, k = mksubtables(env, split(name, '[^%.]+')) - if type(value) == 'string' and (i or upper(name) ~= name) then - value = stringimport(value, level + 1) - end - dst[k] = value - return env -end - - --- Replace host Lua functions with normalized equivalents. --- @tparam table userenv user's lexical environment table --- @treturn table *userenv* with normalized functions -local function normalize(userenv, level) - -- Top level functions are always available. - local env = shallow_copy(F) - - -- Everything else must be requested by name. - for name, value in next, userenv do - env = import(env, name, value, level + 1) - end - - return env -end - - -return setmetatable(G, { - --- Metamethods - -- @section metamethods - - --- Normalize caller's lexical environment. - -- - -- Using 'std.strict' when available and selected, otherwise a (Lua 5.1 - -- compatible) function to set the given environment. - -- - -- With an empty table argument, the core (not-table) normalize - -- functions are loaded into the callers environment. For consistent - -- behaviour between supported host Lua implementations, the result - -- must always be assigned back to `_ENV`. Additional core modules - -- must be named to be loaded at all (i.e. no 'debug' table unless it - -- is explicitly listed in the argument table). - -- - -- Additionally, external modules are loaded using `require`, with `.` - -- separators in the module name translated to nested tables in the - -- module environment. For example 'std.prototype' in the usage below - -- will add to the environment table the equivalent of: - -- - -- local prototype = require 'std.prototype' - -- - -- Alternatively, you can assign a loaded module symbol to a specific - -- environment table symbol with `key=value` syntax. For example the - -- the 'math.tointeger' from the usage below is equivalent to: - -- - -- local int = require 'std.normalize.math'.tointeger - -- - -- Compare this to loading the non-normalized implementation from the - -- host Lua with a table entry such as: - -- - -- int = require 'math'.tointeger, - -- - -- Finally, explicit string assignment to ALLCAPS keys are not loaded - -- from modules at all, but behave as a constant string assignment: - -- - -- INT = 'math.tointeger', - -- @function __call - -- @tparam table env environment table - -- @tparam[opt=1] int level stack level for `setfenv`, 1 means set - -- caller's environment - -- @treturn table *env* with this module's functions merge id. Assign - -- back to `_ENV` - -- @usage - -- local _ENV = require 'std.normalize' { - -- 'string', - -- 'std.prototype', - -- int = 'math.tointeger', - -- } - __call = function(_, env, level) - level = 1 + (level or 1) - return strict(normalize(env, level), level), nil - end, - - --- Lazy loading of normalize modules. - -- Don't load everything on initial startup, wait until first attempt - -- to access a submodule, and then load it on demand. - -- @function __index - -- @string name submodule name - -- @treturn table|nil the submodule that was loaded to satisfy the missing - -- `name`, otherwise `nil` if nothing was found - -- @usage - -- local version = require 'std.normalize'.version - __index = function(self, name) - local ok, t = pcall(require, 'std.normalize.' .. name) - if ok then - rawset(self, name, t) - return t - end - end, -}) - - ---- Types --- @section types - ---- Table of functions for string.render. --- @table RenderFns --- @tfield RenderElem elem return unique string representation of an element --- @tfield RenderTerm term return true for elements that should not be --- recursed --- @tfield RenderSort sort return list of keys in order to be rendered --- @tfield RenderOpen open return a string for before first element of a table --- @tfield RenderClose close return a string for after last element of a table --- @tfield RenderPair pair return a string rendering of a key value pair --- element --- @tfield RenderSep sep return a string to render between elements --- @see string.render --- @usage --- arrayvfns = { --- elem = tostring, --- term = function(x) --- return type(x) ~= 'table' or getmetamethod(x, '__tostring') --- end, --- sort = function(keys) --- local r = {} --- for i = 1, #keys do --- if type(keys[i]) == 'number' then r[#r + 1] = keys[i] end --- end --- return r --- end, --- open = function(_) return '[' end, --- close = function(_) return ']' end, --- pair = function(x, kp, vp, k, v, kstr, vstr, seqp) --- return seqp and vstr or '' --- end, --- sep = function(x, kp, vp, kn, vn, seqp) --- return seqp and kp ~= nil and kn ~= nil and ', ' or '' --- end, --- ) - ---- Type of function for uniquely stringifying rendered element. --- @function RenderElem --- @param x element to operate on --- @treturn string stringified *x* - ---- Type of predicate function for terminal elements. --- @function RenderTerm --- @param x element to operate on --- @treturn bool true for terminal elements that should be rendered --- immediately - ---- Type of function for sorting keys of a recursively rendered element. --- @function RenderSort --- @tparam table keys list of table keys, it's okay to mutate and return --- this parameter --- @treturn table sorted list of keys for pairs to be rendered - ---- Type of function to get string for before first element. --- @function RenderOpen --- @param x element to operate on --- @treturn string string to render before first element - ---- Type of function te get string for after last element. --- @function RenderClose --- @param x element to operate on --- @treturn string string to render after last element - ---- Type of function to render a key value pair. --- @function RenderPair --- @param x complete table elmeent being operated on --- @param kp unstringified previous pair key --- @param vp unstringified previous pair value --- @param k unstringified pair key to render --- @param v unstringified pair value to render --- @param kstr already stringified pair key to render --- @param vstr already stringified pair value to render --- @param seqp true if all keys so far have been a contiguous range of --- integers --- @treturn string stringified rendering of pair *kstr* and *vstr* - ---- Type of function to render a separator between pairs. --- @function RenderSep --- @param x complet table element being operated on --- @param kp unstringified previous pair key --- @param vp unstringified previous pair value --- @param kn unstringified next pair key --- @param vn unstringified next pair value --- @param seqp true if all keys so far have been a contiguous range of --- integers --- @treturn string stringified rendering of separator between previous and --- next pairs diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/package.lua b/modules/mixins/dotfiles/config/nvim/lua/std/package.lua @@ -1,263 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core package module. - - The module table returned by `std.package` also contains all of the entries - from the core `package` table. An hygienic way to import this module, then, is - simply to override core `package` locally: - - local package = require 'std.package' - - Manage `package.path` with normalization, duplicate removal, - insertion & removal of elements and automatic folding of '/' and '?' - onto `package.dirsep` and `package.pathmark`, for easy addition of - new paths. For example, instead of all this: - - lib = std.io.catfile('.', 'lib', package.pathmark .. '.lua') - paths = std.string.split(package.path, package.pathsep) - for i, path in ipairs(paths) do - -- ... lots of normalization code... - end - i = 1 - while i <= #paths do - if paths[i] == lib then - table.remove(paths, i) - else - i = i + 1 - end - end - table.insert(paths, 1, lib) - package.path = table.concat(paths, package.pathsep) - - You can now write just: - - package.path = package.normalize('./lib/?.lua', package.path) - - @corelibrary std.package -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck -local catfile = _.io.catfile -local escape_pattern = _.string.escape_pattern -local invert = _.table.invert -local split = _.string.split - -_ = nil - -local _ENV = require 'std.normalize' { - 'package', - concat = 'table.concat', - dirsep = 'package.dirsep', - gsub = 'string.gsub', - merge = 'table.merge', - pathmark = 'package.pathmark', - pathsep = 'package.pathsep', - string_find = 'string.find', - table_insert = 'table.insert', - table_remove = 'table.remove', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - ---- Make named constants for `package.config` --- (undocumented in 5.1; see luaconf.h for C equivalents). --- @table package --- @string dirsep directory separator --- @string pathsep path separator --- @string pathmark string that marks substitution points in a path template --- @string execdir(Windows only) replaced by the executable's directory in a path --- @string igmark Mark to ignore all before it when building `luaopen_` function name. - - -local function pathsub(path) - return gsub(path, '%%?.', function(capture) - if capture == '?' then - return pathmark - elseif capture == '/' then - return dirsep - else - return gsub(capture, '^%%', '', 1) - end - end) -end - - -local function find(pathstrings, patt, init, plain) - local paths = split(pathstrings, pathsep) - if plain then - patt = escape_pattern(patt) - end - init = init or 1 - if init < 0 then - init = #paths - init - end - for i = init, #paths do - if string_find(paths[i], patt) then - return i, paths[i] - end - end -end - - -local function normalize(...) - local i, paths, pathstrings = 1, {}, concat({...}, pathsep) - for _, path in ipairs(split(pathstrings, pathsep)) do - path = gsub(pathsub(path), catfile('^[^', ']'), catfile('.', '%0')) - path = gsub(path, catfile('', '%.', ''), dirsep) - path = gsub(path, catfile('', '%.$'), '') - path = gsub(path, catfile('^%.', '%..', ''), catfile('..', '')) - path = gsub(path, catfile('', '$'), '') - - -- Carefully remove redundant /foo/../ matches. - repeat - local again = false - path = gsub(path, catfile('', '([^', ']+)', '%.%.', ''), - function(dir1) - if dir1 == '..' then -- don't remove /../../ - return catfile('', '..', '..', '') - else - again = true - return dirsep - end - end) - path = gsub(path, catfile('', '([^', ']+)', '%.%.$'), - function(dir1) - if dir1 == '..' then -- don't remove /../.. - return catfile('', '..', '..') - else - again = true - return '' - end - end) - until again == false - - -- Build an inverted table of elements to eliminate duplicates after - -- normalization. - if not paths[path] then - paths[path], i = i, i + 1 - end - end - return concat(invert(paths), pathsep) -end - - -local function insert(pathstrings, ...) - local paths = split(pathstrings, pathsep) - table_insert(paths, ...) - return normalize(unpack(paths, 1, len(paths))) -end - - -local function mappath(pathstrings, callback, ...) - for _, path in ipairs(split(pathstrings, pathsep)) do - local r = callback(path, ...) - if r ~= nil then - return r - end - end -end - - -local function remove(pathstrings, pos) - local paths = split(pathstrings, pathsep) - table_remove(paths, pos) - return concat(paths, pathsep) -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.package.' .. decl, fn) or fn -end - - -local M = { - --- Look for a path segment match of *patt* in *pathstrings*. - -- @function find - -- @string pathstrings `pathsep` delimited path elements - -- @string patt a Lua pattern to search for in *pathstrings* - -- @int[opt=1] init element(not byte index!) to start search at. - -- Negative numbers begin counting backwards from the last element - -- @bool[opt=false] plain unless false, treat *patt* as a plain - -- string, not a pattern. Note that if *plain* is given, then *init* - -- must be given as well. - -- @return the matching element number(not byte index!) and full text - -- of the matching element, if any; otherwise nil - -- @usage - -- i, s = find(package.path, '^[^' .. package.dirsep .. '/]') - find = X('find(string, string, ?int, ?boolean|:plain)', find), - - --- Insert a new element into a `package.path` like string of paths. - -- @function insert - -- @string pathstrings a `package.path` like string - -- @int[opt=n+1] pos element index at which to insert *value*, where `n` is - -- the number of elements prior to insertion - -- @string value new path element to insert - -- @treturn string a new string with the new element inserted - -- @usage - -- package.path = insert(package.path, 1, install_dir .. '/?.lua') - insert = X('insert(string, [int], string)', insert), - - --- Call a function with each element of a path string. - -- @function mappath - -- @string pathstrings a `package.path` like string - -- @tparam mappathcb callback function to call for each element - -- @param ... additional arguments passed to *callback* - -- @return nil, or first non-nil returned by *callback* - -- @usage - -- mappath(package.path, searcherfn, transformfn) - mappath = X('mappath(string, function, [any...])', mappath), - - --- Normalize a path list. - -- Removing redundant `.` and `..` directories, and keep only the first - -- instance of duplicate elements. Each argument can contain any number - -- of `pathsep` delimited elements; wherein characters are subject to - -- `/` and `?` normalization, converting `/` to `dirsep` and `?` to - -- `pathmark`(unless immediately preceded by a `%` character). - -- @function normalize - -- @param ... path elements - -- @treturn string a single normalized `pathsep` delimited paths string - -- @usage - -- package.path = normalize(user_paths, sys_paths, package.path) - normalize = X('normalize(string...)', normalize), - - --- Remove any element from a `package.path` like string of paths. - -- @function remove - -- @string pathstrings a `package.path` like string - -- @int[opt=n] pos element index from which to remove an item, where `n` - -- is the number of elements prior to removal - -- @treturn string a new string with given element removed - -- @usage - -- package.path = remove(package.path) - remove = X('remove(string, ?int)', remove), -} - - -return merge(package, M) - - ---- Types --- @section Types - ---- Function signature of a callback for @{mappath}. --- @function mappathcb --- @string element an element from a `pathsep` delimited string of --- paths --- @param ... additional arguments propagated from @{mappath} --- @return non-nil to break, otherwise continue with the next element diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/string.lua b/modules/mixins/dotfiles/config/nvim/lua/std/string.lua @@ -1,504 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core string module. - - The module table returned by `std.string` also contains all of the entries - from the core string table. An hygienic way to import this module, then, is - simply to override the core `string` locally: - - local string = require 'std.string' - - @corelibrary std.string -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.std.typecheck.argscheck -local escape_pattern = _.string.escape_pattern -local split = _.string.split - -_ = nil - - -local _ENV = require 'std.normalize' { - 'string', - abs = 'math.abs', - concat = 'table.concat', - find = 'string.find', - floor = 'math.floor', - format = 'string.format', - gsub = 'string.gsub', - insert = 'table.insert', - match = 'string.match', - merge = 'table.merge', - render = 'string.render', - sort = 'table.sort', - sub = 'string.sub', - upper = 'string.upper', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local M - - -local function toqstring(x, xstr) - if type(x) ~= 'string' then - return xstr - end - return format('%q', x) -end - - -local concatvfns = { - elem = tostring, - term = function(x) - return type(x) ~= 'table' or getmetamethod(x, '__tostring') - end, - sort = function(keys) - return keys - end, - open = function(x) return '{' end, - close = function(x) return '}' end, - pair = function(x, kp, vp, k, v, kstr, vstr, seqp) - return toqstring(k, kstr) .. '=' .. toqstring(v, vstr) - end, - sep = function(x, kp, vp, kn, vn, seqp) - return kp ~= nil and kn ~= nil and ',' or '' - end, -} - - -local function __concat(s, o) - -- Don't use normalize.str here, because we don't want ASCII escape rendering. - return render(s, concatvfns) .. render(o, concatvfns) -end - - -local function __index(s, i) - if type(i) == 'number' then - return sub(s, i, i) - else - -- Fall back to module metamethods - return M[i] - end -end - - -local _format = string.format - -local function format(f, arg1, ...) - return(arg1 ~= nil) and _format(f, arg1, ...) or f -end - - -local function tpack(from, to, ...) - return from, to, {...} -end - -local function tfind(s, ...) - return tpack(find(s, ...)) -end - - -local function finds(s, p, i, ...) - i = i or 1 - local l = {} - local from, to, r - repeat - from, to, r = tfind(s, p, i, ...) - if from ~= nil then - insert(l, {from, to, capt=r}) - i = to + 1 - end - until not from - return l -end - - -local function caps(s) - return(gsub(s, '(%w)([%w]*)', function(l, ls) - return upper(l) .. ls - end)) -end - - -local function escape_shell(s) - return(gsub(s, '([ %(%)%\\%[%]\'"])', '\\%1')) -end - - -local function ordinal_suffix(n) - n = abs(n) % 100 - local d = n % 10 - if d == 1 and n ~= 11 then - return 'st' - elseif d == 2 and n ~= 12 then - return 'nd' - elseif d == 3 and n ~= 13 then - return 'rd' - else - return 'th' - end -end - - -local function pad(s, w, p) - p = string.rep(p or ' ', abs(w)) - if w < 0 then - return string.sub(p .. s, w) - end - return string.sub(s .. p, 1, w) -end - - -local function wrap(s, w, ind, ind1) - w = w or 78 - ind = ind or 0 - ind1 = ind1 or ind - assert(ind1 < w and ind < w, - 'the indents must be less than the line width') - local r = {string.rep(' ', ind1)} - local i, lstart, lens = 1, ind1, len(s) - while i <= lens do - local j = i + w - lstart - while len(s[j]) > 0 and s[j] ~= ' ' and j > i do - j = j - 1 - end - local ni = j + 1 - while s[j] == ' ' do - j = j - 1 - end - insert(r, sub(s, i, j)) - i = ni - if i < lens then - insert(r, '\n' .. string.rep(' ', ind)) - lstart = ind - end - end - return concat(r) -end - - -local function numbertosi(n) - local SIprefix = { - [-8]='y', [-7]='z', [-6]='a', [-5]='f', - [-4]='p', [-3]='n', [-2]='mu', [-1]='m', - [0]='', [1]='k', [2]='M', [3]='G', - [4]='T', [5]='P', [6]='E', [7]='Z', - [8]='Y' - } - local t = _format('% #.2e', n) - local _, _, m, e = find(t, '.(.%...)e(.+)') - local man, exp = tonumber(m), tonumber(e) - local siexp = floor(exp / 3) - local shift = exp - siexp * 3 - local s = SIprefix[siexp] or 'e' .. tostring(siexp) - man = man *(10 ^ shift) - return _format('%0.f', man) .. s -end - - --- Ordor numbers first then asciibetically. -local function keycmp(a, b) - if type(a) == 'number' then - return type(b) ~= 'number' or a < b - end - return type(b) ~= 'number' and tostring(a) < tostring(b) -end - - -local render_fallbacks = { - __index = concatvfns, -} - - -local function prettytostring(x, indent, spacing) - indent = indent or '\t' - spacing = spacing or '' - return render(x, setmetatable({ - elem = function(x) - if type(x) ~= 'string' then - return tostring(x) - end - return format('%q', x) - end, - - sort = function(keylist) - sort(keylist, keycmp) - return keylist - end, - - open = function() - local s = spacing .. '{' - spacing = spacing .. indent - return s - end, - - close = function() - spacing = string.gsub(spacing, indent .. '$', '') - return spacing .. '}' - end, - - pair = function(x, _, _, k, v, kstr, vstr) - local type_k = type(k) - local s = spacing - if type_k ~= 'string' or match(k, '[^%w_]') then - s = s .. '[' - if type_k == 'table' then - s = s .. '\n' - end - s = s .. kstr - if type_k == 'table' then - s = s .. '\n' - end - s = s .. ']' - else - s = s .. k - end - s = s .. ' =' - if type(v) == 'table' then - s = s .. '\n' - else - s = s .. ' ' - end - s = s .. vstr - return s - end, - - sep = function(_, k) - local s = '\n' - if k then - s = ',' .. s - end - return s - end, - }, render_fallbacks)) -end - - -local function trim(s, r) - r = r or '%s+' - return (gsub(gsub(s, '^' .. r, ''), r .. '$', '')) -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.string.' .. decl, fn) or fn -end - -M = { - --- Metamethods - -- @section metamethods - - --- String concatenation operation. - -- @function __concat - -- @string s initial string - -- @param o object to stringify and concatenate - -- @return s .. tostring(o) - -- @usage - -- local string = setmetatable('', require 'std.string') - -- concatenated = 'foo' .. {'bar'} - __concat = __concat, - - --- String subscript operation. - -- @function __index - -- @string s string - -- @tparam int|string i index or method name - -- @return `sub(s, i, i)` if i is a number, otherwise - -- fall back to a `std.string` metamethod(if any). - -- @usage - -- getmetatable('').__index = require 'std.string'.__index - -- third =('12345')[3] - __index = __index, - - - --- Core Functions - -- @section corefuncs - - --- Capitalise each word in a string. - -- @function caps - -- @string s any string - -- @treturn string *s* with each word capitalized - -- @usage - -- userfullname = caps(input_string) - caps = X('caps(string)', caps), - - --- Remove any final newline from a string. - -- @function chomp - -- @string s any string - -- @treturn string *s* with any single trailing newline removed - -- @usage - -- line = chomp(line) - chomp = X('chomp(string)', function(s) - return(gsub(s, '\n$', '')) - end), - - --- Escape a string to be used as a pattern. - -- @function escape_pattern - -- @string s any string - -- @treturn string *s* with active pattern characters escaped - -- @usage - -- substr = match(inputstr, escape_pattern(literal)) - escape_pattern = X('escape_pattern(string)', escape_pattern), - - --- Escape a string to be used as a shell token. - -- Quotes spaces, parentheses, brackets, quotes, apostrophes and - -- whitespace. - -- @function escape_shell - -- @string s any string - -- @treturn string *s* with active shell characters escaped - -- @usage - -- os.execute('echo ' .. escape_shell(outputstr)) - escape_shell = X('escape_shell(string)', escape_shell), - - --- Repeatedly `string.find` until target string is exhausted. - -- @function finds - -- @string s target string - -- @string pattern pattern to match in *s* - -- @int[opt=1] init start position - -- @bool[opt] plain inhibit magic characters - -- @return list of `{from, to; capt={captures}}` - -- @see std.string.tfind - -- @usage - -- for t in std.elems(finds('the target string', '%S+')) do - -- print(tostring(t.capt)) - -- end - finds = X('finds(string, string, ?int, ?boolean|:plain)', finds), - - --- Extend to work better with one argument. - -- If only one argument is passed, no formatting is attempted. - -- @function format - -- @string f format string - -- @param[opt] ... arguments to format - -- @return formatted string - -- @usage - -- print(format '100% stdlib!') - format = X('format(string, [any...])', format), - - --- Remove leading matter from a string. - -- @function ltrim - -- @string s any string - -- @string[opt='%s+'] r leading pattern - -- @treturn string *s* with leading *r* stripped - -- @usage - -- print('got: ' .. ltrim(userinput)) - ltrim = X('ltrim(string, ?string)', function(s, r) - return (gsub(s, '^' ..(r or '%s+'), '')) - end), - - --- Write a number using SI suffixes. - -- The number is always written to 3 s.f. - -- @function numbertosi - -- @tparam number|string n any numeric value - -- @treturn string *n* simplifed using largest available SI suffix. - -- @usage - -- print(numbertosi(bitspersecond) .. 'bps') - numbertosi = X('numbertosi(number|string)', numbertosi), - - --- Return the English suffix for an ordinal. - -- @function ordinal_suffix - -- @tparam int|string n any integer value - -- @treturn string English suffix for *n* - -- @usage - -- local now = os.date '*t' - -- print('%d%s day of the week', now.day, ordinal_suffix(now.day)) - ordinal_suffix = X('ordinal_suffix(int|string)', ordinal_suffix), - - --- Justify a string. - -- When the string is longer than w, it is truncated(left or right - -- according to the sign of w). - -- @function pad - -- @string s a string to justify - -- @int w width to justify to(-ve means right-justify; +ve means - -- left-justify) - -- @string[opt=' '] p string to pad with - -- @treturn string *s* justified to *w* characters wide - -- @usage - -- print(pad(trim(outputstr, 78)) .. '\n') - pad = X('pad(string, int, ?string)', pad), - - --- Pretty-print a table, or other object. - -- @function prettytostring - -- @param x object to convert to string - -- @string[opt='\t'] indent indent between levels - -- @string[opt=''] spacing space before every line - -- @treturn string pretty string rendering of *x* - -- @usage - -- print(prettytostring(std, ' ')) - prettytostring = X('prettytostring(?any, ?string, ?string)', prettytostring), - - --- Remove trailing matter from a string. - -- @function rtrim - -- @string s any string - -- @string[opt='%s+'] r trailing pattern - -- @treturn string *s* with trailing *r* stripped - -- @usage - -- print('got: ' .. rtrim(userinput)) - rtrim = X('rtrim(string, ?string)', function(s, r) - return (gsub(s, (r or '%s+') .. '$', '')) - end), - - --- Split a string at a given separator. - -- Separator is a Lua pattern, so you have to escape active characters, - -- `^$()%.[]*+-?` with a `%` prefix to match a literal character in *s*. - -- @function split - -- @string s to split - -- @string[opt='%s+'] sep separator pattern - -- @return list of strings - -- @usage - -- words = split 'a very short sentence' - split = X('split(string, ?string)', split), - - --- Do `string.find`, returning a table of captures. - -- @function tfind - -- @string s target string - -- @string pattern pattern to match in *s* - -- @int[opt=1] init start position - -- @bool[opt] plain inhibit magic characters - -- @treturn int start of match - -- @treturn int end of match - -- @treturn table list of captured strings - -- @see std.string.finds - -- @usage - -- b, e, captures = tfind('the target string', '%s', 10) - tfind = X('tfind(string, string, ?int, ?boolean|:plain)', tfind), - - --- Remove leading and trailing matter from a string. - -- @function trim - -- @string s any string - -- @string[opt='%s+'] r trailing pattern - -- @treturn string *s* with leading and trailing *r* stripped - -- @usage - -- print('got: ' .. trim(userinput)) - trim = X('trim(string, ?string)', trim), - - --- Wrap a string into a paragraph. - -- @function wrap - -- @string s a paragraph of text - -- @int[opt=78] w width to wrap to - -- @int[opt=0] ind indent - -- @int[opt=ind] ind1 indent of first line - -- @treturn string *s* wrapped to *w* columns - -- @usage - -- print(wrap(copyright, 72, 4)) - wrap = X('wrap(string, ?int, ?int, ?int)', wrap), -} - - -return merge(string, M) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/table.lua b/modules/mixins/dotfiles/config/nvim/lua/std/table.lua @@ -1,439 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Extensions to the core table module. - - The module table returned by `std.table` also contains all of the entries from - the core table module. An hygienic way to import this module, then, is simply - to override the core `table` locally: - - local table = require 'std.table' - - @corelibrary std.table -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck -local invert = _.table.invert -local maxn = _.table.maxn - -_ = nil - -local _ENV = require 'std.normalize' { - 'table', - merge = 'table.merge', - min = 'math.min', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local M - - -local function merge_allfields(t, u, map, nometa) - if type(map) ~= 'table' then - map, nometa = nil, map - end - - if not nometa then - setmetatable(t, getmetatable(u)) - end - if map then - for k, v in pairs(u) do - t[map[k] or k] = v - end - else - for k, v in pairs(u) do - t[k] = v - end - end - return t -end - - -local function merge_namedfields(t, u, keys, nometa) - if type(keys) ~= 'table' then - keys, nometa = nil, keys - end - - if not nometa then - setmetatable(t, getmetatable(u)) - end - for _, k in pairs(keys or {}) do - t[k] = u[k] - end - return t -end - - -local function depair(ls) - local t = {} - for _, v in ipairs(ls) do - t[v[1]] = v[2] - end - return t -end - - -local function enpair(t) - local tt = {} - for i, v in pairs(t) do - tt[#tt + 1] = {i, v} - end - return tt -end - - -local _insert = table.insert - -local function insert(t, pos, v) - if v == nil then - pos, v = len(t) + 1, pos - end - if pos < 1 or pos > len(t) + 1 then - argerror('std.table.insert', 2, 'position ' .. pos .. ' out of bounds', 2) - end - _insert(t, pos, v) - return t -end - - -local function keys(t) - local l = {} - for k in pairs(t) do - l[#l + 1] = k - end - return l -end - - -local function new(x, t) - return setmetatable(t or {}, {__index = function(t, i) - return x - end}) -end - - -local function project(fkey, tt) - local r = {} - for _, t in ipairs(tt) do - r[#r + 1] = t[fkey] - end - return r -end - - -local function size(t) - local n = 0 - for _ in pairs(t) do - n = n + 1 - end - return n -end - - --- Preserve core table sort function. -local _sort = table.sort - -local function sort(t, c) - _sort(t, c) - return t -end - - -local _remove = table.remove - -local function remove(t, pos) - local lent = len(t) - pos = pos or lent - if pos < min(1, lent) or pos > lent + 1 then -- +1? whu? that's what 5.2.3 does!?! - argerror('std.table.remove', 2, 'position ' .. pos .. ' out of bounds', 2) - end - return _remove(t, pos) -end - - -local _unpack = unpack - -local function unpack(t, i, j) - if j == nil then - -- if j was not given, respect __len, otherwise use maxn - local m = getmetamethod(t, '__len') - j = m and m(t) or maxn(t) - end - return _unpack(t, tonumber(i) or 1, tonumber(j)) -end - - -local function values(t) - local l = {} - for _, v in pairs(t) do - l[#l + 1] = v - end - return l -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.table.' .. decl, fn) or fn -end - -M = { - --- Core Functions - -- @section corefuncs - - --- Enhance core *table.insert* to return its result. - -- If *pos* is not given, respect `__len` metamethod when calculating - -- default append. Also, diagnose out of bounds *pos* arguments - -- consistently on any supported version of Lua. - -- @function insert - -- @tparam table t a table - -- @int[opt=len(t)] pos index at which to insert new element - -- @param v value to insert into *t* - -- @treturn table *t* - -- @usage - -- --> {1, 'x', 2, 3, 'y'} - -- insert(insert({1, 2, 3}, 2, 'x'), 'y') - insert = X('insert(table, [int], any)', insert), - - --- Largest integer key in a table. - -- @function maxn - -- @tparam table t a table - -- @treturn int largest integer key in *t* - -- @usage - -- --> 42 - -- maxn {'a', b='c', 99, [42]='x', 'x', [5]=67} - maxn = X('maxn(table)', maxn), - - --- Turn a tuple into a list, with tuple-size in field `n` - -- @function pack - -- @param ... tuple - -- @return list-like table, with tuple-size in field `n` - -- @usage - -- --> {1, 2, 'ax', n=3} - -- pack(find('ax1', '(%D+)')) - pack = pack, - - --- Enhance core *table.remove* to respect `__len` when *pos* is omitted. - -- Also, diagnose out of bounds *pos* arguments consistently on any supported - -- version of Lua. - -- @function remove - -- @tparam table t a table - -- @int[opt=len(t)] pos index from which to remove an element - -- @return removed value, or else `nil` - -- @usage - -- --> {1, 2, 5} - -- t = {1, 2, 'x', 5} - -- remove(t, 3) == 'x' and t - remove = X('remove(table, ?int)', remove), - - --- Enhance core *table.sort* to return its result. - -- @function sort - -- @tparam table t unsorted table - -- @tparam[opt=std.operator.lt] comparator c ordering function callback - -- @return *t* with keys sorted according to *c* - -- @usage - -- table.concat(sort(object)) - sort = X('sort(table, ?function)', sort), - - --- Enhance core *table.unpack* to always unpack up to __len or maxn. - -- @function unpack - -- @tparam table t table to act on - -- @int[opt=1] i first index to unpack - -- @int[opt=table.maxn(t)] j last index to unpack - -- @return ... values of numeric indices of *t* - -- @usage - -- return unpack(results_table) - unpack = X('unpack(table, ?int, ?int)', unpack), - - - --- Accessor Functions - -- @section accessorfuncs - - --- Make a shallow copy of a table, including any metatable. - -- @function clone - -- @tparam table t source table - -- @tparam[opt={}] table map table of `{old_key=new_key, ...}` - -- @bool[opt] nometa if non-nil don't copy metatable - -- @return copy of *t*, also sharing *t*'s metatable unless *nometa* - -- is true, and with keys renamed according to *map* - -- @see merge - -- @see clone_select - -- @usage - -- shallowcopy = clone(original, {rename_this='to_this'}, ':nometa') - clone = X('clone(table, [table], ?boolean|:nometa)', function(...) - return merge_allfields({}, ...) - end), - - --- Make a partial clone of a table. - -- - -- Like `clone`, but does not copy any fields by default. - -- @function clone_select - -- @tparam table t source table - -- @tparam[opt={}] table keys list of keys to copy - -- @bool[opt] nometa if non-nil don't copy metatable - -- @treturn table copy of fields in *selection* from *t*, also sharing *t*'s - -- metatable unless *nometa* - -- @see clone - -- @see merge_select - -- @usage - -- partialcopy = clone_select(original, {'this', 'and_this'}, true) - clone_select = X('clone_select(table, [table], ?boolean|:nometa)', function(...) - return merge_namedfields({}, ...) - end), - - --- Turn a list of pairs into a table. - -- @todo Find a better name. - -- @function depair - -- @tparam table ls list of lists - -- @treturn table a flat table with keys and values from *ls* - -- @see enpair - -- @usage - -- --> {a=1, b=2, c=3} - -- depair {{'a', 1}, {'b', 2}, {'c', 3}} - depair = X('depair(list of lists)', depair), - - --- Turn a table into a list of pairs. - -- @todo Find a better name. - -- @function enpair - -- @tparam table t a table `{i1=v1, ..., in=vn}` - -- @treturn table a new list of pairs containing `{{i1, v1}, ..., {in, vn}}` - -- @see depair - -- @usage - -- --> {{1, 'a'}, {2, 'b'}, {3, 'c'}} - -- enpair {'a', 'b', 'c'} - enpair = X('enpair(table)', enpair), - - --- Return whether table is empty. - -- @function empty - -- @tparam table t any table - -- @treturn boolean `true` if *t* is empty, otherwise `false` - -- @usage - -- if empty(t) then error 'ohnoes' end - empty = X('empty(table)', function(t) - return not next(t) - end), - - --- Make a table with a default value for unset keys. - -- @function new - -- @param[opt=nil] x default entry value - -- @tparam[opt={}] table t initial table - -- @treturn table table whose unset elements are *x* - -- @usage - -- t = new(0) - new = X('new(?any, ?table)', new), - - --- Project a list of fields from a list of tables. - -- @function project - -- @param fkey field to project - -- @tparam table tt a list of tables - -- @treturn table list of *fkey* fields from *tt* - -- @usage - -- --> {1, 3, 'yy'} - -- project('xx', {{'a', xx=1, yy='z'}, {'b', yy=2}, {'c', xx=3}, {xx='yy'}) - project = X('project(any, list of tables)', project), - - --- Find the number of elements in a table. - -- @function size - -- @tparam table t any table - -- @treturn int number of non-nil values in *t* - -- @usage - -- --> 3 - -- size {foo=true, bar=true, baz=false} - size = X('size(table)', size), - - --- Make the list of values of a table. - -- @function values - -- @tparam table t any table - -- @treturn table list of values in *t* - -- @see keys - -- @usage - -- --> {'a', 'c', 42} - -- values {'a', b='c', [-1]=42} - values = X('values(table)', values), - - - --- Mutator Functions - -- @section mutatorfuncs - - --- Invert a table. - -- @function invert - -- @tparam table t a table with `{k=v, ...}` - -- @treturn table inverted table `{v=k, ...}` - -- @usage - -- --> {a=1, b=2, c=3} - -- invert {'a', 'b', 'c'} - invert = X('invert(table)', invert), - - --- Make the list of keys in table. - -- @function keys - -- @tparam table t a table - -- @treturn table list of keys from *t* - -- @see values - -- @usage - -- globals = keys(_G) - keys = X('keys(table)', keys), - - --- Destructively merge one table's fields into another. - -- @function merge - -- @tparam table t destination table - -- @tparam table u table with fields to merge - -- @tparam[opt={}] table map table of `{old_key=new_key, ...}` - -- @bool[opt] nometa if `true` or ':nometa' don't copy metatable - -- @treturn table *t* with fields from *u* merged in - -- @see clone - -- @see merge_select - -- @usage - -- merge(_G, require 'std.debug', {say='log'}, ':nometa') - merge = X('merge(table, table, [table], ?boolean|:nometa)', merge_allfields), - - --- Destructively merge another table's named fields into *table*. - -- - -- Like `merge`, but does not merge any fields by default. - -- @function merge_select - -- @tparam table t destination table - -- @tparam table u table with fields to merge - -- @tparam[opt={}] table keys list of keys to copy - -- @bool[opt] nometa if `true` or ':nometa' don't copy metatable - -- @treturn table copy of fields in *selection* from *t*, also sharing *t*'s - -- metatable unless *nometa* - -- @see merge - -- @see clone_select - -- @usage - -- merge_select(_G, require 'std.debug', {'say'}, false) - merge_select = X('merge_select(table, table, [table], ?boolean|:nometa)', - merge_namedfields), -} - - -return merge(table, M) - - - ---- Types --- @section Types - ---- Signature of a @{sort} comparator function. --- @function comparator --- @param a any object --- @param b any object --- @treturn boolean `true` if *a* sorts before *b*, otherwise `false` --- @see sort --- @usage --- local reversor = function(a, b) return a > b end --- sort(t, reversor)