summaryrefslogtreecommitdiff
path: root/server/src/glob
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/glob')
-rw-r--r--server/src/glob/gitignore.lua222
-rw-r--r--server/src/glob/glob.lua122
-rw-r--r--server/src/glob/init.lua4
-rw-r--r--server/src/glob/matcher.lua151
4 files changed, 0 insertions, 499 deletions
diff --git a/server/src/glob/gitignore.lua b/server/src/glob/gitignore.lua
deleted file mode 100644
index f96aa627..00000000
--- a/server/src/glob/gitignore.lua
+++ /dev/null
@@ -1,222 +0,0 @@
-local m = require 'lpeglabel'
-local matcher = require 'glob.matcher'
-
-local function prop(name, pat)
- return m.Cg(m.Cc(true), name) * pat
-end
-
-local function object(type, pat)
- return m.Ct(
- m.Cg(m.Cc(type), 'type') *
- m.Cg(pat, 'value')
- )
-end
-
-local function expect(p, err)
- return p + m.T(err)
-end
-
-local parser = m.P {
- 'Main',
- ['Sp'] = m.S(' \t')^0,
- ['Slash'] = m.S('/\\')^1,
- ['Main'] = m.Ct(m.V'Sp' * m.P'{' * m.V'Pattern' * (',' * expect(m.V'Pattern', 'Miss exp after ","'))^0 * m.P'}')
- + m.Ct(m.V'Pattern')
- + m.T'Main Failed'
- ,
- ['Pattern'] = m.Ct(m.V'Sp' * prop('neg', m.P'!') * expect(m.V'Unit', 'Miss exp after "!"'))
- + m.Ct(m.V'Unit')
- ,
- ['NeedRoot'] = prop('root', (m.P'.' * m.V'Slash' + m.V'Slash')),
- ['Unit'] = m.V'Sp' * m.V'NeedRoot'^-1 * expect(m.V'Exp', 'Miss exp') * m.V'Sp',
- ['Exp'] = m.V'Sp' * (m.V'FSymbol' + object('/', m.V'Slash') + m.V'Word')^0 * m.V'Sp',
- ['Word'] = object('word', m.Ct((m.V'CSymbol' + m.V'Char' - m.V'FSymbol')^1)),
- ['CSymbol'] = object('*', m.P'*')
- + object('?', m.P'?')
- + object('[]', m.V'Range')
- ,
- ['Char'] = object('char', (1 - m.S',{}[]*?/\\')^1),
- ['FSymbol'] = object('**', m.P'**'),
- ['Range'] = m.P'[' * m.Ct(m.V'RangeUnit'^0) * m.P']'^-1,
- ['RangeUnit'] = m.Ct(- m.P']' * m.C(m.P(1)) * (m.P'-' * - m.P']' * m.C(m.P(1)))^-1),
-}
-
----@class gitignore
-local mt = {}
-mt.__index = mt
-mt.__name = 'gitignore'
-
-function mt:addPattern(pat)
- if type(pat) ~= 'string' then
- return
- end
- self.pattern[#self.pattern+1] = pat
- if self.options.ignoreCase then
- pat = pat:lower()
- end
- local states, err = parser:match(pat)
- if not states then
- self.errors[#self.errors+1] = {
- pattern = pat,
- message = err
- }
- return
- end
- for _, state in ipairs(states) do
- self.matcher[#self.matcher+1] = matcher(state)
- end
-end
-
-function mt:setOption(op, val)
- if val == nil then
- val = true
- end
- self.options[op] = val
-end
-
----@param key string | "'type'" | "'list'"
----@param func function | "function (path) end"
-function mt:setInterface(key, func)
- if type(func) ~= 'function' then
- return
- end
- self.interface[key] = func
-end
-
-function mt:callInterface(name, ...)
- local func = self.interface[name]
- return func(...)
-end
-
-function mt:hasInterface(name)
- return self.interface[name] ~= nil
-end
-
-function mt:checkDirectory(catch, path, matcher)
- if not self:hasInterface 'type' then
- return true
- end
- if not matcher:isNeedDirectory() then
- return true
- end
- if #catch < #path then
- -- if path is 'a/b/c' and catch is 'a/b'
- -- then the catch must be a directory
- return true
- else
- return self:callInterface('type', path) == 'directory'
- end
-end
-
-function mt:simpleMatch(path)
- for i = #self.matcher, 1, -1 do
- local matcher = self.matcher[i]
- local catch = matcher(path)
- if catch and self:checkDirectory(catch, path, matcher) then
- if matcher:isNegative() then
- return false
- else
- return true
- end
- end
- end
- return nil
-end
-
-function mt:finishMatch(path)
- local paths = {}
- for filename in path:gmatch '[^/\\]+' do
- paths[#paths+1] = filename
- end
- for i = 1, #paths do
- local newPath = table.concat(paths, '/', 1, i)
- local passed = self:simpleMatch(newPath)
- if passed == true then
- return true
- elseif passed == false then
- return false
- end
- end
- return false
-end
-
-function mt:scan(callback)
- local files = {}
- if type(callback) ~= 'function' then
- callback = nil
- end
- local list = {}
- local result = self:callInterface('list', '')
- if type(result) ~= 'table' then
- return files
- end
- for _, path in ipairs(result) do
- list[#list+1] = path:match '([^/\\]+)[/\\]*$'
- end
- while #list > 0 do
- local current = list[#list]
- if not current then
- break
- end
- list[#list] = nil
- if not self:simpleMatch(current) then
- local fileType = self:callInterface('type', current)
- if fileType == 'file' then
- if callback then
- callback(current)
- end
- files[#files+1] = current
- elseif fileType == 'directory' then
- local result = self:callInterface('list', current)
- if type(result) == 'table' then
- for _, path in ipairs(result) do
- local filename = path:match '([^/\\]+)[/\\]*$'
- if filename then
- list[#list+1] = current .. '/' .. filename
- end
- end
- end
- end
- end
- end
- return files
-end
-
-function mt:__call(path)
- if self.options.ignoreCase then
- path = path:lower()
- end
- return self:finishMatch(path)
-end
-
-return function (pattern, options, interface)
- local self = setmetatable({
- pattern = {},
- options = {},
- matcher = {},
- errors = {},
- interface = {},
- }, mt)
-
- if type(pattern) == 'table' then
- for _, pat in ipairs(pattern) do
- self:addPattern(pat)
- end
- else
- self:addPattern(pattern)
- end
-
- if type(options) == 'table' then
- for op, val in pairs(options) do
- self:setOption(op, val)
- end
- end
-
- if type(interface) == 'table' then
- for key, func in pairs(interface) do
- self:setInterface(key, func)
- end
- end
-
- return self
-end
diff --git a/server/src/glob/glob.lua b/server/src/glob/glob.lua
deleted file mode 100644
index aa8923f3..00000000
--- a/server/src/glob/glob.lua
+++ /dev/null
@@ -1,122 +0,0 @@
-local m = require 'lpeglabel'
-local matcher = require 'glob.matcher'
-
-local function prop(name, pat)
- return m.Cg(m.Cc(true), name) * pat
-end
-
-local function object(type, pat)
- return m.Ct(
- m.Cg(m.Cc(type), 'type') *
- m.Cg(pat, 'value')
- )
-end
-
-local function expect(p, err)
- return p + m.T(err)
-end
-
-local parser = m.P {
- 'Main',
- ['Sp'] = m.S(' \t')^0,
- ['Slash'] = m.S('/\\')^1,
- ['Main'] = m.Ct(m.V'Sp' * m.P'{' * m.V'Pattern' * (',' * expect(m.V'Pattern', 'Miss exp after ","'))^0 * m.P'}')
- + m.Ct(m.V'Pattern')
- + m.T'Main Failed'
- ,
- ['Pattern'] = m.Ct(m.V'Sp' * prop('neg', m.P'!') * expect(m.V'Unit', 'Miss exp after "!"'))
- + m.Ct(m.V'Unit')
- ,
- ['NeedRoot'] = prop('root', (m.P'.' * m.V'Slash' + m.V'Slash')),
- ['Unit'] = m.V'Sp' * m.V'NeedRoot'^-1 * expect(m.V'Exp', 'Miss exp') * m.V'Sp',
- ['Exp'] = m.V'Sp' * (m.V'FSymbol' + object('/', m.V'Slash') + m.V'Word')^0 * m.V'Sp',
- ['Word'] = object('word', m.Ct((m.V'CSymbol' + m.V'Char' - m.V'FSymbol')^1)),
- ['CSymbol'] = object('*', m.P'*')
- + object('?', m.P'?')
- + object('[]', m.V'Range')
- ,
- ['Char'] = object('char', (1 - m.S',{}[]*?/\\')^1),
- ['FSymbol'] = object('**', m.P'**'),
- ['RangeWord'] = 1 - m.P']',
- ['Range'] = m.P'[' * m.Ct(m.V'RangeUnit'^0) * m.P']'^-1,
- ['RangeUnit'] = m.Ct(m.C(m.V'RangeWord') * m.P'-' * m.C(m.V'RangeWord'))
- + m.V'RangeWord',
-}
-
-local mt = {}
-mt.__index = mt
-mt.__name = 'glob'
-
-function mt:addPattern(pat)
- if type(pat) ~= 'string' then
- return
- end
- self.pattern[#self.pattern+1] = pat
- if self.options.ignoreCase then
- pat = pat:lower()
- end
- local states, err = parser:match(pat)
- if not states then
- self.errors[#self.errors+1] = {
- pattern = pat,
- message = err
- }
- return
- end
- for _, state in ipairs(states) do
- if state.neg then
- self.refused[#self.refused+1] = matcher(state)
- else
- self.passed[#self.passed+1] = matcher(state)
- end
- end
-end
-
-function mt:setOption(op, val)
- if val == nil then
- val = true
- end
- self.options[op] = val
-end
-
-function mt:__call(path)
- if self.options.ignoreCase then
- path = path:lower()
- end
- for _, refused in ipairs(self.refused) do
- if refused(path) then
- return false
- end
- end
- for _, passed in ipairs(self.passed) do
- if passed(path) then
- return true
- end
- end
- return false
-end
-
-return function (pattern, options)
- local self = setmetatable({
- pattern = {},
- options = {},
- passed = {},
- refused = {},
- errors = {},
- }, mt)
-
- if type(pattern) == 'table' then
- for _, pat in ipairs(pattern) do
- self:addPattern(pat)
- end
- else
- self:addPattern(pattern)
- end
-
- if type(options) == 'table' then
- for op, val in pairs(options) do
- self:setOption(op, val)
- end
- end
- return self
-end
diff --git a/server/src/glob/init.lua b/server/src/glob/init.lua
deleted file mode 100644
index 6578a0d4..00000000
--- a/server/src/glob/init.lua
+++ /dev/null
@@ -1,4 +0,0 @@
-return {
- glob = require 'glob.glob',
- gitignore = require 'glob.gitignore',
-}
diff --git a/server/src/glob/matcher.lua b/server/src/glob/matcher.lua
deleted file mode 100644
index f4c2b12c..00000000
--- a/server/src/glob/matcher.lua
+++ /dev/null
@@ -1,151 +0,0 @@
-local m = require 'lpeglabel'
-
-local Slash = m.S('/\\')^1
-local Symbol = m.S',{}[]*?/\\'
-local Char = 1 - Symbol
-local Path = Char^1 * Slash
-local NoWord = #(m.P(-1) + Symbol)
-local function whatHappened()
- return m.Cmt(m.P(1)^1, function (...)
- print(...)
- end)
-end
-
-local mt = {}
-mt.__index = mt
-mt.__name = 'matcher'
-
-function mt:exp(state, index)
- local exp = state[index]
- if not exp then
- return
- end
- if exp.type == 'word' then
- return self:word(exp, state, index + 1)
- elseif exp.type == 'char' then
- return self:char(exp, state, index + 1)
- elseif exp.type == '**' then
- return self:anyPath(exp, state, index + 1)
- elseif exp.type == '*' then
- return self:anyChar(exp, state, index + 1)
- elseif exp.type == '?' then
- return self:oneChar(exp, state, index + 1)
- elseif exp.type == '[]' then
- return self:range(exp, state, index + 1)
- elseif exp.type == '/' then
- return self:slash(exp, state, index + 1)
- end
-end
-
-function mt:word(exp, state, index)
- local current = self:exp(exp.value, 1)
- local after = self:exp(state, index)
- if after then
- return current * Slash * after
- else
- return current
- end
-end
-
-function mt:char(exp, state, index)
- local current = m.P(exp.value)
- local after = self:exp(state, index)
- if after then
- return current * after * NoWord
- else
- return current * NoWord
- end
-end
-
-function mt:anyPath(_, state, index)
- local after = self:exp(state, index)
- if after then
- return m.P {
- 'Main',
- Main = after
- + Path * m.V'Main'
- }
- else
- return Path^0
- end
-end
-
-function mt:anyChar(_, state, index)
- local after = self:exp(state, index)
- if after then
- return m.P {
- 'Main',
- Main = after
- + Char * m.V'Main'
- }
- else
- return Char^0
- end
-end
-
-function mt:oneChar(_, state, index)
- local after = self:exp(state, index)
- if after then
- return Char * after
- else
- return Char
- end
-end
-
-function mt:range(exp, state, index)
- local after = self:exp(state, index)
- local ranges = {}
- local selects = {}
- for _, range in ipairs(exp.value) do
- if #range == 1 then
- selects[#selects+1] = range[1]
- elseif #range == 2 then
- ranges[#ranges+1] = range[1] .. range[2]
- end
- end
- local current = m.S(table.concat(selects)) + m.R(table.unpack(ranges))
- if after then
- return current * after
- else
- return current
- end
-end
-
-function mt:slash(_, state, index)
- local after = self:exp(state, index)
- if after then
- return after
- else
- self.needDirectory = true
- return nil
- end
-end
-
-function mt:pattern(state)
- if state.root then
- return m.C(self:exp(state, 1))
- else
- return m.C(self:anyPath(nil, state, 1))
- end
-end
-
-function mt:isNeedDirectory()
- return self.needDirectory == true
-end
-
-function mt:isNegative()
- return self.state.neg == true
-end
-
-function mt:__call(path)
- return self.matcher:match(path)
-end
-
-return function (state, options)
- local self = setmetatable({
- options = options,
- state = state,
- }, mt)
- self.matcher = self:pattern(state)
- return self
-end