1# SPDX-FileCopyrightText: 2020 GNOME Foundation
2# SPDX-License-Identifier: Apache-2.0 OR GPL-3.0-or-later
3
4import argparse
5import shutil
6import sys
7import traceback
8
9from . import core, log
10from . import gdindex, gdgenerate, gdgenindices, gdgendeps, gdsearch, gdcheck
11
12
13class GIDocGenApp:
14    """
15    The main GIDocGen application, working as a multiplexer for different
16    commands.
17    """
18    def __init__(self):
19        self.term_width = shutil.get_terminal_size().columns
20        self.formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=int(self.term_width / 2), width=self.term_width)
21
22        self.quiet = False
23        self.commands = {}
24        self.parser = argparse.ArgumentParser(prog='gi-docgen', formatter_class=self.formatter)
25
26        self.subparser = self.parser.add_subparsers(title='Commands',
27                                                    description='If no command is specified, default to help')
28
29        self.add_command('help',
30                         add_args_func=self.add_help_args,
31                         run_func=self.run_help_cmd,
32                         help_msg='Show the help for gi-docgen or a sub-command')
33        self.add_command('index',
34                         add_args_func=gdindex.add_args,
35                         run_func=gdindex.run,
36                         help_msg=gdindex.HELP_MSG)
37        self.add_command('generate',
38                         add_args_func=gdgenerate.add_args,
39                         run_func=gdgenerate.run,
40                         help_msg=gdgenerate.HELP_MSG)
41        self.add_command('gen-index',
42                         add_args_func=gdgenindices.add_args,
43                         run_func=gdgenindices.run,
44                         help_msg=gdgenindices.HELP_MSG)
45        self.add_command('gen-deps',
46                         add_args_func=gdgendeps.add_args,
47                         run_func=gdgendeps.run,
48                         help_msg=gdgendeps.HELP_MSG)
49        self.add_command('search',
50                         add_args_func=gdsearch.add_args,
51                         run_func=gdsearch.run,
52                         help_msg=gdsearch.HELP_MSG)
53        self.add_command('check',
54                         add_args_func=gdcheck.add_args,
55                         run_func=gdcheck.run,
56                         help_msg=gdcheck.HELP_MSG)
57
58    def run(self, args):
59        """
60        Run the main application.
61        """
62        known_commands = list(self.commands.keys()) + ['-h', '--help']
63        if not args or args[0] not in known_commands:
64            args = ['help'] + args
65
66        options = self.parser.parse_args(args)
67
68        # Set up the logging system
69        log.set_quiet(options.quiet)
70        log.set_fatal_warnings(options.fatal_warnings)
71        log.set_log_epoch()
72
73        try:
74            res = options.run_func(options)
75            if 'help' not in args:
76                report_res = log.report()
77            else:
78                report_res = 0
79            if res == 0:
80                return report_res
81            return res
82
83        except Exception:
84            traceback.print_exc()
85            return 1
86
87    def add_command(self, name, add_args_func, run_func, help_msg, aliases=[]):
88        """
89        Add a command to the application.
90
91        @name (str): the name of the command
92        @add_args_func (callable): a function to be called to add the arguments
93        @run_func (callable): a function to be called when running the command
94        @help_msg (str): short help message for the command
95        @aliases (array): a list of aliases for the command
96        """
97        p = self.subparser.add_parser(name, help=help_msg, aliases=aliases, formatter_class=self.formatter)
98
99        # Add shared commands
100        p.add_argument("-q", "--quiet", action="store_true", help="suppress messages except warnings")
101        p.add_argument("--fatal-warnings", action="store_true", help="whether warnings are fatal")
102
103        if add_args_func:
104            add_args_func(p)
105        p.set_defaults(run_func=run_func)
106        for i in [name] + aliases:
107            self.commands[i] = p
108
109    def add_help_args(self, parser):
110        parser.add_argument("-v", "--version", action="store_true", help="show the version of gi-docgen")
111        parser.add_argument('command', nargs='?')
112
113    def run_help_cmd(self, options):
114        if options.version:
115            print(core.version)
116        elif options.command:
117            known_commands = list(self.commands.keys())
118            if options.command not in known_commands:
119                log.error(f'Unknown command {options.command}.')
120                return 1
121            self.commands[options.command].print_help()
122        else:
123            self.parser.print_help()
124        return 0
125
126
127def main():
128    """The entry point expected by setuptools"""
129    return GIDocGenApp().run(sys.argv[1:])
130