-- -- melisma - extensible and scriptable audio engine -- Copyright (C) 2026 Ludvig Gunne Lindström -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- local M = {} function M.deepstring(value,visited,depth,is_key) if not is_key and type(value) == 'string' then return '\'' .. value .. '\'' end if type(value) ~= 'table' then return tostring(value) end if next(value) == nil then return '{}' end visited = visited or {} visited[value] = true depth = depth or 0 local indent = string.rep(' ',depth) local str = {} local function append(...) table.insert(str,string.format(...)) end append('{ ') for k,v in pairs(value) do if visited[k] then k='{...}' else k=M.deepstring(k,visited,depth+1,true) end if visited[v] then v='{...}' else v=M.deepstring(v,visited,depth+1) end append(indent .. ' ' .. '%s = %s, ',k,v) end append(indent .. '}') return table.concat(str,'\n') end function M.deepcopy(x) if type(x) ~= 'table' then return x end local copy = {} for k,v in pairs(x) do copy[k] = M.deepcopy(v) end return copy end function M.size(x) local s = 0 for _,_ in pairs(x) do s = s + 1 end return s end function M.image(a,b,c,d,x) return (x - a)/(b - a)*(d - c) + c end function M.select(list,prompt) for i,entry in ipairs(list) do print(i,entry) end while true do io.write(prompt .. '> ') io.flush() local input = io.read('*l') local i = tonumber(input) if i == nil then print() error() end if i >= 1 and i <= #list then return list[i] end end end function M.splitcmd(str) local words = {} local word = '' local state = 'skip' for i = 1,#str do local c = string.sub(str,i,i) if state == 'skip' then if c == '"' then state = 'string' elseif c ~= ' ' then state = 'take' word = word .. c end elseif state == 'take' then if c == ' ' then state = 'skip' table.insert(words,word) word = '' elseif c == '"' then state = 'string' else word = word .. c end elseif state == 'string' then if c == '"' then state = 'take' else word = word .. c end end end if state ~= 'skip' then table.insert(words,word) end return words end function M.openmodule(module) if module.lazy_require_getmodule ~= nil then module = module.lazy_require_getmodule() end for k,v in pairs(module) do if string.sub(k,1,2) ~= '__' then _G[k] = v end end end return M