1# Copyright (c) 2024 Vestas Wind Systems A/S
2# Copyright (c) 2019 Nordic Semiconductor ASA
3#
4# SPDX-License-Identifier: Apache-2.0
5
6import argparse
7import os
8import re
9import sys
10import textwrap
11from pathlib import Path
12
13from west.commands import WestCommand
14from zephyr_ext_common import ZEPHYR_BASE
15
16sys.path.append(os.fspath(Path(__file__).parent.parent))
17import list_shields
18import zephyr_module
19
20
21class Shields(WestCommand):
22
23    def __init__(self):
24        super().__init__(
25            'shields',
26            # Keep this in sync with the string in west-commands.yml.
27            'display list of supported shield',
28            'Display supported shields',
29            accepts_unknown_args=False)
30
31    def do_add_parser(self, parser_adder):
32        default_fmt = '{name}'
33        parser = parser_adder.add_parser(
34            self.name,
35            help=self.help,
36            formatter_class=argparse.RawDescriptionHelpFormatter,
37            description=self.description,
38            epilog=textwrap.dedent(f'''\
39            FORMAT STRINGS
40            --------------
41
42            Shields are listed using a Python 3 format string. Arguments
43            to the format string are accessed by name.
44
45            The default format string is:
46
47            "{default_fmt}"
48
49            The following arguments are available:
50
51            - name: shield name
52            - full_name: shield full name (typically, its commercial name)
53            - vendor: shield vendor
54            - dir: directory that contains the shield definition
55            '''))
56
57        # Remember to update west-completion.bash if you add or remove
58        # flags
59        parser.add_argument('-f', '--format', default=default_fmt,
60                            help='''Format string to use to list each shield;
61                                    see FORMAT STRINGS below.''')
62        parser.add_argument('-n', '--name', dest='name_re',
63                            help='''a regular expression; only shields whose
64                            names match NAME_RE will be listed''')
65        list_shields.add_args(parser)
66
67        return parser
68
69    def do_run(self, args, _):
70        if args.name_re is not None:
71            name_re = re.compile(args.name_re)
72        else:
73            name_re = None
74
75        modules_board_roots = [ZEPHYR_BASE]
76
77        for module in zephyr_module.parse_modules(ZEPHYR_BASE, self.manifest):
78            board_root = module.meta.get('build', {}).get('settings', {}).get('board_root')
79            if board_root is not None:
80                modules_board_roots.append(Path(module.project) / board_root)
81
82        args.board_roots += modules_board_roots
83
84        for shield in list_shields.find_shields(args):
85            if name_re is not None and not name_re.search(shield.name):
86                continue
87            self.inf(args.format.format(
88                name=shield.name,
89                dir=shield.dir,
90                vendor=shield.vendor if hasattr(shield, 'vendor') else '',
91                full_name=shield.full_name if hasattr(shield, 'full_name') else shield.name
92            ))
93