-
Notifications
You must be signed in to change notification settings - Fork 0
/
timer
executable file
·175 lines (162 loc) · 5.36 KB
/
timer
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
#!/usr/bin/env python
import argparse
from subprocess import call
import time
default_message = "Time's up. Time's up. Do the thing!"
canned_messages_obj = (
("Get the fuck off the computer", ('-f', '--fuck')),
("The bus is leaving soon, don't miss the bus", ('--bus',)),
("Eat breakfast", ('-b', '--breakfast')),
["Tea is done", ('--tea',)],
["Go to class", ('--class',)],
["Check laundry", ('--laundry',)],
["Check food", ('--food',)],
["Go to meeting", ('--meeting',)],
)
# first column is the actual message
canned_messages = tuple(zip(*canned_messages_obj))[0]
def format_time(nsecs):
template = "{:02.0f}:{:02.0f}:{:02.0f}"
# organize time as [hours, minutes, seconds] for display
nsecs_tot = nsecs
time_list = [0, 0, 0]
time_list[0] = int(nsecs / 3600)
nsecs = nsecs % 3600
time_list[1] = int(nsecs / 60)
nsecs = nsecs % 60
time_list[2] = nsecs
return template.format(*time_list)
# setup parser
helpmsg = "Sets a timer, with an optional custom or canned message"
parser = argparse.ArgumentParser(description=helpmsg)
parser.add_argument('-s', '--show-timer', action="store_true",
help="Whether to show the current time remaining")
parser.add_argument('-m', type=str, metavar="message",
help="custom message to print instead of default")
parser.add_argument('-r', '--repeat', action="store_true",
help="repeat message on a loop, until killed")
parser.add_argument('-t', action="store_true",
help="indicates 'time' is a clock time, not a duration")
parser.add_argument('time', type=str, nargs='?',
help="number of seconds for timer, or (if -t is used), " + \
"clock time when timer expires")
# canned message options
canned_message_help="Show a canned message. Use 0 to show all messages."
parser.add_argument('-c', type=int, metavar="canned_num",
help=canned_message_help)
canned_message_all="Canned messages:\n"
canned_attrs = []
for ind, message_tup in enumerate(canned_messages_obj):
message, opts = message_tup
help_str = f"canned message {ind+1}: '{message}'"
canned_message_all += "\t{}: {}\n".format(ind+1, message)
parser.add_argument(*opts, action="store_true", help=help_str)
longest_opt = ''
for opt in opts:
if len(opt) > len(longest_opt):
longest_opt = opt
canned_attrs.append((ind, longest_opt.strip('-')))
canned_message_all = canned_message_all[:-1]
# run parser
args = parser.parse_args()
message = default_message
# check canned message options
for ind, attr in canned_attrs:
if args.__getattribute__(attr):
message = canned_messages[ind]
if args.c != None:
if args.c == 0:
import sys
print(canned_message_all)
sys.exit(0)
else:
message = canned_messages[args.c-1]
# check for custom message
if args.m != None:
message = args.m
# unless user just wants a list of canned message opts, we need a time
if args.time == None:
parser.print_usage()
import sys
sys.exit(1)
# parse time option
nsecs = 0
if args.t:
times = args.time.split(":")
try:
times = list(map(int, times))
except ValueError as e:
print("Error:", args.time, "is not a valid time")
import sys
sys.exit(2)
now = time.localtime()
now_tup = list(now)
now_epoch = time.mktime(now)
# indices to struct_time that we want to modify
inds = [3, 4, 5][:len(times)]
for ind, value in zip(inds, times):
now_tup[ind] = value
now_tup = tuple(now_tup)
dest_epoch = time.mktime(now_tup)
nsecs = dest_epoch - now_epoch
if nsecs < 0:
nsecs += 3600 * 12
if nsecs < 0:
print("Warning: destination is a time tomorrow")
nsecs += 3600 * 12
else:
if ":" in args.time:
times = list(args.time.split(":"))
try:
times = list(map(int, times))
except ValueError as e:
print("Error:", args.time, "is not a valid time")
import sys
sys.exit(3)
# deal with place values in increasing order
times.reverse()
# place value multiplier
multipliers = [1, 60, 60] # s, m, h
# we only want as many muls as needed
multipliers = multipliers[:len(times)]
mul = 1
for this_mul, value in zip(multipliers, times):
mul *= this_mul
nsecs += mul * value
else:
try:
nsecs = int(args.time)
except ValueError as e:
print("Error:", args.time, "is not a valid time")
import sys
sys.exit(4)
try:
if args.show_timer:
from sys import stdout
now_time = time.time()
dst_time = now_time + nsecs
while True:
time_left = dst_time - time.time()
if time_left < 0:
break
print("Time left:", format_time(time_left), "(hh:mm:ss) ... \r", end='')
stdout.flush()
time.sleep(0.2)
print()
print(message)
else:
# run the actual timer
print("Sleeping for", format_time(nsecs), "(hh:mm:ss) ...")
time.sleep(nsecs)
# say the message using macOS's `say`
if args.repeat:
# spam message until we get killed
while True:
call(["say", message])
else:
# just say it once
call(["say", message])
except KeyboardInterrupt:
print()
import sys
sys.exit(1)