1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
open Printf
open Storage.Secrets
type t =
| D of node list
| F of unit outcome
and node = string * t
type top = Top of node
let ext_filt ext base nm sub =
let full = Fpath.add_seg base nm in
let s = Fpath.to_string full in
try
if Sys.is_directory s then (
let sf = sub full in
Some (nm, D sf))
else if FileUtil.test FileUtil.Is_file s && Fpath.has_ext ext full then (
let name = name_of_file (Path.of_fpath full) in
let res =
try
match is_recipient_of_secret (get_own_key ()) name with
| false -> Skipped
| true ->
match decrypt_exn ~silence_stderr:true name with
| exception exn -> Failed exn
| _ -> Succeeded ()
with _ -> Skipped
in
Some (Fpath.(to_string @@ rem_ext (v nm)), F res))
else None
with _ -> None
let of_path path =
let rec sub p =
let names = Sys.readdir (Fpath.to_string p) in
Array.sort compare names;
names |> Array.to_list |> List.filter_map (fun v -> ext_filt ext p v sub)
in
let sp = sub path in
Top (Fpath.to_string path, D sp)
let bar = "│ "
let mid = "├── "
let el = "└── "
let space = " "
let to_pref_str is_last_l =
let rec p_aux acc d =
match d with
| [] -> String.concat "" acc
| v :: rest -> p_aux ((if v then space else bar) :: acc) rest
in
match is_last_l with
| v :: rest -> if v then p_aux [ el ] rest else p_aux [ mid ] rest
| [] -> ""
let p buf d s =
Buffer.add_string buf (to_pref_str d);
Buffer.add_string buf s;
Buffer.add_char buf '\n'
let rec iter_but_one f lastf l =
match l with
| [] -> ()
| [ i ] -> lastf i
| i :: rest ->
let () = f i in
iter_but_one f lastf rest
let red = "31"
let blue = "34"
let green = "32"
let color c s = sprintf "\027[01;%sm%s\027[00m" c s
let rec pp_node buf d n =
match n with
| nm, F r ->
(match r with
| Succeeded _ -> p buf d (color green nm)
| Failed _ -> p buf d (color red nm)
| _ -> p buf d nm)
| nm, D nl ->
let () = p buf d (color blue nm) in
iter_but_one (pp_node buf (false :: d)) (pp_node buf (true :: d)) nl
let pp t =
let buf = Buffer.create 256 in
match t with
| Top (_, D l) ->
Buffer.add_string buf ".\n";
iter_but_one (pp_node buf [ false ]) (pp_node buf [ true ]) l;
Buffer.contents buf
| Top (_, F _) -> ""