list: Improve output.
[todo.git] / todo_list.ml
1 (* Implement 'list' subcommand. *)
2
3 open CalendarLib
4
5 open Todo_types
6 open Todo_utils
7 open Todo_tag_utils
8
9 open Printf
10
11 let print_task dbh taskid ?rhbz ?deadline ?estimate description =
12   let cols = ref 0 in
13   printf "  •";
14   cols := !cols + 3;
15
16   (match deadline with
17    | None -> ()
18    | Some deadline ->
19       let deadline =
20         if Time.equal (Time.midnight ()) (Calendar.to_time deadline) then
21           Printer.Calendar.sprint "%F" deadline
22         else
23           Printer.Calendar.to_string deadline in
24       let deadline = " " ^ deadline in
25       printf "%s" deadline;
26       cols := !cols + String.length deadline
27   );
28
29   (match estimate with
30    | None -> ()
31    | Some period ->
32       let estimate = " " ^ string_of_estimate period in
33       printf "%s" estimate;
34       cols := !cols + String.length estimate
35   );
36
37   (match rhbz with
38    | None -> ()
39    | Some rhbz ->
40       printf " https://bugzilla.redhat.com/%ld\n   " rhbz;
41       cols := 3
42   );
43
44   printf " %s" (string_of_task_desc description);
45   cols := !cols + String.length description + 1;
46
47   let taskid_len = String.length (sprintf "#%ld" taskid) in
48   if !cols + taskid_len >= 78 then (
49     printf "\n   ";
50     cols := 3
51   );
52   printf " %s" (string_of_taskid taskid);
53   cols := !cols + taskid_len + 1;
54
55   let rows = PGSQL(dbh) "select tags.name, tags.colour
56                            from tags_tasks, tags
57                           where tags_tasks.taskid = $taskid
58                             and tags_tasks.tagid = tags.id
59                        order by tags.name" in
60   List.iter (
61     fun (name, colour) ->
62       let len = String.length name + 2 in
63       if !cols + len >= 78 then (
64         printf "\n   ";
65         cols := 3
66       );
67       printf " %s" (string_of_tag name colour);
68       cols := !cols + len + 1;
69   ) rows;
70   printf "\n"
71
72 let cmd_list dbh anon_params list_retired list_all =
73   if anon_params <> [] then
74     error "extra parameters to 'list' subcommand";
75
76   let show_unretired, show_retired =
77     match list_retired, list_all with
78     | _, true -> true, true
79     | false, false -> true, false
80     | true, false -> false, true in
81
82   if show_unretired then (
83     let rows = PGSQL(dbh) "select imminent.taskid, tasks.rhbz, tasks.description
84                              from imminent, tasks
85                             where imminent.taskid = tasks.id
86                          order by tasks.description" in
87     if rows <> [] then heading "Today";
88     List.iter (
89       fun (id, rhbz, desc) ->
90         print_task dbh id ?rhbz desc
91     ) rows;
92
93     let rows = PGSQL(dbh) "select todo.taskid, todo.deadline, todo.estimate,
94                                   tasks.rhbz, tasks.description
95                              from todo, tasks
96                             where todo.taskid = tasks.id
97                          order by todo.deadline, tasks.description" in
98     if rows <> [] then heading "To-do list";
99     List.iter (
100       fun (id, deadline, estimate, rhbz, desc) ->
101         print_task dbh id ?rhbz ~deadline ?estimate desc
102     ) rows;
103
104     let rows = PGSQL(dbh) "
105          select tasks.id, tasks.rhbz, tasks.description
106           from tasks
107          where not exists (select 1 from imminent where taskid = tasks.id)
108            and not exists (select 1 from todo where taskid = tasks.id)
109            and not exists (select 1 from ideas where taskid = tasks.id)
110            and not exists (select 1 from retired where taskid = tasks.id)
111       order by tasks.description" in
112     if rows <> [] then heading "Unsorted (use 'todo move' to move these)";
113     List.iter (
114       fun (id, rhbz, desc) ->
115         print_task dbh id ?rhbz desc
116     ) rows;
117
118     let rows = PGSQL(dbh) "select ideas.taskid, tasks.rhbz, tasks.description
119                              from ideas, tasks
120                             where ideas.taskid = tasks.id
121                          order by tasks.description" in
122     if rows <> [] then heading "Ideas";
123     List.iter (
124       fun (id, rhbz, desc) ->
125         print_task dbh id ?rhbz desc
126     ) rows
127   ); (* unretired *)
128
129   if show_retired then (
130     let rows = PGSQL(dbh) "select retired.taskid, tasks.rhbz, tasks.description
131                              from retired, tasks
132                             where retired.taskid = tasks.id
133                          order by tasks.description" in
134     if rows <> [] then heading "Retired";
135     List.iter (
136       fun (id, rhbz, desc) ->
137         print_task dbh id ?rhbz desc
138     ) rows
139   )