summaryrefslogtreecommitdiff
path: root/server/src/path_filter.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/path_filter.lua')
-rw-r--r--server/src/path_filter.lua68
1 files changed, 68 insertions, 0 deletions
diff --git a/server/src/path_filter.lua b/server/src/path_filter.lua
new file mode 100644
index 00000000..2a362677
--- /dev/null
+++ b/server/src/path_filter.lua
@@ -0,0 +1,68 @@
+local m = require 'lpeglabel'
+
+local m_cut = m.S'/\\'
+local m_path = (1-m_cut)^1
+
+local function match_any(p, pass)
+ return m.P{p + pass * m.V(1)}
+end
+
+local function compile_format(fmt)
+ local function next(cur)
+ local pos, fn = fmt:find('%*+', cur)
+ if not pos then
+ return m.P(fmt:sub(cur)) * -1
+ end
+ local word = m.P(fmt:sub(cur, pos-1))
+ return word * match_any(next(fn+1), 1)
+ end
+ return next(1)
+end
+
+local function compile_exp(exp)
+ if exp:sub(1, 1) == '/' then
+ exp = exp:sub(2)
+ else
+ exp = '**/' .. exp
+ end
+ local function next(cur)
+ local pos, fn = exp:find('[/\\]+', cur)
+ if not pos then
+ return compile_format(exp:sub(cur))
+ end
+ local fmt = exp:sub(cur, pos-1)
+ if fmt == '**' then
+ return match_any(next(fn+1), m_path * m_cut)
+ elseif fmt == '' then
+ return m_cut
+ else
+ if fn < #exp then
+ return m.P(fmt) * m_cut * next(fn+1)
+ else
+ return m.P(fmt) * m_cut
+ end
+ end
+ end
+ return next(1)
+end
+
+local function compile_exps(exp)
+ local matcher
+ for _, exp in ipairs(exp) do
+ exp = exp:lower()
+ if matcher then
+ matcher = matcher + compile_exp(exp)
+ else
+ matcher = compile_exp(exp)
+ end
+ end
+ return matcher
+end
+
+return function (exp)
+ local matcher = compile_exps(exp)
+ return function (path)
+ local filename = path:lower()
+ return not not matcher:match(filename)
+ end
+end