|
@@ -31,35 +31,66 @@ function FileSystem.Separator()
|
|
|
return "/"
|
|
|
end
|
|
|
|
|
|
+local OS = love.system.getOS() -- Cache it, as it's not expected to change
|
|
|
+
|
|
|
+local function BackslashEscapeQuotes(Str)
|
|
|
+ return "'" .. ("\\'"):rep(#Str) .. "'"
|
|
|
+end
|
|
|
+
|
|
|
+local function EscParam(Param)
|
|
|
+ if OS == "Windows" then
|
|
|
+ -- TODO: safer parameter quoting
|
|
|
+ return '"' .. Param .. '"'
|
|
|
+ end
|
|
|
+ return "'" .. Param:gsub("'+", BackslashEscapeQuotes) .. "'"
|
|
|
+end
|
|
|
+
|
|
|
+
|
|
|
+-- Unit tests
|
|
|
+--[=====[
|
|
|
+assert(EscParam("\"abc\"'def''gh") == "'\"abc\"'\\''def'\\'\\''gh'", "fails 1")
|
|
|
+assert(EscParam("") == "''", "fails 2")
|
|
|
+-- single quotes at the beginning and end could be improved...
|
|
|
+assert(EscParam("''abc''") == "''\\'\\''abc'\\'\\'''", "fails 3")
|
|
|
+assert(EscParam("\0") == "'\0'", "fails 4")
|
|
|
+assert(EscParam("\0xyz\0xyz\0") == "'\0xyz\0xyz\0'", "fails 5")
|
|
|
+print("EscParam tests passed")
|
|
|
+--]=====]
|
|
|
+
|
|
|
+
|
|
|
function FileSystem.GetDirectoryItems(Directory, Options)
|
|
|
Options = Options == nil and {} or Options
|
|
|
Options.Files = Options.Files == nil and true or Options.Files
|
|
|
Options.Directories = Options.Directories == nil and true or Options.Directories
|
|
|
- Options.Filter = Options.Filter == nil and "*.*" or Options.Filter
|
|
|
+ Options.Filter = Options.Filter ~= nil and Options.Filter or OS == "Windows" and "*.*" or "*"
|
|
|
|
|
|
local Cmd = ""
|
|
|
- local OS = love.system.getOS()
|
|
|
|
|
|
if string.sub(Directory, #Directory, #Directory) ~= FileSystem.Separator() then
|
|
|
Directory = Directory .. FileSystem.Separator()
|
|
|
end
|
|
|
|
|
|
+ -- TODO: should ShowHidden be a user option?
|
|
|
+ local ShowHidden = false
|
|
|
+
|
|
|
if OS == "Windows" then
|
|
|
+ local HiddenStr = ShowHidden and '' or ' /A:-H'
|
|
|
Directory = string.gsub(Directory, "/", "\\")
|
|
|
if Options.Files and not Options.Directories then
|
|
|
- Cmd = 'DIR "' .. Directory .. Options.Filter .. '" /B /A:-D-H'
|
|
|
+ Cmd = 'DIR ' .. EscParam(Directory .. Options.Filter) .. ' /B /A:-D' .. HiddenStr
|
|
|
elseif Options.Directories and not Options.Files then
|
|
|
- Cmd = 'DIR "' .. Directory .. '" /B /A:D-H'
|
|
|
+ Cmd = 'DIR ' .. EscParam(Directory) .. ' /B /A:D' .. HiddenStr
|
|
|
else
|
|
|
- Cmd = 'DIR "' .. Directory .. '" /B /A-H'
|
|
|
+ Cmd = 'DIR ' .. EscParam(Directory) .. ' /B' .. HiddenStr
|
|
|
end
|
|
|
else
|
|
|
+ local HiddenStr = ShowHidden and "" or " \\( '!' -name .\\* \\)"
|
|
|
if Options.Files and not Options.Directories then
|
|
|
- Cmd = 'find "' .. Directory .. '" \\( ! -regex ".*/\\..*" \\) -maxdepth 1 -type f \\( -iname \\' .. Options.Filter .. ' \\)'
|
|
|
+ Cmd = 'find ' .. EscParam(Directory) .. " -maxdepth 1 '!' -type d -iname " .. EscParam(Options.Filter) .. HiddenStr .. ' -print0'
|
|
|
elseif Options.Directories and not Options.Files then
|
|
|
- Cmd = 'find "' .. Directory .. '" ! -path ' .. Directory .. ' \\( ! -regex ".*/\\..*" \\) -maxdepth 1 -type d'
|
|
|
+ Cmd = 'find ' .. EscParam(Directory) .. ' -mindepth 1 -maxdepth 1 -type d' .. HiddenStr .. ' -print0'
|
|
|
else
|
|
|
- Cmd = 'ls -1 ' .. Directory
|
|
|
+ Cmd = 'find ' .. EscParam(Directory) .. ' -mindepth 1 -maxdepth 1' .. HiddenStr .. ' -print0'
|
|
|
end
|
|
|
end
|
|
|
|
|
@@ -67,8 +98,14 @@ function FileSystem.GetDirectoryItems(Directory, Options)
|
|
|
local Handle, Error = io.popen(Cmd)
|
|
|
if Handle ~= nil then
|
|
|
local I = 1
|
|
|
- for Item in Handle:lines() do
|
|
|
- if Item ~= "nil" then
|
|
|
+ local Iterator
|
|
|
+ if OS == 'Windows' then
|
|
|
+ Iterator = Handle:lines()
|
|
|
+ else
|
|
|
+ Iterator = Handle:read('*all'):gmatch('%Z+')
|
|
|
+ end
|
|
|
+ for Item in Iterator do
|
|
|
+ if Item ~= "nil" or OS ~= "Windows" then
|
|
|
Result[I] = Item
|
|
|
I = I + 1
|
|
|
end
|
|
@@ -85,7 +122,6 @@ function FileSystem.Exists(Path)
|
|
|
io.close(Handle)
|
|
|
return true
|
|
|
else
|
|
|
- local OS = love.system.getOS()
|
|
|
if OS == "Windows" then
|
|
|
local OK, Error, Code = os.rename(Path, Path)
|
|
|
if OK then
|