aboutsummaryrefslogtreecommitdiff
path: root/src/lib/path.lua
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2026-04-20 13:43:01 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2026-04-20 13:43:01 +0200
commit0686b40f979f4607b3fd8cca21c463e98f617666 (patch)
tree355e8a7bfd4b37510d05370876a9d8cedfdcd5d7 /src/lib/path.lua
parentba561ebd063b391013b6c9c1fcc9b1838dd422e6 (diff)
implement builder and instance
Diffstat (limited to 'src/lib/path.lua')
-rw-r--r--src/lib/path.lua112
1 files changed, 103 insertions, 9 deletions
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
}
}