@@ -26,6 +26,7 @@ class ThingsCLI: # pylint: disable=too-many-instance-attributes
2626
2727 print_json = False
2828 print_csv = False
29+ print_gantt = False
2930 print_opml = False
3031 # anonymize = False
3132 database = None
@@ -70,9 +71,64 @@ def print_tasks(self, tasks):
7071 print (self .opml_dumps (tasks ))
7172 elif self .print_csv :
7273 print (self .csv_dumps (tasks ))
74+ elif self .print_gantt :
75+ print ("gantt" )
76+ print (" dateFormat YYYY-MM-DD" )
77+ print (" title Things To-Dos" )
78+ print (" excludes weekends" )
79+ print (self .gantt_dumps (tasks ))
7380 else :
7481 print (self .txt_dumps (tasks ), end = "" )
7582
83+ def gantt_dumps (self , tasks , array = None ):
84+ """Convert tasks into mermaid-js GANTT."""
85+
86+ result = ""
87+
88+ if array is None :
89+ array = {}
90+
91+ for task in tasks :
92+ ThingsCLI .gantt_add_task (task , array )
93+ self .gantt_dumps (task .get ("items" , []), array )
94+
95+ for group in array :
96+ result += f" section { group } \n "
97+ for item in array [group ]:
98+ result += item
99+
100+ return result
101+
102+ @staticmethod
103+ def gantt_add_task (task , array ):
104+ """Add a task to a mermaid-js GANTT."""
105+
106+ context = (
107+ task .get ("project_title" , None )
108+ or task .get ("area_title" , None )
109+ or task .get ("heading_title" , None )
110+ or task .get ("start" , None )
111+ or ""
112+ )
113+
114+ title = task ["title" ].replace (":" , " " )
115+ start = task .get ("start_date" )
116+ deadline = task .get ("deadline" ) or "1h"
117+ if not start and deadline != "1h" :
118+ start = deadline
119+ if start == deadline :
120+ deadline = "1h"
121+ if deadline == "1h" :
122+ visual = ":milestone"
123+ else :
124+ visual = ":active"
125+ # noqa todo: if in the past: done
126+ if start and not task .get ("stop_date" ):
127+ if context not in array :
128+ array [context ] = []
129+ if not "" .join (s for s in array [context ] if title .lower () in s .lower ()):
130+ array [context ].append (f" { title } { visual } , { start } , { deadline } \n " )
131+
76132 def csv_dumps (self , tasks ):
77133 """Convert tasks into CSV."""
78134
@@ -296,6 +352,15 @@ def get_parser(cls):
296352 dest = "csv" ,
297353 )
298354
355+ parser .add_argument (
356+ "-g" ,
357+ "--gantt" ,
358+ action = "store_true" ,
359+ default = False ,
360+ help = "output as mermaid-js GANTT" ,
361+ dest = "gantt" ,
362+ )
363+
299364 parser .add_argument (
300365 "-r" ,
301366 "--recursive" ,
@@ -339,6 +404,7 @@ def main(self, args=None):
339404 command = args .command
340405 self .print_json = args .json
341406 self .print_csv = args .csv
407+ self .print_gantt = args .gantt
342408 self .print_opml = args .opml
343409 self .database = args .database or self .database
344410 self .filter_project = args .filter_project or None
0 commit comments