Commit
+74 -85 +/-3 browse
1 | diff --git a/completion/note.bash b/completion/note.bash |
2 | index 6dd1cf4..5b96695 100644 |
3 | --- a/completion/note.bash |
4 | +++ b/completion/note.bash |
5 | @@ -1,11 +1,12 @@ |
6 | - # TODO: Core.Command completion is terrible |
7 | - function _jsautocom_742571 { |
8 | + function _note_complete { |
9 | export COMP_CWORD |
10 | COMP_WORDS[0]=note |
11 | if type readarray > /dev/null |
12 | then readarray -t COMPREPLY < <("${COMP_WORDS[@]}") |
13 | else IFS=" |
14 | " read -d "" -A COMPREPLY < <("${COMP_WORDS[@]}") |
15 | + echo $COMP_CWORD $COMP_WORDS |
16 | fi |
17 | } |
18 | - complete -F _jsautocom_742571 note |
19 | + |
20 | + complete -F _note_complete note |
21 | diff --git a/lib/cmd.ml b/lib/cmd.ml |
22 | index abc4439..6893d5c 100644 |
23 | --- a/lib/cmd.ml |
24 | +++ b/lib/cmd.ml |
25 | @@ -8,6 +8,22 @@ let init_config path = |
26 | Config.initialize config_path config; |
27 | config |
28 | |
29 | + let get_slugs = |
30 | + let open Config in |
31 | + let cfg = init_config None in |
32 | + let slugs = Slug.load (get_exn cfg "state_dir") in |
33 | + List.map |
34 | + ~f:(fun s -> Filename.concat (get_exn cfg "state_dir") (Slug.to_string s)) |
35 | + slugs |
36 | + |
37 | + let get_notes_with_paths = |
38 | + List.map |
39 | + ~f:(fun path -> (Note.of_string (In_channel.read_all path), path)) |
40 | + get_slugs |
41 | + |
42 | + let get_notes = |
43 | + List.map ~f:(fun path -> Note.of_string (In_channel.read_all path)) get_slugs |
44 | + |
45 | type encoding = Json | Yaml | Text |
46 | |
47 | let encoding_argument = |
48 | @@ -18,6 +34,19 @@ let encoding_argument = |
49 | | "Text" | "text" | "TEXT" -> Text |
50 | | _ -> failwith "unsupported encoding type") |
51 | |
52 | + let filter_arg = |
53 | + Command.Arg_type.create |
54 | + ~complete:(fun _ ~part -> |
55 | + let notes = get_notes in |
56 | + List.filter_map |
57 | + ~f:(fun note -> |
58 | + let title = Note.get_title note in |
59 | + if String.equal part "" then Some title |
60 | + else if String.is_substring ~substring:part title then Some title |
61 | + else None) |
62 | + notes) |
63 | + (fun filter -> filter) |
64 | + |
65 | type value = Config of Config.t | Note of Note.t |
66 | |
67 | let encode_value value = function |
68 | @@ -55,33 +84,20 @@ note cat fuubar |
69 | note cat -encoding json |
70 | |}) |
71 | [%map_open |
72 | - let filter_args = anon (sequence ("filters" %: string)) |
73 | + let filter_args = anon (sequence ("filter" %: filter_arg)) |
74 | and fulltext = |
75 | - flag "fulltext" (no_arg) ~doc:"perform a fulltext search instead of just key comparison" |
76 | + flag "fulltext" no_arg |
77 | + ~doc:"perform a fulltext search instead of just key comparison" |
78 | and encoding = |
79 | flag "encoding" |
80 | (optional_with_default Text encoding_argument) |
81 | ~doc:"format [Text | Json | Yaml] (default: Text)" |
82 | in |
83 | fun () -> |
84 | - let open Config in |
85 | - let cfg = init_config None in |
86 | - let slugs = Slug.load (get_exn cfg "state_dir") in |
87 | - let paths = |
88 | - List.map |
89 | - ~f:(fun s -> |
90 | - Filename.concat (get_exn cfg "state_dir") (Slug.to_string s)) |
91 | - slugs |
92 | - in |
93 | let open Note.Filter in |
94 | let filter_kind = if fulltext then Some Fulltext else None in |
95 | let notes = |
96 | - find_many |
97 | - ?strategy:filter_kind |
98 | - ~args: filter_args |
99 | - (List.map |
100 | - ~f:(fun path -> Note.of_string (In_channel.read_all path)) |
101 | - paths) |
102 | + find_many ?strategy:filter_kind ~args:filter_args get_notes |
103 | in |
104 | List.iter |
105 | ~f:(fun note -> print_endline (encode_value (Note note) encoding)) |
106 | @@ -178,31 +194,21 @@ Examples |
107 | note delete fuubar |
108 | |}) |
109 | [%map_open |
110 | - let filter_args = anon (sequence ("filter" %: string)) |
111 | + let filter_args = anon (sequence ("filter" %: filter_arg)) |
112 | and fulltext = |
113 | - flag "fulltext" (no_arg) ~doc:"perform a fulltext search instead of just key comparison" |
114 | + flag "fulltext" no_arg |
115 | + ~doc:"perform a fulltext search instead of just key comparison" |
116 | in |
117 | fun () -> |
118 | let open Config in |
119 | let cfg = init_config None in |
120 | - let slugs = Slug.load (get_exn cfg "state_dir") in |
121 | - let paths = |
122 | - List.map |
123 | - ~f:(fun s -> |
124 | - Filename.concat (get_exn cfg "state_dir") (Slug.to_string s)) |
125 | - slugs |
126 | - in |
127 | let open Note.Filter in |
128 | let filter_kind = if fulltext then Some Fulltext else None in |
129 | let note = |
130 | - Note.Filter.find_one_with_paths |
131 | - ?strategy: filter_kind |
132 | - ~args: filter_args |
133 | - (List.map |
134 | - ~f:(fun path -> |
135 | - (Note.of_string (In_channel.read_all path), path)) |
136 | - paths) |
137 | + Note.Filter.find_one_with_paths ?strategy:filter_kind |
138 | + ~args:filter_args get_notes_with_paths |
139 | in |
140 | + |
141 | match note with |
142 | | Some (note, path) -> |
143 | Io.delete |
144 | @@ -223,30 +229,19 @@ Examples |
145 | note edit fuubar |
146 | |}) |
147 | [%map_open |
148 | - let filter_args = anon (sequence ("filter" %: string)) |
149 | + let filter_args = anon (sequence ("filter" %: filter_arg)) |
150 | and fulltext = |
151 | - flag "fulltext" (no_arg) ~doc:"perform a fulltext search instead of just key comparison" |
152 | + flag "fulltext" no_arg |
153 | + ~doc:"perform a fulltext search instead of just key comparison" |
154 | in |
155 | fun () -> |
156 | let open Config in |
157 | let cfg = init_config None in |
158 | - let slugs = Slug.load (get_exn cfg "state_dir") in |
159 | - let paths = |
160 | - List.map |
161 | - ~f:(fun s -> |
162 | - Filename.concat (get_exn cfg "state_dir") (Slug.to_string s)) |
163 | - slugs |
164 | - in |
165 | let open Note.Filter in |
166 | let filter_kind = if fulltext then Some Fulltext else None in |
167 | let note = |
168 | - Note.Filter.find_one_with_paths |
169 | - ?strategy: filter_kind |
170 | - ~args: filter_args |
171 | - (List.map |
172 | - ~f:(fun path -> |
173 | - (Note.of_string (In_channel.read_all path), path)) |
174 | - paths) |
175 | + Note.Filter.find_one_with_paths ?strategy:filter_kind |
176 | + ~args:filter_args get_notes_with_paths |
177 | in |
178 | match note with |
179 | | Some (_, path) -> |
180 | @@ -270,35 +265,25 @@ note ls |
181 | ``` |
182 | |}) |
183 | [%map_open |
184 | - let filter_args = anon (sequence ("args" %: string)) |
185 | + let filter_args = anon (sequence ("filter" %: filter_arg)) |
186 | and fulltext = |
187 | - flag "fulltext" (no_arg) ~doc:"perform a fulltext search instead of just key comparison" |
188 | + flag "fulltext" no_arg |
189 | + ~doc:"perform a fulltext search instead of just key comparison" |
190 | + and simple = |
191 | + flag "simple" no_arg ~doc:"simple program output (machine readable)" |
192 | in |
193 | fun () -> |
194 | - let open Config in |
195 | - let cfg = init_config None in |
196 | - let slugs = Slug.load (get_exn cfg "state_dir") in |
197 | - let paths = |
198 | - List.map |
199 | - ~f:(fun s -> |
200 | - Filename.concat (get_exn cfg "state_dir") (Slug.to_string s)) |
201 | - slugs |
202 | - in |
203 | let open Note.Filter in |
204 | + let style = if simple then Simple else Fancy in |
205 | let filter_kind = if fulltext then Some Fulltext else None in |
206 | let notes = |
207 | - Note.Filter.find_many |
208 | - ?strategy: filter_kind |
209 | - ~args: filter_args |
210 | - (List.map |
211 | - ~f:(fun path -> Note.of_string (In_channel.read_all path)) |
212 | - paths) |
213 | + Note.Filter.find_many ?strategy:filter_kind ~args:filter_args |
214 | + get_notes |
215 | in |
216 | - print_short ~style:Fancy notes] |
217 | + print_short ~style notes] |
218 | |
219 | let run = |
220 | - Command.run |
221 | - ~version: "%%VERSION%%" |
222 | + Command.run ~version:"%%VERSION%%" |
223 | (Command.group ~summary:"Note is a simple CLI based note taking application" |
224 | [ |
225 | ("cat", cat_note); |
226 | diff --git a/lib/note.ml b/lib/note.ml |
227 | index 66065cc..a1bc130 100644 |
228 | --- a/lib/note.ml |
229 | +++ b/lib/note.ml |
230 | @@ -177,7 +177,7 @@ module Filter = struct |
231 | args |
232 | | Fulltext -> failwith "not implemented" |
233 | |
234 | - let find_one ?(strategy=Keys) ~args notes = |
235 | + let find_one ?(strategy = Keys) ~args notes = |
236 | let filters = of_strings strategy args in |
237 | List.find |
238 | ~f:(fun note -> |
239 | @@ -185,7 +185,7 @@ module Filter = struct |
240 | || List.length filters = 0) |
241 | notes |
242 | |
243 | - let find_one_with_paths ?(strategy=Keys) ~args notes = |
244 | + let find_one_with_paths ?(strategy = Keys) ~args notes = |
245 | let filters = of_strings strategy args in |
246 | List.find |
247 | ~f:(fun (note, _) -> |
248 | @@ -193,7 +193,7 @@ module Filter = struct |
249 | || List.length filters = 0) |
250 | notes |
251 | |
252 | - let find_many ?(strategy=Keys) ~args notes = |
253 | + let find_many ?(strategy = Keys) ~args notes = |
254 | let filters = of_strings strategy args in |
255 | List.filter |
256 | ~f:(fun note -> |
257 | @@ -233,23 +233,26 @@ module Display = struct |
258 | |
259 | let print_short ~style notes = |
260 | let columns = |
261 | - [ (([ Bold ], "title"), ([ Bold ], "tags"), ([ Bold ], "words")) ] |
262 | - @ List.map |
263 | - ~f:(fun note -> |
264 | - let title = get_title note in |
265 | - let tags = String.concat ~sep:"|" (get_tags note) in |
266 | - let word_count = Core.sprintf "%d" (List.length (tokenize note)) in |
267 | - (([], title), ([], tags), ([], word_count))) |
268 | - notes |
269 | + List.map |
270 | + ~f:(fun note -> |
271 | + let title = get_title note in |
272 | + let tags = String.concat ~sep:"|" (get_tags note) in |
273 | + let word_count = Core.sprintf "%d" (List.length (tokenize note)) in |
274 | + (([], title), ([], tags), ([], word_count))) |
275 | + notes |
276 | in |
277 | match style with |
278 | | Simple -> |
279 | List.iter |
280 | ~f:(fun (col1, col2, col3) -> |
281 | - let (_, text1), (_, text2), (_, text3) = (col1, col2, col3) in |
282 | - print_endline (Core.sprintf "%s %s %s" text1 text2 text3)) |
283 | + let (_, text1), (_, _), (_, _) = (col1, col2, col3) in |
284 | + print_endline (Core.sprintf "%s" text1)) |
285 | columns |
286 | | Fancy -> |
287 | + let columns = |
288 | + [ (([ Bold ], "title"), ([ Bold ], "tags"), ([ Bold ], "words")) ] |
289 | + @ columns |
290 | + in |
291 | let max1, max2, max3 = |
292 | List.fold ~init:(0, 0, 0) |
293 | ~f:(fun accm pair -> |