summaryrefslogtreecommitdiff
path: root/lib/python/qmk/cli/info.py
blob: 572b305cacb2192e0e393a25742dedee7a209a5b (plain)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""Keyboard information script.

Compile an info.json for a particular keyboard and pretty-print it.
"""
import json
import platform

from milc import cli

from qmk.json_encoders import InfoJSONEncoder
from qmk.constants import COL_LETTERS, ROW_LETTERS
from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.keyboard import keyboard_completer, keyboard_folder, render_layouts, render_layout
from qmk.keymap import locate_keymap
from qmk.info import info_json
from qmk.path import is_keyboard

platform_id = platform.platform().lower()


def show_keymap(kb_info_json, title_caps=True):
    """Render the keymap in ascii art.
    """
    keymap_path = locate_keymap(cli.config.info.keyboard, cli.config.info.keymap)

    if keymap_path and keymap_path.suffix == '.json':
        if title_caps:
            cli.echo('{fg_blue}Keymap "%s"{fg_reset}:', cli.config.info.keymap)
        else:
            cli.echo('{fg_blue}keymap_%s{fg_reset}:', cli.config.info.keymap)

        keymap_data = json.load(keymap_path.open(encoding='utf-8'))
        layout_name = keymap_data['layout']

        for layer_num, layer in enumerate(keymap_data['layers']):
            if title_caps:
                cli.echo('{fg_cyan}Layer %s{fg_reset}:', layer_num)
            else:
                cli.echo('{fg_cyan}layer_%s{fg_reset}:', layer_num)

            print(render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, layer))


def show_layouts(kb_info_json, title_caps=True):
    """Render the layouts with info.json labels.
    """
    for layout_name, layout_art in render_layouts(kb_info_json, cli.config.info.ascii).items():
        title = layout_name.title() if title_caps else layout_name
        cli.echo('{fg_cyan}%s{fg_reset}:', title)
        print(layout_art)  # Avoid passing dirty data to cli.echo()


def show_matrix(kb_info_json, title_caps=True):
    """Render the layout with matrix labels in ascii art.
    """
    for layout_name, layout in kb_info_json['layouts'].items():
        # Build our label list
        labels = []
        for key in layout['layout']:
            if 'matrix' in key:
                row = ROW_LETTERS[key['matrix'][0]]
                col = COL_LETTERS[key['matrix'][1]]

                labels.append(row + col)
            else:
                labels.append('')

        # Print the header
        if title_caps:
            cli.echo('{fg_blue}Matrix for "%s"{fg_reset}:', layout_name)
        else:
            cli.echo('{fg_blue}matrix_%s{fg_reset}:', layout_name)

        print(render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, labels))


def print_friendly_output(kb_info_json):
    """Print the info.json in a friendly text format.
    """
    cli.echo('{fg_blue}Keyboard Name{fg_reset}: %s', kb_info_json.get('keyboard_name', 'Unknown'))
    cli.echo('{fg_blue}Manufacturer{fg_reset}: %s', kb_info_json.get('manufacturer', 'Unknown'))
    if 'url' in kb_info_json:
        cli.echo('{fg_blue}Website{fg_reset}: %s', kb_info_json.get('url', ''))
    if kb_info_json.get('maintainer', 'qmk') == 'qmk':
        cli.echo('{fg_blue}Maintainer{fg_reset}: QMK Community')
    else:
        cli.echo('{fg_blue}Maintainer{fg_reset}: %s', kb_info_json['maintainer'])
    cli.echo('{fg_blue}Keyboard Folder{fg_reset}: %s', kb_info_json.get('keyboard_folder', 'Unknown'))
    cli.echo('{fg_blue}Layouts{fg_reset}: %s', ', '.join(sorted(kb_info_json['layouts'].keys())))
    if 'width' in kb_info_json and 'height' in kb_info_json:
        cli.echo('{fg_blue}Size{fg_reset}: %s x %s' % (kb_info_json['width'], kb_info_json['height']))
    cli.echo('{fg_blue}Processor{fg_reset}: %s', kb_info_json.get('processor', 'Unknown'))
    cli.echo('{fg_blue}Bootloader{fg_reset}: %s', kb_info_json.get('bootloader', 'Unknown'))
    if 'layout_aliases' in kb_info_json:
        aliases = [f'{key}={value}' for key, value in kb_info_json['layout_aliases'].items()]
        cli.echo('{fg_blue}Layout aliases:{fg_reset} %s' % (', '.join(aliases),))

    if cli.config.info.layouts:
        show_layouts(kb_info_json, True)

    if cli.config.info.matrix:
        show_matrix(kb_info_json, True)

    if cli.config_source.info.keymap and cli.config_source.info.keymap != 'config_file':
        show_keymap(kb_info_json, True)


def print_text_output(kb_info_json):
    """Print the info.json in a plain text format.
    """
    for key in sorted(kb_info_json):
        if key == 'layouts':
            cli.echo('{fg_blue}layouts{fg_reset}: %s', ', '.join(sorted(kb_info_json['layouts'].keys())))
        else:
            cli.echo('{fg_blue}%s{fg_reset}: %s', key, kb_info_json[key])

    if cli.config.info.layouts:
        show_layouts(kb_info_json, False)

    if cli.config.info.matrix:
        show_matrix(kb_info_json, False)

    if cli.config_source.info.keymap and cli.config_source.info.keymap != 'config_file':
        show_keymap(kb_info_json, False)


@cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.')
@cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.')
@cli.argument('-l', '--layouts', action='store_true', help='Render the layouts.')
@cli.argument('-m', '--matrix', action='store_true', help='Render the layouts with matrix information.')
@cli.argument('-f', '--format', default='friendly', arg_only=True, help='Format to display the data in (friendly, text, json) (Default: friendly).')
@cli.argument('--ascii', action='store_true', default='windows' in platform_id, help='Render layout box drawings in ASCII only.')
@cli.subcommand('Keyboard information.')
@automagic_keyboard
@automagic_keymap
def info(cli):
    """Compile an info.json for a particular keyboard and pretty-print it.
    """
    # Determine our keyboard(s)
    if not cli.config.info.keyboard:
        cli.log.error('Missing parameter: --keyboard')
        cli.subcommands['info'].print_help()
        return False

    if not is_keyboard(cli.config.info.keyboard):
        cli.log.error('Invalid keyboard: "%s"', cli.config.info.keyboard)
        return False

    # Build the info.json file
    kb_info_json = info_json(cli.config.info.keyboard)

    # Output in the requested format
    if cli.args.format == 'json':
        print(json.dumps(kb_info_json, cls=InfoJSONEncoder))
    elif cli.args.format == 'text':
        print_text_output(kb_info_json)
    elif cli.args.format == 'friendly':
        print_friendly_output(kb_info_json)
    else:
        cli.log.error('Unknown format: %s', cli.args.format)
        return False