Commit
+81 -90 +/-5 browse
1 | diff --git a/bin/note.ml b/bin/note.ml |
2 | index e88536d..eb988cf 100644 |
3 | --- a/bin/note.ml |
4 | +++ b/bin/note.ml |
5 | @@ -5,16 +5,16 @@ open Note_lib |
6 | |
7 | let cfg = Config.config_path |> Config.load |
8 | |
9 | - let options : Note.Adapter.options = |
10 | + let options : Note.options = |
11 | { |
12 | state_dir = cfg.state_dir; |
13 | on_modification = cfg.on_modification; |
14 | editor = cfg.editor; |
15 | } |
16 | |
17 | - let get_title (note : Note.note) = note.frontmatter.path |
18 | + let get_title (note : Note.t) = (note |> Note.frontmatter).path |
19 | |
20 | - let get_tags (note : Note.note) = note.frontmatter.tags |
21 | + let get_tags (note : Note.t) = (note |> Note.frontmatter).tags |
22 | |
23 | let to_keys ~kind notes = |
24 | match kind with |
25 | @@ -77,7 +77,7 @@ is provided then all notes will be listed. |
26 | fun () -> |
27 | let paths = match paths with [] -> [ "/" ] | paths -> paths in |
28 | paths |
29 | - |> List.map ~f:(fun path -> options |> Note.Adapter.load ~path) |
30 | + |> List.map ~f:(fun path -> options |> Note.load ~path) |
31 | |> List.iter ~f:(fun notes -> |
32 | let note = notes |> Note.fst in |
33 | note |> Note.to_string |> print_endline)] |
34 | @@ -105,7 +105,7 @@ on_modification callback will be invoked if the file is committed to disk. |
35 | | Some _ -> Some (In_channel.stdin |> In_channel.input_all) |
36 | | None -> None |
37 | in |
38 | - options |> Note.Adapter.create ~description ~tags ~content ~path] |
39 | + options |> Note.create ~description ~tags ~content ~path] |
40 | |
41 | let remove_note = |
42 | let open Command.Let_syntax in |
43 | @@ -114,10 +114,12 @@ let remove_note = |
44 | [%map_open |
45 | let path = anon ("path" %: name_arg) in |
46 | fun () -> |
47 | - let message = (Format.sprintf "Are you sure you want to delete note %s?" path) in |
48 | - match options |> Note.Adapter.find ~path with |
49 | + let message = |
50 | + Format.sprintf "Are you sure you want to delete note %s?" path |
51 | + in |
52 | + match options |> Note.find ~path with |
53 | | Some _ -> |
54 | - let callback () = options |> Note.Adapter.remove ~path in |
55 | + let callback () = options |> Note.remove ~path in |
56 | Util.prompt ~callback message |
57 | | None -> failwith "not found"] |
58 | |
59 | @@ -134,7 +136,7 @@ Select a note that matches the filter criteria and open it in your text editor. |
60 | and _ = |
61 | flag "description" (optional_with_default "" string) ~doc:"description" |
62 | in |
63 | - fun () -> options |> Note.Adapter.edit ~path] |
64 | + fun () -> options |> Note.edit ~path] |
65 | |
66 | let list_notes = |
67 | let open Command.Let_syntax in |
68 | @@ -149,7 +151,7 @@ is provided then all notes will be listed. |
69 | fun () -> |
70 | let paths = match paths with [] -> [ "/" ] | paths -> paths in |
71 | paths |
72 | - |> List.map ~f:(fun path -> options |> Note.Adapter.load ~path) |
73 | + |> List.map ~f:(fun path -> options |> Note.load ~path) |
74 | |> List.iter ~f:(fun notes -> |
75 | notes |> Display.convert_tree |> Display.Hierarchical.to_string |
76 | |> print_endline)] |
77 | diff --git a/lib/display.ml b/lib/display.ml |
78 | index 408a575..37f468f 100644 |
79 | --- a/lib/display.ml |
80 | +++ b/lib/display.ml |
81 | @@ -15,7 +15,7 @@ module Tabular = struct |
82 | | Some entry -> sprintf entry.styles "%s" text |
83 | | None -> sprintf [ Foreground Default ] "%s" text |
84 | |
85 | - let to_cells ?(paint = false) ~columns ~styles (notes : Note.note list) = |
86 | + let to_cells ?(paint = false) ~columns ~styles (notes : Note.t list) = |
87 | let header = |
88 | List.map |
89 | ~f:(fun column -> |
90 | @@ -38,21 +38,21 @@ module Tabular = struct |
91 | ~f:(fun column -> |
92 | match column with |
93 | | `Title -> |
94 | - let text_value = note.frontmatter.path in |
95 | + let text_value = (note |> Note.frontmatter).path in |
96 | (text_value, String.length text_value, default_padding) |
97 | | `Description -> |
98 | let text_value = |
99 | - match note.frontmatter.description with |
100 | + match (note |> Note.frontmatter).description with |
101 | | Some text_value -> text_value |
102 | | None -> "" |
103 | in |
104 | (text_value, String.length text_value, default_padding) |
105 | | `Tags -> |
106 | let text_value = |
107 | - String.concat ~sep:"|" note.frontmatter.tags |
108 | + String.concat ~sep:"|" (note |> Note.frontmatter).tags |
109 | in |
110 | let text_length = String.length text_value in |
111 | - let tags = note.frontmatter.tags in |
112 | + let tags = (note |> Note.frontmatter).tags in |
113 | let tags = |
114 | if paint then |
115 | List.map ~f:(fun tag -> paint_tag styles tag) tags |
116 | @@ -62,7 +62,7 @@ module Tabular = struct |
117 | (text_value, text_length, default_padding) |
118 | | `LineCount -> |
119 | let count = |
120 | - note.content |> String.split_lines |> List.length |
121 | + note |> Note.content |> String.split_lines |> List.length |
122 | in |
123 | let text_value = count |> Core.sprintf "%d" in |
124 | (text_value, String.length text_value, default_padding)) |
125 | @@ -185,7 +185,7 @@ end |
126 | |
127 | let rec convert_tree tree = |
128 | let (Note.Tree (note, others)) = tree in |
129 | - let title = Filename.basename note.frontmatter.path in |
130 | + let title = Filename.basename (note |> Note.frontmatter).path in |
131 | let title = "[" ^ title ^ "]" in |
132 | Hierarchical.Tree (title, List.map ~f:convert_tree others) |
133 | |
134 | diff --git a/lib/note.ml b/lib/note.ml |
135 | index ca90229..831ea96 100644 |
136 | --- a/lib/note.ml |
137 | +++ b/lib/note.ml |
138 | @@ -41,9 +41,13 @@ module Frontmatter = struct |
139 | content |> Ezjsonm.dict |
140 | end |
141 | |
142 | - type note = { frontmatter : Frontmatter.t; content : string } |
143 | + type t = { frontmatter : Frontmatter.t; content : string } |
144 | |
145 | - and tree = Tree of (note * tree list) |
146 | + and tree = Tree of (t * tree list) |
147 | + |
148 | + let frontmatter note = note.frontmatter |
149 | + |
150 | + let content note = note.content |
151 | |
152 | let fst tree = |
153 | let (Tree (note, _)) = tree in |
154 | @@ -60,7 +64,7 @@ tags: [] |
155 | # This is a Note! |
156 | |} |
157 | |
158 | - let rec flatten ~accm tree = |
159 | + let rec flatten ?(accm = []) tree = |
160 | let (Tree (note, others)) = tree in |
161 | List.fold ~init:(note :: accm) ~f:(fun accm note -> flatten ~accm note) others |
162 | |
163 | @@ -110,7 +114,7 @@ let of_string ?(path = None) content = |
164 | meta_str |> Yaml.of_string_exn |> Frontmatter.of_json ~path |
165 | in |
166 | (* read second half of note as "content" *) |
167 | - let content = String.slice content ((List.nth_exn indexes 1)+3) 0 in |
168 | + let content = String.slice content (List.nth_exn indexes 1 + 3) 0 in |
169 | { frontmatter; content } |
170 | else { frontmatter = Frontmatter.empty; content } |
171 | |
172 | @@ -227,3 +231,5 @@ module Adapter = struct |
173 | options.on_modification |> run_or_noop |
174 | | None -> failwith "not found" |
175 | end |
176 | + |
177 | + include Adapter |
178 | diff --git a/lib/note.mli b/lib/note.mli |
179 | new file mode 100644 |
180 | index 0000000..377c501 |
181 | --- /dev/null |
182 | +++ b/lib/note.mli |
183 | @@ -0,0 +1,42 @@ |
184 | + module Frontmatter : sig |
185 | + type t = { path : string; description : string option; tags : string list } |
186 | + end |
187 | + |
188 | + type t |
189 | + |
190 | + type tree = Tree of (t * tree list) |
191 | + |
192 | + val fst : tree -> t |
193 | + |
194 | + type options = { |
195 | + state_dir : string; |
196 | + editor : string; |
197 | + on_modification : string option; |
198 | + } |
199 | + |
200 | + val to_string : t -> string |
201 | + |
202 | + val of_string : ?path:string option -> string -> t |
203 | + |
204 | + val to_json : t -> Ezjsonm.value |
205 | + |
206 | + val frontmatter : t -> Frontmatter.t |
207 | + val content : t -> string |
208 | + |
209 | + val flatten : ?accm:t list -> tree -> t list |
210 | + |
211 | + val load : path:string -> options -> tree |
212 | + |
213 | + val find : path:string -> options -> t option |
214 | + |
215 | + val create : |
216 | + ?description:string option -> |
217 | + ?tags:string list -> |
218 | + ?content:string option -> |
219 | + path:string -> |
220 | + options -> |
221 | + unit |
222 | + |
223 | + val remove : path:string -> options -> unit |
224 | + |
225 | + val edit : path:string -> options -> unit |
226 | diff --git a/test/note_test.ml b/test/note_test.ml |
227 | index 919e08b..e2d5857 100644 |
228 | --- a/test/note_test.ml |
229 | +++ b/test/note_test.ml |
230 | @@ -10,91 +10,34 @@ description: "baz" |
231 | --- |
232 | # Hello World|} in |
233 | let n1 = n1 |> Note.of_string in |
234 | - Alcotest.(check string) "path" "/fuu" n1.frontmatter.path ; |
235 | - let tag = n1.frontmatter.tags |> List.hd_exn in |
236 | + Alcotest.(check string) "path" "/fuu" (n1 |> Note.frontmatter).path ; |
237 | + let tag = (n1 |> Note.frontmatter).tags |> List.hd_exn in |
238 | Alcotest.(check string) "tag" "bar" tag ; |
239 | - let description = (Option.value_exn n1.frontmatter.description) in |
240 | + let description = (Option.value_exn (n1 |> Note.frontmatter).description) in |
241 | Alcotest.(check string) "description" "baz" description ; |
242 | - let content = n1.content in |
243 | + let content = (n1 |> Note.content) in |
244 | Alcotest.(check string) "content" "\n# Hello World" content |
245 | |
246 | |
247 | - let load_manifest () = |
248 | - let state_dir = Filename.temp_dir "note-test" "" in |
249 | - let manifest = Manifest.load_or_init state_dir in |
250 | - let note_root = |
251 | - Note.of_string |
252 | - {| |
253 | - --- |
254 | - path: "/" |
255 | - description: "all notes desend from here" |
256 | - tags: [] |
257 | - --- |
258 | - # Root Note |
259 | - |} |
260 | - in |
261 | - let note_0 = |
262 | - Note.of_string |
263 | - {| |
264 | - --- |
265 | - path: "/note-0" |
266 | - description: "this is a note" |
267 | - tags: ["fuu", "bar"] |
268 | - --- |
269 | - |} |
270 | - in |
271 | - let note_1 = |
272 | - Note.of_string |
273 | - {| |
274 | - --- |
275 | - path: "/note-0/note-1" |
276 | - description: "this is another note" |
277 | - tags: ["baz", "qux"] |
278 | - --- |
279 | - |} |
280 | - in |
281 | - let manifest = manifest |> Manifest.create ~path:"/" in |
282 | - let item = manifest.items |> List.hd_exn in |
283 | - let slug = item.slug |> Slug.to_string in |
284 | - Out_channel.write_all ~data:(note_root |> Note.to_string) slug; |
285 | - let manifest = manifest |> Manifest.create ~path:"/note-0" in |
286 | - let item = manifest.items |> List.hd_exn in |
287 | - let slug = item.slug |> Slug.to_string in |
288 | - Out_channel.write_all ~data:(note_0 |> Note.to_string) slug; |
289 | - manifest |> Manifest.save; |
290 | - let manifest = manifest |> Manifest.create ~path:"/note-0/note-1" in |
291 | - let item = manifest.items |> List.hd_exn in |
292 | - let slug = item.slug |> Slug.to_string in |
293 | - Out_channel.write_all ~data:(note_1 |> Note.to_string) slug; |
294 | - manifest |> Manifest.save; |
295 | - let manifest = Manifest.load_or_init state_dir in |
296 | - let root = |
297 | - Note.Tree |
298 | - ( Note.of_string ~path:(Some "/") Note.root_template, |
299 | - Note.resolve_manifest ~path:"/" manifest ) |
300 | - in |
301 | - let (Note.Tree (_, others)) = root in |
302 | - Alcotest.(check int) "one" 1 (others |> List.length) |
303 | - |
304 | let adapter () = |
305 | - let options : Note.Adapter.options = |
306 | + let options : Note.options = |
307 | { |
308 | state_dir = Filename.temp_dir "note-test" ""; |
309 | editor = "true"; |
310 | on_modification = None; |
311 | } |
312 | in |
313 | - let tree = options |> Note.Adapter.load ~path:"/" in |
314 | + let tree = options |> Note.load ~path:"/" in |
315 | Alcotest.(check int) |
316 | "initialized" 1 |
317 | (tree |> Note.flatten ~accm:[] |> List.length); |
318 | - options |> Note.Adapter.create ~content:(Some "bar") ~path:"/fuu"; |
319 | - let tree = options |> Note.Adapter.load ~path:"/" in |
320 | + options |> Note.create ~content:(Some "bar") ~path:"/fuu"; |
321 | + let tree = options |> Note.load ~path:"/" in |
322 | Alcotest.(check int) |
323 | "note added" 2 |
324 | (tree |> Note.flatten ~accm:[] |> List.length); |
325 | - options |> Note.Adapter.remove ~path:"/fuu"; |
326 | - let tree = options |> Note.Adapter.load ~path:"/" in |
327 | + options |> Note.remove ~path:"/fuu"; |
328 | + let tree = options |> Note.load ~path:"/" in |
329 | Alcotest.(check int) |
330 | "note removed" 1 |
331 | (tree |> Note.flatten ~accm:[] |> List.length) |
332 | @@ -103,7 +46,5 @@ let () = |
333 | Alcotest.run "Note" |
334 | [ |
335 | ("parse", [ Alcotest.test_case "parse" `Quick parsing ]); |
336 | - ( "load_manifest", |
337 | - [ Alcotest.test_case "load manifest" `Quick load_manifest ] ); |
338 | ("adapter", [ Alcotest.test_case "adapter" `Quick adapter ]); |
339 | ] |