diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2020-09-18 11:05:33 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2020-09-18 11:05:33 +0800 |
commit | fcdcc3bafdcf78fa658ca6a0bdc9badf0135c34f (patch) | |
tree | 1af4177993c37cce06594de54fcaa2dca1f78152 | |
parent | 2bfc21a6e65caa0c16c718c4b787e239e3d2dae4 (diff) | |
download | lua-language-server-fcdcc3bafdcf78fa658ca6a0bdc9badf0135c34f.zip |
更新fs-utility
-rw-r--r-- | script-beta/fs-utility.lua | 291 |
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 |