Simple tool for automatic file management
1# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
2#
3# SPDX-License-Identifier: EUPL-1.2
4let Action = [|
5 'script String,
6 'move String,
7 'echo String,
8 'trash
9|]
10in
11let NameMatch = [| 'exact String, 'wildcard String, 'regex String |] in
12let FileType = [| 'dir, 'file, 'symlink |] in
13let ContentMatch = [|
14 'mime String,
15 'magic {
16 offset | Number = 0,
17 bytes | (Array Number),
18 }
19|]
20in
21let rec Filter = [|
22 'name NameMatch,
23 'file_type FileType,
24 'size [| 'less Number, 'equal Number, 'greater Number |],
25 'content_type ContentMatch,
26 'any (Array Filter),
27 'all (Array Filter),
28 'not Filter,
29|]
30in
31{
32 Job = {
33 location
34 | String
35 | doc "Location that will be traversed for patterns",
36 filter
37 | Filter
38 | doc "File filters",
39 actions
40 | Array Action
41 | doc "Actions that should be applied to entry that matches pattern"
42 },
43
44 build | (Array Job) -> Dyn
45 =
46 let actionMatcher = match {
47 'script path => { script = path },
48 'move path => { move = path },
49 'echo msg => { echo = msg },
50 'trash => "trash",
51 }
52 in
53 let nameMatcher = match {
54 'exact val => { exact = val },
55 'wildcard val => { wildcard = val },
56 'regex val => { regex = val },
57 }
58 in
59 let rec filterMapper = match {
60 'name name => { type = "name" } & (nameMatcher name),
61 'file_type type => { type = "file_type", is = type },
62 'content_type type =>
63 type
64 |> match {
65 'mime mime => { type = "content_type", mime = mime },
66 'magic bytes => { type = "content_type", magic = bytes },
67 },
68 'size pred =>
69 let { tag, arg } = std.enum.to_tag_and_arg pred
70 in
71 {
72 type = "size",
73 size = arg,
74 ordering = tag,
75 },
76 'all allFilters =>
77 {
78 type = "all",
79 filters = std.array.map filterMapper allFilters
80 },
81 'any anyFilter =>
82 {
83 type = "any",
84 filters = std.array.map filterMapper anyFilter
85 },
86 }
87 in
88 let jobMapper = fun job =>
89 {
90 location = job.location,
91 filter = filterMapper job.filter,
92 actions = std.array.map actionMatcher job.actions,
93 }
94 in
95 std.array.map jobMapper
96}