-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathfulgurate-run
executable file
·146 lines (119 loc) · 4.57 KB
/
fulgurate-run
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
#!/usr/bin/env python2
"""
NAME
----
fulgurate-run - run flashcards in the terminal
SYNOPSIS
--------
*fulgurate-run* ['OPTIONS'] CARDS-FILE [CARDS-FILE ...]
DESCRIPTION
-----------
Runs one or more sets of flashcards interactively at the terminal. Cards can be presented individually (the default) or in batches where several cards will be presented before user feedback is required.
The interaction for each card is as follows. The program first shows the first (top) part of the card. Press any key after deciding on an answer. The program then shows the second (bottom) part of the card. Press ~,1,2,3,4,5 for 0 through 5 respectively, indicating your evaluation of how well you remembered the answer. 0 through 2 are failure responses and 3 through 5 are success.
OPTIONS
-------
*-n* 'YYYY-MM-DD'::
Set the current time. Defaults to the system clock.
*-R* 'NUM'
Set the maximum number of cards to review.
*-N* 'NUM'
Set the maximum number of new cards.
*-r*
Randomly order cards to review, from among all input card sets.
*-b* 'NUM'
Enable batch mode and set the number of cards in one batch.
*-f* 'CMD'
Set a command to filter cards. It should take on stdin a sequence of card data lines consisting of filename, first field, and second field, separated by tabs. It should output to stdout new card data in the same format, which will be shown instead of the original card data.
*-F* 'CMD'
Set a command to execute after a card's second field is shown. It should take cards on stdin in the same format as the command for -f. Its output is ignored.
"""
import cards
import ttyio
def show_batch(cards):
ttyio.clear()
for i, card in enumerate(cards):
print "%i: %s\r" % (i + 1, card.top)
print "\r"
class external_filter:
def __init__(self, command):
import subprocess
self.proc = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def send_card(self, card):
print >> self.proc.stdin, "%s\t%s\t%s" % (card.filename or "", card.top, card.bot)
self.proc.stdin.flush()
def receive(self):
return tuple(p.decode('string_escape') for p in self.proc.stdout.readline().rstrip('\n').split('\t'))
def close(self):
import os
self.proc.stdin.close()
os.waitpid(self.proc.pid, 0)[1]
def review_card(card, clear=True, wait=True, pre_filter=None, ext_filter=None, ext_finish=None):
if clear:
ttyio.clear()
with ttyio.unbuffered(sys.stdin) as input:
if ext_filter is None:
filename, top, bot = card.filename, card.top, card.bot
else:
ext_filter.send_card(card)
filename, top, bot = ext_filter.receive()
if filename:
print "%s\r" % (filename)
print "%s\r" % (top)
if wait:
ttyio.getch()
print "%s\r" % (bot)
if ext_finish is not None:
ext_finish.send_card(card)
while True:
ch = ttyio.getch()
if ch == '`':
return 0
elif ch in "12345":
return int(ch)
if __name__ == "__main__":
import datetime
import sys
import getopt
import argopen
try:
opts, args = getopt.getopt(sys.argv[1:], "n:R:N:rb:f:F:")
if len(args) < 1:
raise getopt.GetoptError("wrong number of positional arguments")
except getopt.GetoptError:
print >> sys.stderr, "usage: %s [-n TIME] [-R NUM] [-N NUM] [-r] [-b NUM] [-f CMD] [-F CMD] CARDS-FILE [...]" % (sys.argv[0])
sys.exit(1)
deck = tuple(cards.load_all(args))
now = datetime.datetime.now()
max_reviews = None
max_new = None
randomize = False
batch_size = None
ext_filter = None
ext_finish = None
for opt, arg in opts:
if opt == '-n':
import dateutil.parser
now = dateutil.parser.parse(arg)
elif opt == '-R':
max_reviews = int(arg)
elif opt == '-N':
max_new = int(arg)
elif opt == '-r':
randomize = True
elif opt == '-b':
batch_size = int(arg)
elif opt == '-f':
ext_filter = external_filter(arg)
elif opt == '-F':
ext_finish = external_filter(arg)
try:
with ttyio.unbuffered(sys.stdin) as input:
now = now.replace(hour=0, minute=0, second=0, microsecond=0)
if batch_size is None:
cards.run_cards(deck, now, lambda *args: review_card(*args, ext_filter=ext_filter, ext_finish=ext_finish), max_reviews=max_reviews, max_new=max_new, randomize=randomize)
else:
cards.bulk_review(deck, now, batch_size, show_batch, lambda *args: review_card(*args, clear=False, wait=False, ext_filter=ext_filter, ext_finish=ext_finish), max_reviews=max_reviews, max_new=max_new, randomize=randomize)
except KeyboardInterrupt:
pass
finally:
cards.save_all(deck)