summaryrefslogtreecommitdiff
path: root/script-beta/fs-utility.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2020-09-18 11:05:33 +0800
committer最萌小汐 <sumneko@hotmail.com>2020-09-18 11:05:33 +0800
commitfcdcc3bafdcf78fa658ca6a0bdc9badf0135c34f (patch)
tree1af4177993c37cce06594de54fcaa2dca1f78152 /script-beta/fs-utility.lua
parent2bfc21a6e65caa0c16c718c4b787e239e3d2dae4 (diff)
downloadlua-language-server-fcdcc3bafdcf78fa658ca6a0bdc9badf0135c34f.zip
更新fs-utility
Diffstat (limited to 'script-beta/fs-utility.lua')
-rw-r--r--script-beta/fs-utility.lua291
1 files changed, 265 insertions, 26 deletions
diff --git a/script-beta/fs-utility.lua b/script-beta/fs-utility.lua
index 14dcb08f..40a939ce 100644
--- a/script-beta/fs-utility.lua
+++ b/script-beta/fs-utility.lua
@@ -7,6 +7,9 @@ local pcall = pcall
local pairs = pairs
local setmetatable = setmetatable
local next = next
+local ipairs = ipairs
+local tostring = tostring
+local tableSort = table.sort
_ENV = nil
@@ -56,6 +59,177 @@ local function buildOptional(optional)
return optional
end
+local function split(str, sep)
+ local t = {}
+ local current = 1
+ while current <= #str do
+ local s, e = str:find(sep, current)
+ if not s then
+ t[#t+1] = str:sub(current)
+ break
+ end
+ if s > 1 then
+ t[#t+1] = str:sub(current, s - 1)
+ end
+ current = e + 1
+ end
+ return t
+end
+
+local dfs = {}
+dfs.__index = dfs
+dfs.type = 'dummy'
+dfs.path = ''
+
+function m.dummyFS(t)
+ return setmetatable({
+ files = t or {},
+ }, dfs)
+end
+
+function dfs:__tostring()
+ return 'dummy:' .. tostring(self.path)
+end
+
+function dfs:__div(filename)
+ if type(filename) ~= 'string' then
+ filename = filename:string()
+ end
+ local new = m.dummyFS(self.files)
+ if self.path:sub(-1):match '[^/\\]' then
+ new.path = self.path .. '\\' .. filename
+ else
+ new.path = self.path .. filename
+ end
+ return new
+end
+
+function dfs:_open(index)
+ local paths = split(self.path, '[/\\]')
+ local current = self.files
+ if not index then
+ index = #paths
+ elseif index < 0 then
+ index = #paths + index + 1
+ end
+ for i = 1, index do
+ local path = paths[i]
+ if current[path] then
+ current = current[path]
+ else
+ return nil
+ end
+ end
+ return current
+end
+
+function dfs:_filename()
+ return self.path:match '[^/\\]+$'
+end
+
+function dfs:parent_path()
+ local new = m.dummyFS(self.files)
+ if self.path:find('[/\\]') then
+ new.path = self.path:gsub('[/\\]+[^/\\]*$', '')
+ else
+ new.path = ''
+ end
+ return new
+end
+
+function dfs:filename()
+ local new = m.dummyFS(self.files)
+ new.path = self:_filename()
+ return new
+end
+
+function dfs:string()
+ return self.path
+end
+
+function dfs:list_directory()
+ local dir = self:_open()
+ if type(dir) ~= 'table' then
+ return function () end
+ end
+ local keys = {}
+ for k in pairs(dir) do
+ keys[#keys+1] = k
+ end
+ tableSort(keys)
+ local i = 0
+ return function ()
+ i = i + 1
+ local k = keys[i]
+ if not k then
+ return nil
+ end
+ return self / k
+ end
+end
+
+function dfs:isDirectory()
+ local target = self:_open()
+ if type(target) == 'table' then
+ return true
+ end
+ return false
+end
+
+function dfs:remove()
+ local dir = self:_open(-2)
+ local filename = self:_filename()
+ if not filename then
+ return
+ end
+ dir[filename] = nil
+end
+
+function dfs:exists()
+ local target = self:_open()
+ return target ~= nil
+end
+
+function dfs:createDirectories(path)
+ if type(path) ~= 'string' then
+ path = path:string()
+ end
+ local paths = split(path, '[/\\]')
+ local current = self.files
+ for i = 1, #paths do
+ local sub = paths[i]
+ if current[sub] then
+ if type(current[sub]) ~= 'table' then
+ return false
+ end
+ else
+ current[sub] = {}
+ end
+ current = current[sub]
+ end
+ return true
+end
+
+function dfs:saveFile(path, text)
+ if type(path) ~= 'string' then
+ path = path:string()
+ end
+ local temp = m.dummyFS(self.files)
+ temp.path = path
+ local dir = temp:_open(-2)
+ if not dir then
+ return false, '无法打开:' .. path
+ end
+ local filename = temp:_filename()
+ if not filename then
+ return false, '无法打开:' .. path
+ end
+ if type(dir[filename]) == 'table' then
+ return false, '无法打开:' .. path
+ end
+ dir[filename] = text
+end
+
local function fsAbsolute(path, optional)
if type(path) == 'string' then
local suc, res = pcall(fs.path, path)
@@ -64,6 +238,8 @@ local function fsAbsolute(path, optional)
return nil
end
path = res
+ elseif type(path) == 'table' then
+ return path
end
local suc, res = pcall(fs.absolute, path)
if not suc then
@@ -74,6 +250,9 @@ local function fsAbsolute(path, optional)
end
local function fsIsDirectory(path, optional)
+ if path.type == 'dummy' then
+ return path:isDirectory()
+ end
local suc, res = pcall(fs.is_directory, path)
if not suc then
optional.err[#optional.err+1] = res
@@ -83,6 +262,9 @@ local function fsIsDirectory(path, optional)
end
local function fsRemove(path, optional)
+ if path.type == 'dummy' then
+ return path:remove()
+ end
local suc, res = pcall(fs.remove, path)
if not suc then
optional.err[#optional.err+1] = res
@@ -91,6 +273,9 @@ local function fsRemove(path, optional)
end
local function fsExists(path, optional)
+ if path.type == 'dummy' then
+ return path:exists()
+ end
local suc, res = pcall(fs.exists, path)
if not suc then
optional.err[#optional.err+1] = res
@@ -99,16 +284,84 @@ local function fsExists(path, optional)
return res
end
-local function fsCopy(source, target, optional)
- local suc, res = pcall(fs.copy_file, source, target, true)
- if not suc then
- optional.err[#optional.err+1] = res
+local function fsSave(path, text, optional)
+ if path.type == 'dummy' then
+ local dir = path:_open(-2)
+ if not dir then
+ optional.err[#optional.err+1] = '无法打开:' .. path:string()
+ return false
+ end
+ local filename = path:_filename()
+ if not filename then
+ optional.err[#optional.err+1] = '无法打开:' .. path:string()
+ return false
+ end
+ if type(dir[filename]) == 'table' then
+ optional.err[#optional.err+1] = '无法打开:' .. path:string()
+ return false
+ end
+ dir[filename] = text
+ else
+ local suc, err = m.saveFile(path, text)
+ if suc then
+ return true
+ end
+ optional.err[#optional.err+1] = err
return false
end
+end
+
+local function fsLoad(path, optional)
+ if path.type == 'dummy' then
+ local text = path:_open()
+ if type(text) == 'string' then
+ return text
+ else
+ optional.err[#optional.err+1] = '无法打开:' .. path:string()
+ return nil
+ end
+ else
+ local text, err = m.loadFile(path)
+ if text then
+ return text
+ else
+ optional.err[#optional.err+1] = err
+ return nil
+ end
+ end
+end
+
+local function fsCopy(source, target, optional)
+ if source.type == 'dummy' then
+ local sourceText = source:_open()
+ if not sourceText then
+ optional.err[#optional.err+1] = '无法打开:' .. source:string()
+ return false
+ end
+ return fsSave(target, sourceText, optional)
+ else
+ if target.type == 'dummy' then
+ local sourceText, err = m.loadFile(source)
+ if not sourceText then
+ optional.err[#optional.err+1] = err
+ return false
+ end
+ return fsSave(target, sourceText, optional)
+ else
+ local suc, res = pcall(fs.copy_file, source, target, true)
+ if not suc then
+ optional.err[#optional.err+1] = res
+ return false
+ end
+ end
+ end
return true
end
local function fsCreateDirectories(path, optional)
+ if path.type == 'dummy' then
+ return path:createDirectories()
+ end
local suc, res = pcall(fs.create_directories, path)
if not suc then
optional.err[#optional.err+1] = res
@@ -136,29 +389,22 @@ local function fileCopy(source, target, optional)
local isDir2 = fsIsDirectory(target, optional)
local isExists = fsExists(target, optional)
if isDir1 then
- if isDir2 or fsCreateDirectories(target) then
+ if isDir2 or fsCreateDirectories(target, optional) then
for filePath in source:list_directory() do
- local name = filePath:filename()
+ local name = filePath:filename():string()
fileCopy(filePath, target / name, optional)
end
end
else
if isExists and not isDir2 then
- local buf1, err1 = m.loadFile(source)
- local buf2, err2 = m.loadFile(target)
+ local buf1 = fsLoad(source, optional)
+ local buf2 = fsLoad(target, optional)
if buf1 and buf2 then
if buf1 ~= buf2 then
if fsCopy(source, target, optional) then
optional.mod[#optional.mod+1] = target:string()
end
end
- else
- if not buf1 then
- optional.err[#optional.err+1] = err1
- end
- if not buf2 then
- optional.err[#optional.err+1] = err2
- end
end
else
if fsCopy(source, target, optional) then
@@ -179,7 +425,7 @@ local function fileSync(source, target, optional)
fileList[filePath] = true
end
for filePath in source:list_directory() do
- local name = filePath:filename()
+ local name = filePath:filename():string()
local targetPath = target / name
fileSync(filePath, targetPath, optional)
fileList[targetPath] = nil
@@ -193,7 +439,7 @@ local function fileSync(source, target, optional)
end
if fsCreateDirectories(target) then
for filePath in source:list_directory() do
- local name = filePath:filename()
+ local name = filePath:filename():string()
fileCopy(filePath, target / name, optional)
end
end
@@ -203,21 +449,14 @@ local function fileSync(source, target, optional)
fileRemove(target, optional)
end
if isExists then
- local buf1, err1 = m.loadFile(source)
- local buf2, err2 = m.loadFile(target)
+ local buf1 = fsLoad(source, optional)
+ local buf2 = fsLoad(target, optional)
if buf1 and buf2 then
if buf1 ~= buf2 then
if fsCopy(source, target, optional) then
optional.mod[#optional.mod+1] = target:string()
end
end
- else
- if not buf1 then
- optional.err[#optional.err+1] = err1
- end
- if not buf2 then
- optional.err[#optional.err+1] = err2
- end
end
else
if fsCopy(source, target, optional) then