cli: Add --select to filter the stack by index
[quizzer.git] / quizzer / cli.py
1 # Copyright (C) 2013 W. Trevor King <wking@tremily.us>
2 #
3 # This file is part of quizzer.
4 #
5 # quizzer is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # quizzer is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along with
15 # quizzer.  If not, see <http://www.gnu.org/licenses/>.
16
17 import argparse as _argparse
18 import locale as _locale
19
20 from . import __doc__ as _module_doc
21 from . import __version__
22 from . import answerdb as _answerdb
23 from . import quiz as _quiz
24 from .ui import cli as _cli
25
26
27 def main():
28     encoding = _locale.getpreferredencoding(do_setlocale=True)
29
30     parser = _argparse.ArgumentParser(description=_module_doc)
31     parser.add_argument(
32         '--version', action='version',
33         version='%(prog)s {}'.format(__version__))
34     parser.add_argument(
35         '-a', '--answers', metavar='ANSWERS', default='answers.json',
36         help='path to an answers database')
37     parser.add_argument(
38         '--all', action='store_const', const=True, default=False,
39         help=('ask all questions '
40               '(not just never-correctly-answered leaf questions)'))
41     parser.add_argument(
42         '-t', '--tag', action='append',
43         help='limit original questions to those matching at least one tag')
44     parser.add_argument(
45         '-s', '--select', action='append', type=int,
46         help='select questions from the original stack by index')
47     parser.add_argument(
48         '--tags', action='store_const', const=True, default=False,
49         help='instead of running the quiz, print a list of tags on the stack')
50     parser.add_argument(
51         '--questions', action='store_const', const=True, default=False,
52         help=('instead of running the quiz, '
53               'print a list of questions on the stack'))
54     parser.add_argument(
55         'quiz', metavar='QUIZ',
56         help='path to a quiz file')
57
58     args = parser.parse_args()
59
60     quiz = _quiz.Quiz(path=args.quiz, encoding=encoding)
61     quiz.load()
62     answers = _answerdb.AnswerDatabase(path=args.answers, encoding=encoding)
63     try:
64         answers.load()
65     except IOError:
66         pass
67     stack = answers.get_never_correctly_answered(
68         questions=quiz.leaf_questions())
69     if args.all:
70         stack = [question for question in quiz]
71     if args.tag:
72         stack = [q for q in stack if q.tags.intersection(args.tag)]
73     if args.tags:
74         tags = set()
75         for q in stack:
76             tags.update(q.tags)
77         for tag in sorted(tags):
78             print(tag)
79         return
80     if args.select:
81         stack = [stack[i] for i in args.select]
82     if args.questions:
83         for i,q in enumerate(stack):
84             print('Question {}:'.format(i))
85             print(q.format_prompt())
86             print()
87         return
88     ui = _cli.CommandLineInterface(quiz=quiz, answers=answers, stack=stack)
89     ui.run()
90     ui.answers.save()
91     ui.display_results()