-
Notifications
You must be signed in to change notification settings - Fork 0
/
daze.py
235 lines (198 loc) · 7.87 KB
/
daze.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import click
import calendar
from datetime import date, timedelta
import subprocess
import sys
import re
import dazeutils as d
cal = calendar.Calendar()
@click.group()
@click.option('--log',
type=click.Path(exists=True),
help="Select a log. Default is the one specified in $DAZE/settings.json.")
@click.pass_context
def cli(ctx, log):
ctx.obj = dict()
ctx.obj['log'] = log
ctx.obj['daze'] = d.fileToDaze(log)
pass
@cli.command()
@click.option('--month', '-m',
type=click.INT,
help="Show summary for a specific month (in the current or specified year).")
@click.option('--year', '-y',
type=click.INT,
help="Show the summary for a specific year.")
@click.pass_context
def summary(ctx, month, year):
"""Show a summary of all logged days that includes days in each location,
as well as if any days are missing."""
daze = ctx.obj['daze']
if not year:
year = date.today().year # defaults to this year
if month:
first = date(year, month, 1)
last = max([day for day in cal.itermonthdates(year, month) if day.month == month])
s = daze.summarize(firstdate=first, lastdate=last)
else:
s = daze.summarize()
# summarize values: placeDict, number of days, first date, last date
for (p, v) in s[0].items():
click.echo("%s: %d" % (p, v))
missing_days = ((s[3] - s[2]) - timedelta(days=s[1]-1)).days
click.echo("\nBetween %s and %s:" % (s[2].isoformat(), s[3].isoformat()))
click.secho("%d total dates" % s[1], bg='green', nl=(missing_days == 0))
if missing_days > 0:
click.secho("with %d missing days." % missing_days, bg='red')
@cli.command()
@click.argument('place', required=False)
@click.argument('strdate', required=False)
@click.pass_context
def add(ctx, place, strdate):
"""Add (or overwrite) an entry to the log.
Enter the place followed by the date as YYYY-MM-DD."""
daze = ctx.obj['daze']
if place is None:
place = getPlaceFromDialog()
if strdate is None:
strdate = date.today().isoformat()
else:
# Check whether the arguments are maybe switched
if re.match(r"[A-z]+", strdate):
print("Arguments may have been inverted. Assuming {} is the date.".format(place), file=sys.stderr)
place, strdate = strdate, place
if re.match(r"\d{2}-\d{2}", strdate):
strdate = str(date.today().year) + "-" + strdate
print(strdate)
print("\n\n")
daze.add(strdate, place)
d.dazeToFile(daze, ctx.obj['log'])
@cli.command()
@click.option('--cron',
help="""If cron is on, there is no output but the exit value
is non-zero if today has not been logged.""")
@click.pass_context
def checkToday(ctx, cron):
"""Check whether today has been logged. Returns true/false."""
daze = ctx.obj['daze']
if cron is not None:
if date.today() in daze.dateDict.keys():
sys.exit(1)
else:
sys.exit(0)
click.echo(date.today() in daze.dateDict.keys())
return date.today() in daze.dateDict.keys()
# Poor man's implementation of an alias
def display_calendar(daze, month, year):
"""Display a calendar of all logged dates."""
log = daze.dateDict
if not year:
year = date.today().year # defaults to this year
if month:
first = date(year, month, 1)
last = max([day for day in cal.itermonthdates(year, month) if day.month == month])
s, ndates, firstdate, lastdate = daze.summarize(firstdate=first, lastdate=last)
else:
s, ndates, firstdate, lastdate = daze.summarize()
places = sorted(s, key=s.get, reverse=True)
colors = ['green', 'magenta', 'white', 'cyan', 'blue', 'red', 'yellow']
months = calendar.month_name[1:]
dates = [firstdate + timedelta(days=i) for i in range((lastdate - firstdate).days + 1)]
matches = {p: c for (p, c) in zip(places, colors)}
for (p, c) in matches.items():
click.secho(" %s " % p, bg=c, fg='black', bold=True)
for _date in dates:
if _date.day == 1 or _date == firstdate:
click.echo('')
click.echo("\n" + months[_date.month - 1])
if (_date.isoweekday() != 7):
click.echo(" " * 3 * _date.isoweekday(), nl=False)
if _date in log:
p = log[_date]
click.secho("%s" % str(_date.day).rjust(3),
fg='black',
bg=matches[p],
nl=(_date.isoweekday() == 6))
else:
click.secho("%s" % str(_date.day).rjust(3),
fg='black', nl=(_date.isoweekday() == 6))
click.echo('\n\n\n')
def display_calendar_redo(daze, year, month):
""" Display a calendar of all logged dates.
If year is specified, display only months of that year.
If month is specified display only that month of current (or specified) year.
"""
log = daze.dateDict
# Set first and last dates
if year is None:
year = date.today().year
if month is None:
first = date(year, 1, 1)
if year == date.today().year:
last = date.today()
else:
last = date(year, 12, 31)
else:
first = date(year, month, 1)
last = date(2016, month, calendar.monthrange(2016, month)[1])
# Get summarized data
s, ndates, firstdate, lastdate = daze.summarize()
places = sorted(s, key=s.get, reverse=True)
colors = ['green', 'magenta', 'white', 'cyan', 'blue', 'red', 'yellow']
# alias cal to calendar
@cli.command('cal')
@click.option('--month', '-m',
type=click.INT,
help="Show calendar for a specific month (in the current or specified year).")
@click.option('--year', '-y',
type=click.INT,
help="Show calendar for a specific year.")
@click.pass_context
def cal_cmd(ctx, month, year):
display_calendar(ctx.obj['daze'], month, year)
@cli.command('calendar')
@click.option('--month', '-m',
type=click.INT,
help="Show calendar for a specific month (in the current or specified year).")
@click.option('--year', '-y',
type=click.INT,
help="Show calendar for a specific year.")
@click.pass_context
def calendar_cmd(ctx, month, year):
display_calendar(ctx.obj['daze'], month, year)
@cli.command()
@click.argument('strdate', required=True)
@click.pass_context
def remove(ctx, strdate):
ctx.obj['daze'].remove(strdate)
d.dazeToFile(ctx.obj['daze'], ctx.obj['log'])
@cli.command()
@click.pass_context
def setup(ctx):
click.echo("Not yet implemented.")
@cli.command()
@click.pass_context
def backup(ctx):
click.echo("Not yet implemented.")
def getPlaceFromDialog():
workOrNot = '''
tell app "System Events" to display dialog "Working today?" with title "Daze" buttons {"Yes", "No"} default button "Yes" giving up after 15
'''
workingWhere = '''
tell app "System Events" to display dialog "Where?" with title "Daze" buttons {"Guilford", "New York", "Other"} default answer "" default button "Other"
'''
notWorkingWhy = '''
tell app "System Events" to display dialog "Why not?" with title "Daze" buttons {"Weekend", "Holiday", "Other"} default answer "" default button "Weekend"
'''
def dialogResponseToDict(rawResponse):
clipped = str(rawResponse)[2:-3]
split = [c.strip().split(':') for c in clipped.split(',')]
return {c[0]:c[1] for c in split}
answer_workOrNot = dialogResponseToDict(subprocess.check_output(['osascript', '-e', workOrNot]))
if answer_workOrNot["button returned"] == "Yes":
subanswer = dialogResponseToDict(subprocess.check_output(['osascript', '-e', workingWhere]))
else:
subanswer = dialogResponseToDict(subprocess.check_output(['osascript', '-e', notWorkingWhy]))
if subanswer['text returned'] == "":
return subanswer['button returned'].lower()
return subanswer['text returned'].lower()