You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
2.7 KiB
Lua

--[[lit-meta
name = "creationix/pathjoin"
description = "The path utilities that used to be part of luvi"
version = "2.0.0"
tags = {"path"}
license = "MIT"
author = { name = "Tim Caswell" }
]]
local getPrefix, splitPath, joinParts
local isWindows
if _G.jit then
isWindows = _G.jit.os == "Windows"
else
isWindows = not not package.path:match("\\")
end
if isWindows then
-- Windows aware path utilities
function getPrefix(path)
return path:match("^%a:\\") or
path:match("^/") or
path:match("^\\+")
end
function splitPath(path)
local parts = {}
for part in string.gmatch(path, '([^/\\]+)') do
table.insert(parts, part)
end
return parts
end
function joinParts(prefix, parts, i, j)
if not prefix then
return table.concat(parts, '/', i, j)
elseif prefix ~= '/' then
return prefix .. table.concat(parts, '\\', i, j)
else
return prefix .. table.concat(parts, '/', i, j)
end
end
else
-- Simple optimized versions for UNIX systems
function getPrefix(path)
return path:match("^/")
end
function splitPath(path)
local parts = {}
for part in string.gmatch(path, '([^/]+)') do
table.insert(parts, part)
end
return parts
end
function joinParts(prefix, parts, i, j)
if prefix then
return prefix .. table.concat(parts, '/', i, j)
end
return table.concat(parts, '/', i, j)
end
end
local function pathJoin(...)
local inputs = {...}
local l = #inputs
-- Find the last segment that is an absolute path
-- Or if all are relative, prefix will be nil
local i = l
local prefix
while true do
prefix = getPrefix(inputs[i])
if prefix or i <= 1 then break end
i = i - 1
end
-- If there was one, remove its prefix from its segment
if prefix then
inputs[i] = inputs[i]:sub(#prefix)
end
-- Split all the paths segments into one large list
local parts = {}
while i <= l do
local sub = splitPath(inputs[i])
for j = 1, #sub do
parts[#parts + 1] = sub[j]
end
i = i + 1
end
-- Evaluate special segments in reverse order.
local skip = 0
local reversed = {}
for idx = #parts, 1, -1 do
local part = parts[idx]
if part ~= '.' then
if part == '..' then
skip = skip + 1
elseif skip > 0 then
skip = skip - 1
else
reversed[#reversed + 1] = part
end
end
end
-- Reverse the list again to get the correct order
parts = reversed
for idx = 1, #parts / 2 do
local j = #parts - idx + 1
parts[idx], parts[j] = parts[j], parts[idx]
end
local path = joinParts(prefix, parts)
return path
end
return {
isWindows = isWindows,
getPrefix = getPrefix,
splitPath = splitPath,
joinParts = joinParts,
pathJoin = pathJoin,
}