summaryrefslogtreecommitdiff
path: root/script-beta/fs-utility.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2020-11-20 21:57:09 +0800
committer最萌小汐 <sumneko@hotmail.com>2020-11-20 21:57:09 +0800
commit4ca61ec457822dd14966afa0752340ae8ce180a1 (patch)
treeae8adb1ad82c717868e551e699fd3cf3bb290089 /script-beta/fs-utility.lua
parentc63b2e404d8d2bb984afe3678a5ba2b2836380cc (diff)
downloadlua-language-server-4ca61ec457822dd14966afa0752340ae8ce180a1.zip
no longer beta
Diffstat (limited to 'script-beta/fs-utility.lua')
-rw-r--r--script-beta/fs-utility.lua559
1 files changed, 0 insertions, 559 deletions
diff --git a/script-beta/fs-utility.lua b/script-beta/fs-utility.lua
deleted file mode 100644
index 42041734..00000000
--- a/script-beta/fs-utility.lua
+++ /dev/null
@@ -1,559 +0,0 @@
-local fs = require 'bee.filesystem'
-local platform = require 'bee.platform'
-
-local type = type
-local ioOpen = io.open
-local pcall = pcall
-local pairs = pairs
-local setmetatable = setmetatable
-local next = next
-local ipairs = ipairs
-local tostring = tostring
-local tableSort = table.sort
-
-_ENV = nil
-
-local m = {}
---- 读取文件
----@param path string
-function m.loadFile(path)
- if type(path) ~= 'string' then
- path = path:string()
- end
- local f, e = ioOpen(path, 'rb')
- if not f then
- return nil, e
- end
- if f:read(3) ~= '\xEF\xBB\xBF' then
- f:seek("set")
- end
- local buf = f:read 'a'
- f:close()
- return buf
-end
-
---- 写入文件
----@param path string
----@param content string
-function m.saveFile(path, content)
- if type(path) ~= 'string' then
- path = path:string()
- end
- local f, e = ioOpen(path, "wb")
-
- if f then
- f:write(content)
- f:close()
- return true
- else
- return false, e
- end
-end
-
-local function buildOptional(optional)
- optional = optional or {}
- optional.add = optional.add or {}
- optional.del = optional.del or {}
- optional.mod = optional.mod or {}
- optional.err = optional.err or {}
- 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)
- if not suc then
- optional.err[#optional.err+1] = res
- return nil
- end
- path = res
- elseif type(path) == 'table' then
- return path
- end
- local suc, res = pcall(fs.absolute, path)
- if not suc then
- optional.err[#optional.err+1] = res
- return nil
- end
- return res
-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
- return false
- end
- return res
-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
- end
- optional.del[#optional.del+1] = path:string()
-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
- return false
- end
- return res
-end
-
-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
- return false
- end
- return true
-end
-
-local function fileRemove(path, optional)
- if optional.onRemove and optional.onRemove(path) == false then
- return
- end
- if fsIsDirectory(path, optional) then
- for child in path:list_directory() do
- fileRemove(child, optional)
- end
- end
- if fsRemove(path, optional) then
- optional.del[#optional.del+1] = path:string()
- end
-end
-
-local function fileCopy(source, target, optional)
- if optional.onCopy and optional.onCopy(source, target) == false then
- return
- end
- local isDir1 = fsIsDirectory(source, optional)
- local isDir2 = fsIsDirectory(target, optional)
- local isExists = fsExists(target, optional)
- if isDir1 then
- if isDir2 or fsCreateDirectories(target, optional) then
- for filePath in source:list_directory() do
- local name = filePath:filename():string()
- fileCopy(filePath, target / name, optional)
- end
- end
- else
- if isExists and not isDir2 then
- 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
- end
- else
- if fsCopy(source, target, optional) then
- optional.add[#optional.add+1] = target:string()
- end
- end
- end
-end
-
-local function fileSync(source, target, optional)
- if optional.onSync and optional.onSync(source, target) == false then
- return
- end
- local isDir1 = fsIsDirectory(source, optional)
- local isDir2 = fsIsDirectory(target, optional)
- local isExists = fsExists(target, optional)
- if isDir1 then
- if isDir2 then
- local fileList = m.fileList()
- for filePath in target:list_directory() do
- fileList[filePath] = true
- end
- for filePath in source:list_directory() do
- local name = filePath:filename():string()
- local targetPath = target / name
- fileSync(filePath, targetPath, optional)
- fileList[targetPath] = nil
- end
- for path in pairs(fileList) do
- fileRemove(path, optional)
- end
- else
- if isExists then
- fileRemove(target, optional)
- end
- if fsCreateDirectories(target) then
- for filePath in source:list_directory() do
- local name = filePath:filename():string()
- fileCopy(filePath, target / name, optional)
- end
- end
- end
- else
- if isDir2 then
- fileRemove(target, optional)
- end
- if isExists then
- 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
- end
- else
- if fsCopy(source, target, optional) then
- optional.add[#optional.add+1] = target:string()
- end
- end
- end
-end
-
---- 文件列表
-function m.fileList(optional)
- optional = optional or buildOptional(optional)
- local os = platform.OS
- local keyMap = {}
- local fileList = {}
- local function computeKey(path)
- path = fsAbsolute(path, optional)
- if not path then
- return nil
- end
- local key
- if os == 'Windows' then
- key = path:string():lower()
- else
- key = path:string()
- end
- return key
- end
- return setmetatable({}, {
- __index = function (_, path)
- local key = computeKey(path)
- return fileList[key]
- end,
- __newindex = function (_, path, value)
- local key = computeKey(path)
- if not key then
- return
- end
- if value == nil then
- keyMap[key] = nil
- else
- keyMap[key] = path
- fileList[key] = value
- end
- end,
- __pairs = function ()
- local key, path
- return function ()
- key, path = next(keyMap, key)
- return path, fileList[key]
- end
- end,
- })
-end
-
---- 删除文件(夹)
-function m.fileRemove(path, optional)
- optional = buildOptional(optional)
- path = fsAbsolute(path, optional)
-
- fileRemove(path, optional)
-
- return optional
-end
-
---- 复制文件(夹)
----@param source string
----@param target string
----@return table
-function m.fileCopy(source, target, optional)
- optional = buildOptional(optional)
- source = fsAbsolute(source, optional)
- target = fsAbsolute(target, optional)
-
- fileCopy(source, target, optional)
-
- return optional
-end
-
---- 同步文件(夹)
----@param source string
----@param target string
----@return table
-function m.fileSync(source, target, optional)
- optional = buildOptional(optional)
- source = fsAbsolute(source, optional)
- target = fsAbsolute(target, optional)
-
- fileSync(source, target, optional)
-
- return optional
-end
-
-return m