Commit
+82 -1 +/-3 browse
1 | diff --git a/lib/cmd.ml b/lib/cmd.ml |
2 | index fec8dd6..2b5aae3 100644 |
3 | --- a/lib/cmd.ml |
4 | +++ b/lib/cmd.ml |
5 | @@ -249,6 +249,13 @@ let sync = |
6 | Command.basic ~summary:"sync notes to a remote server" |
7 | (Command.Param.return (fun () -> Sync.sync cfg.on_sync)) |
8 | |
9 | + let tree = |
10 | + Command.basic ~summary:"tree debug command" |
11 | + (Command.Param.return (fun () -> |
12 | + let notes = get_notes in |
13 | + print_endline (sprintf "%d" (List.length notes)); |
14 | + Note.dump_tree notes)) |
15 | + |
16 | let version = |
17 | match Build_info.V1.version () with |
18 | | None -> "n/a" |
19 | @@ -268,4 +275,5 @@ let run = |
20 | ("edit", edit_note); |
21 | ("ls", list_notes); |
22 | ("sync", sync); |
23 | + ("tree", tree); |
24 | ]) |
25 | diff --git a/lib/note.ml b/lib/note.ml |
26 | index 607e3dc..f90f9cc 100644 |
27 | --- a/lib/note.ml |
28 | +++ b/lib/note.ml |
29 | @@ -16,6 +16,27 @@ and note = { |
30 | parent : term option; |
31 | } |
32 | |
33 | + let operator_of_string = function |
34 | + | "Or" -> Or |
35 | + | "And" -> And |
36 | + | _ -> failwith "invalid operator" |
37 | + |
38 | + let term_of_json json = |
39 | + let titles = |
40 | + match Ezjsonm.find_opt json [ "titles" ] with |
41 | + | Some titles -> List.map ~f:Re.Str.regexp (Ezjsonm.get_strings titles) |
42 | + | None -> [] |
43 | + and tags = |
44 | + match Ezjsonm.find_opt json [ "tags" ] with |
45 | + | Some tags -> List.map ~f:Re.Str.regexp (Ezjsonm.get_strings tags) |
46 | + | None -> [] |
47 | + and operator = |
48 | + match Ezjsonm.find_opt json [ "operator" ] with |
49 | + | Some operator -> operator_of_string (Ezjsonm.get_string operator) |
50 | + | None -> Or |
51 | + in |
52 | + { titles; tags; operator } |
53 | + |
54 | let build ?(description = "") ?(tags = []) ?(content = "") ~title slug = |
55 | let frontmatter = |
56 | Ezjsonm.dict |
57 | @@ -96,13 +117,17 @@ let of_string ~content slug = |
58 | "frontmatter is a partial fragment, should be either a dictionary \ |
59 | or list" |
60 | in |
61 | + let parent = Ezjsonm.find_opt (Ezjsonm.value frontmatter) [ "parent" ] in |
62 | + let parent = |
63 | + match parent with Some json -> Some (term_of_json json) | None -> None |
64 | + in |
65 | let markdown : Omd.doc = |
66 | Omd.of_string |
67 | (String.slice content |
68 | (List.nth_exn indexes 1 + 3) |
69 | (String.length content)) |
70 | in |
71 | - { frontmatter; content; markdown; slug; parent = None } |
72 | + { frontmatter; content; markdown; slug; parent } |
73 | else |
74 | let frontmatter = Ezjsonm.dict [] in |
75 | let markdown = Omd.of_string content in |
76 | @@ -176,6 +201,48 @@ let find_one ~term notes = |
77 | let results = find_many ~term notes in |
78 | match List.length results with 0 -> None | _ -> Some (List.hd_exn results) |
79 | |
80 | + let find_one_exn ~term notes = |
81 | + let result = find_one ~term notes in |
82 | + match result with |
83 | + | Some result -> result |
84 | + | None -> failwith "not found" |
85 | + |
86 | + (* TODO terrible performance but who cares? *) |
87 | + let resolve tree notes = |
88 | + List.fold ~init:tree |
89 | + ~f:(fun accm note -> |
90 | + let slug_id = Slug.to_string note.slug in |
91 | + match note.parent with |
92 | + | Some term -> ( |
93 | + match find_one ~term notes with |
94 | + | Some parent -> ( |
95 | + let parent_slug_id = Slug.to_string parent.slug in |
96 | + let children = |
97 | + List.Assoc.find ~equal:String.equal accm parent_slug_id |
98 | + in |
99 | + match children with |
100 | + | Some children -> |
101 | + List.Assoc.add ~equal:String.equal accm parent_slug_id |
102 | + (List.append children [ slug_id ]) |
103 | + | None -> |
104 | + List.Assoc.add ~equal:String.equal accm parent_slug_id |
105 | + [ slug_id ]) |
106 | + | None -> failwith "cannot resolve parent") |
107 | + | None -> |
108 | + if List.Assoc.mem ~equal:String.equal accm slug_id then accm |
109 | + else List.Assoc.add ~equal:String.equal accm slug_id []) |
110 | + notes |
111 | + |
112 | + type node = Node of (note option * note list) |
113 | + |
114 | + let dump_tree notes = |
115 | + let tree = resolve [] notes in |
116 | + let tree = resolve tree notes in |
117 | + List.iter |
118 | + ~f:(fun (key, values) -> |
119 | + print_endline (key ^ sprintf " -> %d" (List.length values))) |
120 | + tree |
121 | + |
122 | open ANSITerminal |
123 | |
124 | let paint_tag (styles : Config.StylePair.t list) text : string = |
125 | diff --git a/lib/slug.ml b/lib/slug.ml |
126 | index ef4cef7..b01a9b0 100644 |
127 | --- a/lib/slug.ml |
128 | +++ b/lib/slug.ml |
129 | @@ -2,6 +2,12 @@ open Core |
130 | |
131 | type t = { path : string; date : Date.t; index : int } |
132 | |
133 | + let compare s1 s2 = |
134 | + String.compare s1.path s2.path |
135 | + |
136 | + let sexp_of_t t : Sexp.t = |
137 | + List [ Atom t.path ] |
138 | + |
139 | let get_path t = t.path |
140 | |
141 | let to_string t = |