Author: Kevin Schoon [kevinschoon@gmail.com]
Hash: 7c0b5b759050885799b82f7bbb180c09883c59d4
Timestamp: Wed, 02 Sep 2020 18:59:48 +0000 (4 years ago)

+78 -93 +/-6 browse
refactor note as a (Ezjsonm.t * Omd.t)
1diff --git a/dune-project b/dune-project
2index 3adfbb4..5c9ec06 100644
3--- a/dune-project
4+++ b/dune-project
5 @@ -1,28 +1,2 @@
6 (lang dune 2.7)
7-
8 (name note)
9- (version 0.0.2)
10-
11- (generate_opam_files true)
12-
13- (source (github kevinschoon/note))
14- (license AGPL3)
15- (authors "Kevin Schoon <kevinschoon@gmail.com>")
16- (maintainers "Kevin Schoon <kevinschoon@gmail.com>")
17-
18- (package
19- (name note)
20- (synopsis "Note is a simple CLI based note taking program")
21- (description "Note is a simple CLI based note taking program")
22- (depends
23- (base
24- (>= v0.14.0))
25- (core
26- (>= v0.14.0))
27- (dune
28- (>= 2.7))
29- (ezjsonm
30- (>= 1.2.0))
31- (stdio ( >= v0.14.0))
32- (yaml
33- (>= 2.1.0))))
34 diff --git a/lib/cmd.ml b/lib/cmd.ml
35index c39a005..a3729b2 100644
36--- a/lib/cmd.ml
37+++ b/lib/cmd.ml
38 @@ -25,15 +25,15 @@ let encode_value value = function
39 | Json -> (
40 match value with
41 | Config config -> Ezjsonm.to_string (Config.to_json config)
42- | Note note -> Ezjsonm.to_string (Note.to_json ~note) )
43+ | Note note -> Ezjsonm.to_string (Note.to_json note) )
44 | Yaml -> (
45 match value with
46 | Config config -> Yaml.to_string_exn (Config.to_json config)
47- | Note note -> Yaml.to_string_exn (Note.to_json ~note) )
48+ | Note note -> Yaml.to_string_exn (Note.to_json note) )
49 | Text -> (
50 match value with
51 | Config config -> Config.to_string config
52- | Note note -> Note.to_string ~note )
53+ | Note note -> Note.to_string note )
54
55 let create_note =
56 let open Command.Let_syntax in
57 @@ -66,13 +66,13 @@ let create_note =
58 | Some _ ->
59 (* reading from stdin so write directly to note *)
60 let content = In_channel.input_all In_channel.stdin in
61- let note = Note.build ~title ~tags ~content in
62+ let note = Note.build ~tags ~content title in
63 Io.create
64 ~callback:(get cfg "on_modification")
65- ~content:(Note.to_string ~note) target_file
66+ ~content:(Note.to_string note) target_file
67 | None ->
68- let note = Note.build ~title ~tags ~content:"" in
69- let init_content = Note.to_string ~note in
70+ let note = Note.build ~tags ~content:"" title in
71+ let init_content = Note.to_string note in
72 Io.create_on_change
73 ~callback:(get cfg "on_modification")
74 ~editor:(get_exn cfg "editor") init_content target_file]
75 @@ -125,7 +125,7 @@ let list_notes =
76 Filename.concat (get_exn cfg "state_dir") (Slug.to_string s))
77 slugs
78 in
79- let notes = Note.filter (Note.read_notes ~paths) filters in
80+ let notes = Note.filter (Note.read_notes paths) filters in
81 List.iter ~f:(fun x -> print_endline (Note.get_title x)) notes]
82
83 let cat_note =
84 @@ -153,7 +153,7 @@ let cat_note =
85 Filename.concat (get_exn cfg "state_dir") (Slug.to_string s))
86 slugs
87 in
88- let notes = Note.filter (Note.read_notes ~paths) filters in
89+ let notes = Note.filter (Note.read_notes paths) filters in
90 List.iter
91 ~f:(fun note -> print_endline (encode_value (Note note) encoding))
92 notes]
93 @@ -186,7 +186,7 @@ let edit_note =
94 slugs
95 in
96 let notes =
97- Note.filter_with_paths (Note.read_notes_with_paths ~paths) filters
98+ Note.filter_with_paths (Note.read_notes_with_paths paths) filters
99 in
100 match List.length notes with
101 | 0 -> failwith "no note found"
102 @@ -222,7 +222,7 @@ let delete_note =
103 slugs
104 in
105 let notes =
106- Note.filter_with_paths (Note.read_notes_with_paths ~paths) filters
107+ Note.filter_with_paths (Note.read_notes_with_paths paths) filters
108 in
109 match List.length notes with
110 | 0 -> failwith "no note found"
111 diff --git a/lib/dune b/lib/dune
112index 59076cc..0c5fa95 100644
113--- a/lib/dune
114+++ b/lib/dune
115 @@ -1,5 +1,5 @@
116 (library
117 (name note_lib)
118- (preprocess (pps ppx_jane))
119- (libraries base core ezjsonm jsonpath stdio yaml)
120- )
121+ (preprocess
122+ (pps ppx_jane))
123+ (libraries base core ezjsonm omd stdio yaml))
124 diff --git a/lib/note.ml b/lib/note.ml
125index 287957d..59cd8bd 100644
126--- a/lib/note.ml
127+++ b/lib/note.ml
128 @@ -1,68 +1,73 @@
129 open Core
130 open Stdio
131
132- type t = {
133- title : string;
134- tags : string list;
135- content : string;
136- }
137+ type t = Ezjsonm.t * Omd.t
138
139- let build ~title ~tags ~content =
140- { title; tags; content}
141+ let build ?(tags = []) ?(content = "") title =
142+ let frontmatter =
143+ Ezjsonm.dict
144+ [ ("title", Ezjsonm.string title); ("tags", Ezjsonm.strings tags) ]
145+ in
146+ (frontmatter, Omd.of_string content)
147
148- let get_title t = t.title
149+ let get_title t =
150+ match Ezjsonm.find_opt (Ezjsonm.value (fst t)) [ "title" ] with
151+ | Some v -> Ezjsonm.get_string v
152+ | None -> ""
153
154- let to_json ~note =
155+ let get_tags t =
156+ match Ezjsonm.find_opt (Ezjsonm.value (fst t)) [ "tags" ] with
157+ | Some v -> Ezjsonm.get_strings v
158+ | None -> []
159+
160+ let to_json t =
161 Ezjsonm.dict
162 [
163- ("title", Ezjsonm.string note.title);
164- ("tags", Ezjsonm.strings note.tags);
165- ("content", Ezjsonm.string note.content);
166+ ("frontmatter", Ezjsonm.value (fst t));
167+ ("content", Ezjsonm.string (Omd.to_text (snd t)));
168 ]
169
170- let to_string ~note =
171- let dict =
172- Ezjsonm.dict
173- [
174- ("title", Ezjsonm.string note.title); ("tags", Ezjsonm.strings note.tags);
175- ]
176- in
177- let front_matter = Yaml.to_string_exn dict in
178- String.concat ~sep:"\n" [ "---"; front_matter; "---"; note.content ]
179+ let to_string t =
180+ let front_matter = Yaml.to_string_exn (Ezjsonm.value (fst t)) in
181+ String.concat ~sep:"\n" [ "---"; front_matter; "---"; Omd.to_text (snd t) ]
182
183- let of_string ~data =
184+ (*TODO: Change to Option*)
185+ let of_string data =
186 let indexes = String.substr_index_all ~may_overlap:true ~pattern:"---" data in
187 if List.length indexes >= 2 then
188 let meta_str =
189 String.slice data (List.nth_exn indexes 0 + 3) (List.nth_exn indexes 1)
190 in
191- let content =
192- String.slice data (List.nth_exn indexes 1 + 3) (String.length data)
193+ let frontmatter : Ezjsonm.t = match (Yaml.of_string_exn meta_str) with
194+ | `O v -> `O v
195+ | `A v -> `A v
196+ | _ -> failwith "frontmatter is a partial fragment, should be either a dictionary or list"
197+ in
198+ let markdown : Omd.t =
199+ Omd.of_string
200+ (String.slice data (List.nth_exn indexes 1 + 3) (String.length data))
201 in
202- let value = Yaml.of_string_exn meta_str in
203- let title = Ezjsonm.get_string (Ezjsonm.find value [ "title" ]) in
204- let tags = Ezjsonm.get_strings (Ezjsonm.find value [ "tags" ]) in
205- Some { title; content; tags }
206+ Some (frontmatter, markdown)
207 else None
208
209- let of_string_exn ~data =
210- let note = of_string ~data in
211+ let of_string_exn data =
212+ let note = of_string data in
213 match note with Some note -> note | None -> failwith "bad note content"
214
215- let read_note ~path =
216+ let read_note path =
217 let data = In_channel.read_all path in
218- of_string ~data
219+ of_string data
220
221- let read_note_exn ~path =
222- let note = read_note ~path in
223+ let read_note_exn path =
224+ let note = read_note path in
225 match note with Some note -> note | None -> failwith "failed to read note"
226
227- let read_notes ~paths = List.map ~f:(fun path -> read_note_exn ~path) paths
228+ let read_notes paths = List.map ~f:(fun path -> read_note_exn path) paths
229
230- let read_notes_with_paths ~paths =
231- List.map ~f:(fun path -> (read_note_exn ~path, path)) paths
232+ let read_notes_with_paths paths =
233+ List.map ~f:(fun path -> (read_note_exn path, path)) paths
234
235- let filter notes filters =
236+ let filter (notes : t list) filters =
237 if List.length filters = 0 then notes
238 (* return everything if there are no filters *)
239 else
240 @@ -70,14 +75,17 @@ let filter notes filters =
241 ~f:(fun accm note ->
242 (* first look by name *)
243 let matches =
244- List.count ~f:(fun filter -> String.equal note.title filter) filters
245+ List.count
246+ ~f:(fun filter -> String.equal (get_title note) filter)
247+ filters
248 in
249 if matches > 0 then note :: accm
250 else
251 (* then compare each tag with each filter *)
252 let matches =
253 List.count
254- ~f:(fun filter -> List.mem ~equal:String.equal note.tags filter)
255+ ~f:(fun filter ->
256+ List.mem ~equal:String.equal (get_tags note) filter)
257 filters
258 in
259 if matches > 0 then note :: accm else accm)
260 @@ -87,19 +95,21 @@ let filter_with_paths notes filters =
261 if List.length filters = 0 then notes
262 (* return everything if there are no filters *)
263 else
264- List.fold
265- ~init:([] : (t * string) list)
266+ List.fold ~init:[]
267 ~f:(fun accm (note, path) ->
268 (* first look by name *)
269 let matches =
270- List.count ~f:(fun filter -> String.equal note.title filter) filters
271+ List.count
272+ ~f:(fun filter -> String.equal (get_title note) filter)
273+ filters
274 in
275 if matches > 0 then (note, path) :: accm
276 else
277 (* then compare each tag with each filter *)
278 let matches =
279 List.count
280- ~f:(fun filter -> List.mem ~equal:String.equal note.tags filter)
281+ ~f:(fun filter ->
282+ List.mem ~equal:String.equal (get_tags note) filter)
283 filters
284 in
285 if matches > 0 then (note, path) :: accm else accm)
286 diff --git a/lib/note.mli b/lib/note.mli
287index 2bac40b..573cdfb 100644
288--- a/lib/note.mli
289+++ b/lib/note.mli
290 @@ -1,31 +1,31 @@
291 type t
292
293- val build : title:string -> tags:string list -> content:string -> t
294+ val build : ?tags:string list -> ?content:string -> string -> t
295 (** build a new note *)
296
297 val get_title : t -> string
298 (** access the title of a note *)
299
300- val to_string : note:t -> string
301+ val to_string : t -> string
302 (** convert a note into a string *)
303
304- val of_string : data:string -> t option
305+ val of_string : string -> t option
306 (** decode a note from a string *)
307
308- val to_json : note:t -> [>Ezjsonm.t]
309+ val to_json : t -> [>Ezjsonm.t]
310
311- val of_string_exn : data:string -> t
312+ val of_string_exn : string -> t
313
314- val read_note : path:string -> t option
315+ val read_note : string -> t option
316 (** read a note from the path *)
317
318- val read_note_exn : path:string -> t
319+ val read_note_exn : string -> t
320 (** read a note from the path raising an exception on failure *)
321
322- val read_notes : paths:string list -> t list
323+ val read_notes : string list -> t list
324 (** read all of the note paths raising an exception of any failure *)
325
326- val read_notes_with_paths : paths:string list -> (t * string) list
327+ val read_notes_with_paths : string list -> (t * string) list
328 (** read all of the note paths returning a tuple of note and it's associated path rasiing an exception on any failure *)
329
330 val filter : t list -> string list -> t list
331 diff --git a/note.opam b/note.opam
332index 3f4fbb4..9cfd4db 100644
333--- a/note.opam
334+++ b/note.opam
335 @@ -13,6 +13,7 @@ depends: [
336 "core" {>= "v0.14.0"}
337 "dune" {>= "2.7" & >= "2.7"}
338 "ezjsonm" {>= "1.2.0"}
339+ "jsonpath" {>= "0.0.1"}
340 "stdio" {>= "v0.14.0"}
341 "yaml" {>= "2.1.0"}
342 "odoc" {with-doc}