1 (* Parse the command line. *)
11 todo -- A simple to-do list
13 todo [--global-options] [subcommand] [--subcommand-options]
16 todo list [--all] [--retired]
18 todo today \"description\" [tag[,tag...]]
19 - Add a simple task for today, with an optional list of tags
20 todo idea \"description\" [tag[,tag...]]
21 - Add an long-term idea
22 todo [todo|task] deadline [--estimate nr_days] \"description\" [tag[,tag...]]
23 - Add a to-do task with a deadline and optional time estimate
24 todo retire ID [ID ...]
25 - Retire one or more tasks using the task #ID
26 todo move ID [today | [todo|task] deadline | ideas | retired | unsorted]
27 - Move a task to another list
28 todo tag ID tag [--del tag]
29 - Add or remove tags from a task
31 - List all tags and their usage
32 todo tag-add tag colour
33 - Create a new tag, with a colour
35 - Delete a tag (must be unused)
36 todo tag-colour tag colour
37 - Change the colour of a tag
39 Tag colours may be: black blue green cyan red purple yellow
42 todo today \"Eat breakfast\" personal,food
43 todo task 2019-31-12 \"Prepare for next decade\"
44 todo idea \"Write a to-do manager\" work
49 (* Parse the command line. *)
50 let parse_command_line () =
51 let print_version_and_exit () =
52 printf "%s %s\n" Todo_config.package_name Todo_config.package_version;
56 let list_all = ref false in
57 let list_retired = ref false in
58 let tag_del = ref [] in
59 let add_tag_del tag = tag_del := tag :: !tag_del in
60 let todo_estimate = ref None in
61 let set_todo_estimate days =
62 todo_estimate := Some (Calendar.Period.day days)
65 (* Per-subcommand specs. *)
71 "--all", Arg.Set list_all, " List all tasks including retired";
72 "--retired", Arg.Set list_retired, " List only retired tasks";
82 "--del", Arg.String add_tag_del, "tag Remove tag";
83 "--delete", Arg.String add_tag_del, "tag Remove tag";
84 "--remove", Arg.String add_tag_del, "tag Remove tag";
85 "--rm", Arg.String add_tag_del, "tag Remove tag";
104 "--estimate", Arg.Int set_todo_estimate, "days Estimated time taken";
107 (* This parses the global parameters before the subcommand. *)
110 "--version", Arg.Unit print_version_and_exit, " Display version and exit";
112 let spec = ref global_spec in
113 let subcommand = ref None in
114 let anon_params = ref [] in
116 if !subcommand = None then (
117 (* It's the subcommand, so switch the spec. *)
119 try subcommand_of_string s
120 with Invalid_argument _ ->
121 raise (Arg.Bad "unknown subcommand") in
122 subcommand := Some sc;
124 | Idea -> spec := idea_spec
125 | List -> spec := list_spec
126 | Move -> spec := move_spec
127 | Retire -> spec := retire_spec
128 | Tag -> spec := tag_spec
129 | Tag_add -> spec := tag_add_spec
130 | Tag_colour -> spec := tag_colour_spec
131 | Tag_del -> spec := tag_del_spec
132 | Tag_list -> spec := tag_list_spec
133 | Today -> spec := today_spec
134 | Todo -> spec := todo_spec
137 (* We've seen the subcommand already, just add it to anon_params. *)
138 anon_params := s :: !anon_params
140 Arg.parse_dynamic spec anon usage;
142 (* Return the parsed command line. *)
144 match !subcommand with
145 | None -> error "no subcommand given"
147 let anon_params = List.rev !anon_params in
149 let list_retired = !list_retired in
150 let list_all = !list_all in
151 let tag_del = List.rev !tag_del in
152 let todo_estimate = !todo_estimate in
154 subcommand, anon_params, list_retired, list_all, tag_del, todo_estimate