-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflipflop.py
executable file
·142 lines (113 loc) · 3.76 KB
/
flipflop.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
#!/usr/bin/env python3
"""
toggeable todos with the ability to flip back/forth easily
$ flipflop.py status
What | On
-----------------+-------
refill_lotion | False
refill_vitamins | False
$ flipflop.py flip
'what' (str) > refill_vitamins
$ flipflop.py status
What | On
-----------------+-------
refill_lotion | False
refill_vitamins | True
"""
import os
import json
from typing import NamedTuple, Dict
from enum import Enum
from datetime import datetime
import click
# disable default ttally config loading when ttally.__init__ is imported
os.environ["TTALLY_SKIP_DEFAULT_IMPORT"] = "1"
from ttally.core import Extension
with open(os.path.join(os.environ["HPIDATA"], ".flipflop.txt")) as f:
flipflop_choices = f.read().strip().splitlines()
# create enum from environment variable
FlipT = Enum("FlipT", flipflop_choices)
class Flip(NamedTuple):
when: datetime
what: FlipT # type: ignore
on: bool
def extension() -> Extension:
return Extension(
name="flipflop",
config_module_name="flipflop.config",
# use this file as the config file - the Flip namedtuple
config_file=__file__,
cache_dir=os.path.expanduser("~/.cache/flipflop"),
data_dir=os.path.join(os.environ["HPIDATA"], "flipflop"),
)
def main() -> None:
ext = extension()
def compute_current_statuses() -> Dict[str, bool]:
ext.cache_sorted_exports()
return {f["what"]: f["on"] for f in ext.read_cache_json(model="flip")}
# create CLI group so we can add additional commands
cli_group = ext.wrap_cli(call=False)
@cli_group.command(short_help="print current status")
@click.option(
"-f",
"--filter-on",
is_flag=True,
default=False,
help="only show items which are on",
)
@click.option(
"-o",
"--output",
type=click.Choice(["table", "plain", "json"]),
default="table",
help="output format to print",
)
def status(output: str, filter_on: bool) -> None:
statuses = compute_current_statuses()
if filter_on:
statuses = {k: v for k, v in statuses.items() if v}
if output == "json":
click.echo(json.dumps(statuses))
elif output == "plain":
if len(statuses) == 0:
click.echo("No items are on.", err=True)
exit(1)
for k, v in statuses.items():
print("{}\t{}".format(k, v))
else:
from tabulate import tabulate
if len(statuses) == 0:
click.echo("No items are on.", err=True)
return
click.echo(
tabulate(
list(statuses.items()),
headers=["What", "On"],
tablefmt="presto",
)
)
@cli_group.command(short_help="flip status on an item", name="flip")
def _flip() -> None:
from autotui.namedtuple_prompt import namedtuple_prompt_funcs
from autotui.shortcuts import load_prompt_and_writeback
from autotui.exceptions import AutoTUIException
statuses = compute_current_statuses()
try:
# prompt for 'what'
what = namedtuple_prompt_funcs(Flip)["what"]()
except AutoTUIException:
click.secho("Did not select anything", err=True, fg="red")
exit(1)
# flip the 'on' value and write back
load_prompt_and_writeback(
Flip,
ext.datafile("flip"),
attr_use_values={
"when": datetime.now,
"what": what,
"on": not statuses.get(what.name, False),
},
)
cli_group(prog_name="flipflop.py")
if __name__ == "__main__":
main()