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/lib/path.lua | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 103 insertions(+), 9 deletions(-) (limited to 'src/lib/path.lua') diff --git a/src/lib/path.lua b/src/lib/path.lua index b0f0fac..f99585b 100644 --- a/src/lib/path.lua +++ b/src/lib/path.lua @@ -1,7 +1,18 @@ Path = {} function Path:new(p) - local path = { segments = p:split('/') } + local is_absolute = p:sub(1, 1) == "/" + p = p:gsub("/+", "/") + p = p:gsub("(/%./", "/") + p = p:gsub("/%.$", "") + p = p:gsub("/$", "") + p = p:gsub("^%./", "") + p = p:gsub("/[^/]+/%.%.", "") + + local path = { + segments = p:split('/'), + is_absolute = is_absolute + } setmetatable(path, self) self.__index = self @@ -18,20 +29,87 @@ function Path:stem() end function Path:parent() - local path = { segments = { table.unpack(self.segments, 1, #self.segments - 1) } } - - setmetatable(path, self) - self.__index = self - - return path + return self / ".." end function Path:__tostring() - return table.concat(self.segments, "/") + return (self.is_absolute and "/" or "") .. table.concat(self.segments, "/") end function Path:__div(next) - return Path:new(self:__tostring() .. "/" .. next) + if next.is_absolute then + error("cannot concat with absolute path") + end + + return Path:new(self:__tostring() .. "/" .. tostring(next)) +end + +function Path:open(mode) + return io.open(tostring(self), mode) +end + +function Path:exists() + local f = self:open('r') + + if f ~= nil then + f:close() + return true + end + return false +end + +function Path:is_directory() + local f = self:open('r') + + if not f then + return false + end + + local value, err, code = f:read() + f:close() + + return code == 21 +end + +function Path:entries() + if not self:is_directory() then + return function() end + end + + local pipe = io.popen('ls' .. ' "' .. tostring(self) .. '"') + local lines = pipe:lines() + + return function() + local value = lines() + if value == nil then + pipe:close() + return nil + end + return self / value + end +end + +function Path:children() + if not self:is_directory() then + return function() end + end + + local pipe = io.popen('find' .. ' "' .. tostring(self) .. '"') + local lines = pipe:lines() + + return function() + local value = lines() + if value == nil then + pipe:close() + return nil + end + return Path:new(value) + end +end + +function Path:make_directory(opts) + local pipe = io.popen('mkdir ' .. (opts.create_parents and '-p ' or ' ') .. tostring(self)) + pipe:close() end return { @@ -56,6 +134,22 @@ return { local path = Path:new("some/path/here") path = path / 'next.txt' assert.equals("some/path/here/next.txt", path:__tostring()) + end, + function() + local path = Path:new("./src") + assert.equals(true, path:is_directory()) + end, + function() + local path = Path:new("./src/blueprint") + assert.equals(false, path:is_directory()) + end, + function() + local path = Path:new("./src/blueprint") + assert.equals(true, path:exists()) + end, + function() + local path = Path:new("./src/blueprint__") + assert.equals(false, path:exists()) end } } -- cgit v1.2.3-70-g09d2