Author: Kevin Schoon [kevinschoon@gmail.com]
Hash: 15b1f2a3427079e078590212897682458dfb09d9
Timestamp: Tue, 22 Jun 2021 19:52:37 +0000 (3 years ago)

+88 -17 +/-2 browse
allow moving of manifest items
1diff --git a/lib/manifest.ml b/lib/manifest.ml
2index 284dd69..7fa4592 100644
3--- a/lib/manifest.ml
4+++ b/lib/manifest.ml
5 @@ -1,5 +1,13 @@
6 open Core
7
8+ module Util = struct
9+ let dirname path =
10+ (* nothing is relative, all things are absolute! *)
11+ match path |> Filename.is_relative with
12+ | true -> Filename.concat "/" (Filename.dirname path)
13+ | false -> path |> Filename.dirname
14+ end
15+
16 module Item = struct
17 type t = {
18 parent : string option;
19 @@ -117,11 +125,13 @@ let list ~path manifest =
20 manifest.items
21 |> List.filter ~f:(fun item ->
22 let item_path = item |> to_path ~manifest in
23- String.equal path (Filename.dirname item_path))
24+ Filename.equal path (Filename.dirname item_path))
25
26- let insert ~path ~slug ~title ~description ~tags manifest =
27- match path with
28- | "" | "/" ->
29+ let insert ~path ~slug ~description ~tags manifest =
30+ let title = path |> Filename.basename in
31+ let dirname = path |> Util.dirname in
32+ match dirname with
33+ | "/" ->
34 let item = Item.make ~parent:None ~slug ~title ~description ~tags in
35 if manifest |> exists ~path:(item |> to_path ~manifest) then
36 failwith "duplicate item"
37 @@ -160,6 +170,29 @@ let remove ~path manifest =
38 { items }
39 | None -> failwith "not found"
40
41+ let update ?(new_path = None) ~path ~description ~tags manifest =
42+ let result =
43+ manifest.items
44+ |> List.findi ~f:(fun _ item ->
45+ let file_path = item |> to_path ~manifest in
46+ Filename.equal file_path path)
47+ in
48+ match result with
49+ | Some (index, item) -> (
50+ match new_path with
51+ | Some new_path ->
52+ let manifest = manifest |> remove ~path in
53+ manifest |> insert ~path:new_path ~slug:item.slug ~description ~tags
54+ | None ->
55+ let item = { item with description; tags } in
56+ let items =
57+ manifest.items
58+ |> List.foldi ~init:[] ~f:(fun i accm other ->
59+ if Int.equal i index then item :: accm else other :: accm)
60+ in
61+ { items })
62+ | None -> failwith "not found"
63+
64 let slugs manifest = manifest.items |> List.map ~f:(fun item -> item.slug)
65
66 let tags manifest =
67 diff --git a/test/manifest_test.ml b/test/manifest_test.ml
68index 1c69b8a..d60d0ff 100644
69--- a/test/manifest_test.ml
70+++ b/test/manifest_test.ml
71 @@ -4,14 +4,14 @@ open Note_lib
72 let test_recurse () =
73 let manifest =
74 Manifest.empty
75- |> Manifest.insert ~path:"/" ~slug:"note-00000000-0" ~title:"a"
76- ~description:"" ~tags:[]
77- |> Manifest.insert ~path:"/a" ~slug:"note-00000000-1" ~title:"b"
78- ~description:"" ~tags:[]
79- |> Manifest.insert ~path:"/a/b" ~slug:"note-00000000-2" ~title:"c"
80- ~description:"" ~tags:[]
81- |> Manifest.insert ~path:"/a/b/c" ~slug:"note-00000000-3" ~title:"d"
82- ~description:"" ~tags:[]
83+ |> Manifest.insert ~path:"/a" ~slug:"note-00000000-0" ~description:""
84+ ~tags:[]
85+ |> Manifest.insert ~path:"/a/b" ~slug:"note-00000000-1" ~description:""
86+ ~tags:[]
87+ |> Manifest.insert ~path:"/a/b/c" ~slug:"note-00000000-2" ~description:""
88+ ~tags:[]
89+ |> Manifest.insert ~path:"/a/b/c/d" ~slug:"note-00000000-3" ~description:""
90+ ~tags:[]
91 in
92 Alcotest.(check int) "n_results" 4 (List.length manifest.items)
93
94 @@ -20,14 +20,14 @@ let test_manifest () =
95 Manifest.empty |> Manifest.save ~path:temp_db;
96 let manifest =
97 Manifest.load_or_init temp_db
98- |> Manifest.insert ~path:"/" ~slug:"note-00000000-0.md" ~title:"fuu"
99- ~description:"" ~tags:[]
100+ |> Manifest.insert ~path:"/fuu" ~slug:"note-00000000-0.md" ~description:""
101+ ~tags:[]
102 in
103 let result = manifest |> Manifest.find ~path:"/fuu" in
104 Alcotest.(check bool) "manifest loaded" (result |> Option.is_some) true;
105 let manifest =
106 manifest
107- |> Manifest.insert ~path:"/fuu" ~slug:"note-00000000-1.md" ~title:"bar"
108+ |> Manifest.insert ~path:"/fuu/bar" ~slug:"note-00000000-1.md"
109 ~description:"" ~tags:[]
110 in
111 let result = manifest |> Manifest.find ~path:"/fuu/bar" in
112 @@ -37,14 +37,14 @@ let test_manifest () =
113 Alcotest.(check string) "result path" "/fuu/bar" result_path;
114 let manifest =
115 manifest
116- |> Manifest.insert ~path:"/fuu" ~slug:"note-00000000-2.md" ~title:"baz"
117+ |> Manifest.insert ~path:"/fuu/baz" ~slug:"note-00000000-2.md"
118 ~description:"" ~tags:[]
119 in
120 let results = manifest |> Manifest.list ~path:"/fuu" in
121 Alcotest.(check int) "n_results" 2 (List.length results);
122 let manifest =
123 manifest
124- |> Manifest.insert ~path:"/fuu/bar" ~slug:"note-00000000-3.md" ~title:"qux"
125+ |> Manifest.insert ~path:"/fuu/bar/qux" ~slug:"note-00000000-3.md"
126 ~description:"" ~tags:[]
127 in
128 let results = manifest |> Manifest.list ~path:"/fuu/bar" in
129 @@ -55,9 +55,47 @@ let test_manifest () =
130 print_endline (Manifest.to_string manifest);
131 Alcotest.(check int) "remove" 3 (List.length manifest.items)
132
133+ let test_update () =
134+ let manifest =
135+ Manifest.empty
136+ |> Manifest.insert ~path:"/a" ~slug:"note-00000000-0" ~description:""
137+ ~tags:[]
138+ |> Manifest.insert ~path:"/a/b" ~slug:"note-00000000-1" ~description:""
139+ ~tags:[]
140+ in
141+ Alcotest.(check int) "two entries" 2 (List.length manifest.items);
142+ let manifest =
143+ manifest |> Manifest.update ~path:"/a/b" ~description:"" ~tags:[ "a"; "b" ]
144+ in
145+ let result = Option.value_exn (manifest |> Manifest.find ~path:"/a/b") in
146+ Alcotest.(check string) "updated" "a" (List.nth_exn result.tags 0);
147+ Alcotest.(check string) "updated" "b" (List.nth_exn result.tags 1);
148+
149+ Alcotest.(check int) "two entries" 2 (List.length manifest.items)
150+
151+ let test_move () =
152+ let manifest =
153+ Manifest.empty
154+ |> Manifest.insert ~path:"/a" ~slug:"note-00000000-0" ~description:""
155+ ~tags:[]
156+ |> Manifest.insert ~path:"/a/b" ~slug:"note-00000000-1" ~description:""
157+ ~tags:[]
158+ in
159+ let manifest =
160+ manifest
161+ |> Manifest.update ~new_path:(Some "/b") ~path:"/a/b" ~description:""
162+ ~tags:[]
163+ in
164+ Alcotest.(check bool)
165+ "moved" true
166+ (manifest |> Manifest.find ~path:"/b" |> Option.is_some) ;
167+ Alcotest.(check int) "two entries" 2 (List.length manifest.items)
168+
169 let () =
170 Alcotest.run "Config"
171 [
172 ("recurse", [ Alcotest.test_case "test recurse" `Quick test_recurse ]);
173 ("load", [ Alcotest.test_case "test manifest" `Quick test_manifest ]);
174+ ("update", [ Alcotest.test_case "test update" `Quick test_update ]);
175+ ("move", [ Alcotest.test_case "test move" `Quick test_move ]);
176 ]