From 0686b40f979f4607b3fd8cca21c463e98f617666 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Mon, 20 Apr 2026 13:43:01 +0200 Subject: implement builder and instance --- src/extensions/init.lua | 1 + src/extensions/string.lua | 86 ++++++++++++++++++++++++++++++++++++++++++++++- src/extensions/table.lua | 28 +++++++++++++++ 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/extensions/table.lua (limited to 'src/extensions') diff --git a/src/extensions/init.lua b/src/extensions/init.lua index a4c4f5a..ba3c928 100644 --- a/src/extensions/init.lua +++ b/src/extensions/init.lua @@ -1 +1,2 @@ require('extensions.string') +require('extensions.table') diff --git a/src/extensions/string.lua b/src/extensions/string.lua index 247d31a..5cbb4ec 100644 --- a/src/extensions/string.lua +++ b/src/extensions/string.lua @@ -1,3 +1,7 @@ +function string:starts_with(s) + return self:sub(1, #s) == s +end + function string:flag_name() if self:sub(1, 2) ~= "--" then return nil @@ -16,11 +20,91 @@ function string:split(sep) return splits end +-- NOTE: This function is for certain not complete and not very efficient +-- but for now it works good enough to proceed with development. +-- We might need to rewrite this function in the future if it is a bottleneck. +function string:split_into_template_blocks() + local splits = { { kind = 'text', content = '' } } + local stack = {} + local current = self + + local matching = { + ["{"] = "}", + ["["] = "]", + ["("] = ")", + } + + while #current > 0 do + local add = true + if #stack == 0 and current:starts_with("@{") then + current = current:sub(2, #current) + stack[#stack + 1] = "}" + splits[#splits + 1] = { kind = 'code', content = '' } + add = false + elseif #stack > 0 and ( + current:starts_with('"') or + current:starts_with("'") or + current:starts_with('[[') + ) then + local string_end = current:starts_with('"') and '"' or (current:starts_with("'") and "'" or ']]') + splits[#splits].content = splits[#splits].content .. current:sub(1, 1) + current = current:sub(2) + + while #current > 0 do + if current:starts_with('\\') then + splits[#splits].content = splits[#splits].content .. current:sub(1, 1) + current = current:sub(2) + elseif current:starts_with(string_end) then + break + end + splits[#splits].content = splits[#splits].content .. current:sub(1, 1) + current = current:sub(2) + end + + elseif #stack > 0 and current:starts_with("--") then + local comment_end = current:starts_with('--[[') and ']]' or '\n' + splits[#splits].content = splits[#splits].content .. current:sub(1, (current:find(comment_end) + #comment_end) or #current + 1) + current = current:sub((current:find(comment_end) + #comment_end) or #current + 1) + add = false + elseif #stack > 0 then + local start = current:sub(1, 1) + local closing = matching[start] + + if start == stack[#stack] then + stack[#stack] = nil + + if #stack == 0 then + current = current:sub(2, #current) + splits[#splits + 1] = { kind = 'text', content = '' } + end + elseif closing then + stack[#stack + 1] = closing + end + end + + if add then + splits[#splits].content = splits[#splits].content .. current:sub(1, 1) + end + current = current:sub(2) + end + + return splits +end + return { tests = { function() local path = 'some/path/here' - assert.equals({ 'some', 'path', 'here' }, path.split("/")) + assert.equals({ 'some', 'path', 'here' }, path:split("/")) end, + function() + local f = Path:new("example/test.py"):open("r") + local raw = f:read("*all") + f:close() + + for _, value in ipairs(raw:split_into_template_blocks()) do + print(require('inspect')(value)) + end + end } } diff --git a/src/extensions/table.lua b/src/extensions/table.lua new file mode 100644 index 0000000..eb983d3 --- /dev/null +++ b/src/extensions/table.lua @@ -0,0 +1,28 @@ + +function table:extend(other) + if type(other) == 'table' then + for _, value in ipairs(other) do + self[#self + 1] = value + end + else + for value in other do + self[#self + 1] = value + end + end +end + +function table:merge(other) + for key, value in pairs(other) do + self[key] = value + end +end + +function table.from_iter(iter) + local t = {} + + for value in iter do + t[#t + 1] = value + end + + return t +end -- cgit v1.2.3-70-g09d2