summaryrefslogtreecommitdiffstatshomepage
path: root/plugins/path/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/path/init.lua')
-rw-r--r--plugins/path/init.lua139
1 files changed, 139 insertions, 0 deletions
diff --git a/plugins/path/init.lua b/plugins/path/init.lua
new file mode 100644
index 00000000000..d0e427d02ee
--- /dev/null
+++ b/plugins/path/init.lua
@@ -0,0 +1,139 @@
+--[[
+
+Copyright 2014 The Luvit Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS-IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+--]]
+
+-- Extracted from https://github.com/luvit/luvi/blob/master/src/lua/init.lua
+
+local isWindows
+if jit and jit.os then
+ -- Luajit provides explicit platform detection
+ isWindows = jit.os == "Windows"
+else
+ -- Normal lua will only have \ for path separator on windows.
+ isWindows = package.config:find("\\") and true or false
+end
+
+local uv = require('luv')
+
+local getPrefix, splitPath, joinParts
+
+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
+ -- Ignore
+ elseif part == '..' then
+ skip = skip + 1
+ elseif skip > 0 then
+ skip = skip - 1
+ else
+ reversed[#reversed + 1] = part
+ 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,
+ join = pathJoin,
+ getPrefix = getPrefix,
+ splitPath = splitPath,
+ joinparts = joinParts,
+}