diff --git a/ptsd.ncl b/ptsd.ncl new file mode 100644 index 0000000..6f8d2a1 --- /dev/null +++ b/ptsd.ncl @@ -0,0 +1,96 @@ +# SPDX-FileCopyrightText: 2024 Ɓukasz Niemier <#@hauleth.dev> +# +# SPDX-License-Identifier: EUPL-1.2 +let Action = [| + 'script String, + 'move String, + 'echo String, + 'trash +|] +in +let NameMatch = [| 'exact String, 'wildcard String, 'regex String |] in +let FileType = [| 'dir, 'file, 'symlink |] in +let ContentMatch = [| + 'mime String, + 'magic { + offset | Number = 0, + bytes | (Array Number), + } +|] +in +let rec Filter = [| + 'name NameMatch, + 'file_type FileType, + 'size [| 'less Number, 'equal Number, 'greater Number |], + 'content_type ContentMatch, + 'any (Array Filter), + 'all (Array Filter), + 'not Filter, +|] +in +{ + Job = { + location + | String + | doc "Location that will be traversed for patterns", + filter + | Filter + | doc "File filters", + actions + | Array Action + | doc "Actions that should be applied to entry that matches pattern" + }, + + build | (Array Job) -> Dyn + = + let actionMatcher = match { + 'script path => { script = path }, + 'move path => { move = path }, + 'echo msg => { echo = msg }, + 'trash => "trash", + } + in + let nameMatcher = match { + 'exact val => { exact = val }, + 'wildcard val => { wildcard = val }, + 'regex val => { regex = val }, + } + in + let rec filterMapper = match { + 'name name => { type = "name" } & (nameMatcher name), + 'file_type type => { type = "file_type", is = type }, + 'content_type type => + type + |> match { + 'mime mime => { type = "content_type", mime = mime }, + 'magic bytes => { type = "content_type", magic = bytes }, + }, + 'size pred => + let { tag, arg } = std.enum.to_tag_and_arg pred + in + { + type = "size", + size = arg, + ordering = tag, + }, + 'all allFilters => + { + type = "all", + filters = std.array.map filterMapper allFilters + }, + 'any anyFilter => + { + type = "any", + filters = std.array.map filterMapper anyFilter + }, + } + in + let jobMapper = fun job => + { + location = job.location, + filter = filterMapper job.filter, + actions = std.array.map actionMatcher job.actions, + } + in + std.array.map jobMapper +}