diff options
| author | Ryan <fauxpark@gmail.com> | 2020-11-02 19:41:01 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-11-02 00:41:01 -0800 |
| commit | e69da2db2c59a8017f0c9dee9933dd508d22b356 (patch) | |
| tree | 69dbe7f0731199331f6975df2ada13feab09eaeb /lib | |
| parent | dc40f00aafeea148d8998c594c4e414d87ee84a3 (diff) | |
| download | qmk_firmware-e69da2db2c59a8017f0c9dee9933dd508d22b356.tar.gz qmk_firmware-e69da2db2c59a8017f0c9dee9933dd508d22b356.zip | |
`qmk info`: Add `--ascii` flag (#10793)
* `qmk info`: Add `--ascii` flag
* Fix typo
* Force ASCII for Windows/MSYS2
* Make it gooder
* Remove redundant windows check
* ...And this too
* Make pytest work on Windows
Diffstat (limited to 'lib')
| -rwxr-xr-x | lib/python/qmk/cli/info.py | 12 | ||||
| -rw-r--r-- | lib/python/qmk/keyboard.py | 37 | ||||
| -rw-r--r-- | lib/python/qmk/tests/test_cli_commands.py | 17 |
3 files changed, 52 insertions, 14 deletions
diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index 44ce1186a..9ab299a21 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | Compile an info.json for a particular keyboard and pretty-print it. | 3 | Compile an info.json for a particular keyboard and pretty-print it. |
| 4 | """ | 4 | """ |
| 5 | import json | 5 | import json |
| 6 | import platform | ||
| 6 | 7 | ||
| 7 | from milc import cli | 8 | from milc import cli |
| 8 | 9 | ||
| @@ -12,6 +13,8 @@ from qmk.keymap import locate_keymap | |||
| 12 | from qmk.info import info_json | 13 | from qmk.info import info_json |
| 13 | from qmk.path import is_keyboard | 14 | from qmk.path import is_keyboard |
| 14 | 15 | ||
| 16 | platform_id = platform.platform().lower() | ||
| 17 | |||
| 15 | ROW_LETTERS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop' | 18 | ROW_LETTERS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop' |
| 16 | COL_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijilmnopqrstuvwxyz' | 19 | COL_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijilmnopqrstuvwxyz' |
| 17 | 20 | ||
| @@ -36,13 +39,13 @@ def show_keymap(kb_info_json, title_caps=True): | |||
| 36 | else: | 39 | else: |
| 37 | cli.echo('{fg_cyan}layer_%s{fg_reset}:', layer_num) | 40 | cli.echo('{fg_cyan}layer_%s{fg_reset}:', layer_num) |
| 38 | 41 | ||
| 39 | print(render_layout(kb_info_json['layouts'][layout_name]['layout'], layer)) | 42 | print(render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, layer)) |
| 40 | 43 | ||
| 41 | 44 | ||
| 42 | def show_layouts(kb_info_json, title_caps=True): | 45 | def show_layouts(kb_info_json, title_caps=True): |
| 43 | """Render the layouts with info.json labels. | 46 | """Render the layouts with info.json labels. |
| 44 | """ | 47 | """ |
| 45 | for layout_name, layout_art in render_layouts(kb_info_json).items(): | 48 | for layout_name, layout_art in render_layouts(kb_info_json, cli.config.info.ascii).items(): |
| 46 | title = layout_name.title() if title_caps else layout_name | 49 | title = layout_name.title() if title_caps else layout_name |
| 47 | cli.echo('{fg_cyan}%s{fg_reset}:', title) | 50 | cli.echo('{fg_cyan}%s{fg_reset}:', title) |
| 48 | print(layout_art) # Avoid passing dirty data to cli.echo() | 51 | print(layout_art) # Avoid passing dirty data to cli.echo() |
| @@ -69,7 +72,7 @@ def show_matrix(kb_info_json, title_caps=True): | |||
| 69 | else: | 72 | else: |
| 70 | cli.echo('{fg_blue}matrix_%s{fg_reset}:', layout_name) | 73 | cli.echo('{fg_blue}matrix_%s{fg_reset}:', layout_name) |
| 71 | 74 | ||
| 72 | print(render_layout(kb_info_json['layouts'][layout_name]['layout'], labels)) | 75 | print(render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, labels)) |
| 73 | 76 | ||
| 74 | 77 | ||
| 75 | def print_friendly_output(kb_info_json): | 78 | def print_friendly_output(kb_info_json): |
| @@ -124,6 +127,7 @@ def print_text_output(kb_info_json): | |||
| 124 | @cli.argument('-l', '--layouts', action='store_true', help='Render the layouts.') | 127 | @cli.argument('-l', '--layouts', action='store_true', help='Render the layouts.') |
| 125 | @cli.argument('-m', '--matrix', action='store_true', help='Render the layouts with matrix information.') | 128 | @cli.argument('-m', '--matrix', action='store_true', help='Render the layouts with matrix information.') |
| 126 | @cli.argument('-f', '--format', default='friendly', arg_only=True, help='Format to display the data in (friendly, text, json) (Default: friendly).') | 129 | @cli.argument('-f', '--format', default='friendly', arg_only=True, help='Format to display the data in (friendly, text, json) (Default: friendly).') |
| 130 | @cli.argument('--ascii', action='store_true', default='windows' in platform_id, help='Render layout box drawings in ASCII only.') | ||
| 127 | @cli.subcommand('Keyboard information.') | 131 | @cli.subcommand('Keyboard information.') |
| 128 | @automagic_keyboard | 132 | @automagic_keyboard |
| 129 | @automagic_keymap | 133 | @automagic_keymap |
| @@ -132,7 +136,7 @@ def info(cli): | |||
| 132 | """ | 136 | """ |
| 133 | # Determine our keyboard(s) | 137 | # Determine our keyboard(s) |
| 134 | if not cli.config.info.keyboard: | 138 | if not cli.config.info.keyboard: |
| 135 | cli.log.error('Missing paramater: --keyboard') | 139 | cli.log.error('Missing parameter: --keyboard') |
| 136 | cli.subcommands['info'].print_help() | 140 | cli.subcommands['info'].print_help() |
| 137 | return False | 141 | return False |
| 138 | 142 | ||
diff --git a/lib/python/qmk/keyboard.py b/lib/python/qmk/keyboard.py index 9ebb2d77d..a4c287375 100644 --- a/lib/python/qmk/keyboard.py +++ b/lib/python/qmk/keyboard.py | |||
| @@ -9,6 +9,25 @@ from glob import glob | |||
| 9 | from qmk.c_parse import parse_config_h_file | 9 | from qmk.c_parse import parse_config_h_file |
| 10 | from qmk.makefile import parse_rules_mk_file | 10 | from qmk.makefile import parse_rules_mk_file |
| 11 | 11 | ||
| 12 | BOX_DRAWING_CHARACTERS = { | ||
| 13 | "unicode": { | ||
| 14 | "tl": "┌", | ||
| 15 | "tr": "┐", | ||
| 16 | "bl": "└", | ||
| 17 | "br": "┘", | ||
| 18 | "v": "│", | ||
| 19 | "h": "─", | ||
| 20 | }, | ||
| 21 | "ascii": { | ||
| 22 | "tl": " ", | ||
| 23 | "tr": " ", | ||
| 24 | "bl": "|", | ||
| 25 | "br": "|", | ||
| 26 | "v": "|", | ||
| 27 | "h": "_", | ||
| 28 | }, | ||
| 29 | } | ||
| 30 | |||
| 12 | base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep | 31 | base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep |
| 13 | 32 | ||
| 14 | 33 | ||
| @@ -72,10 +91,12 @@ def rules_mk(keyboard): | |||
| 72 | return rules | 91 | return rules |
| 73 | 92 | ||
| 74 | 93 | ||
| 75 | def render_layout(layout_data, key_labels=None): | 94 | def render_layout(layout_data, render_ascii, key_labels=None): |
| 76 | """Renders a single layout. | 95 | """Renders a single layout. |
| 77 | """ | 96 | """ |
| 78 | textpad = [array('u', ' ' * 200) for x in range(50)] | 97 | textpad = [array('u', ' ' * 200) for x in range(50)] |
| 98 | style = 'ascii' if render_ascii else 'unicode' | ||
| 99 | box_chars = BOX_DRAWING_CHARACTERS[style] | ||
| 79 | 100 | ||
| 80 | for key in layout_data: | 101 | for key in layout_data: |
| 81 | x = ceil(key.get('x', 0) * 4) | 102 | x = ceil(key.get('x', 0) * 4) |
| @@ -97,13 +118,13 @@ def render_layout(layout_data, key_labels=None): | |||
| 97 | label = label[:label_len] | 118 | label = label[:label_len] |
| 98 | 119 | ||
| 99 | label_blank = ' ' * label_len | 120 | label_blank = ' ' * label_len |
| 100 | label_border = '─' * label_len | 121 | label_border = box_chars['h'] * label_len |
| 101 | label_middle = label + ' '*label_leftover # noqa: yapf insists there be no whitespace around * | 122 | label_middle = label + ' '*label_leftover # noqa: yapf insists there be no whitespace around * |
| 102 | 123 | ||
| 103 | top_line = array('u', '┌' + label_border + '┐') | 124 | top_line = array('u', box_chars['tl'] + label_border + box_chars['tr']) |
| 104 | lab_line = array('u', '│' + label_middle + '│') | 125 | lab_line = array('u', box_chars['v'] + label_middle + box_chars['v']) |
| 105 | mid_line = array('u', '│' + label_blank + '│') | 126 | mid_line = array('u', box_chars['v'] + label_blank + box_chars['v']) |
| 106 | bot_line = array('u', '└' + label_border + "┘") | 127 | bot_line = array('u', box_chars['bl'] + label_border + box_chars['br']) |
| 107 | 128 | ||
| 108 | textpad[y][x:x + w] = top_line | 129 | textpad[y][x:x + w] = top_line |
| 109 | textpad[y + 1][x:x + w] = lab_line | 130 | textpad[y + 1][x:x + w] = lab_line |
| @@ -119,13 +140,13 @@ def render_layout(layout_data, key_labels=None): | |||
| 119 | return '\n'.join(lines) | 140 | return '\n'.join(lines) |
| 120 | 141 | ||
| 121 | 142 | ||
| 122 | def render_layouts(info_json): | 143 | def render_layouts(info_json, render_ascii): |
| 123 | """Renders all the layouts from an `info_json` structure. | 144 | """Renders all the layouts from an `info_json` structure. |
| 124 | """ | 145 | """ |
| 125 | layouts = {} | 146 | layouts = {} |
| 126 | 147 | ||
| 127 | for layout in info_json['layouts']: | 148 | for layout in info_json['layouts']: |
| 128 | layout_data = info_json['layouts'][layout]['layout'] | 149 | layout_data = info_json['layouts'][layout]['layout'] |
| 129 | layouts[layout] = render_layout(layout_data) | 150 | layouts[layout] = render_layout(layout_data, render_ascii) |
| 130 | 151 | ||
| 131 | return layouts | 152 | return layouts |
diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py index 7ac0bcbde..7c261db6c 100644 --- a/lib/python/qmk/tests/test_cli_commands.py +++ b/lib/python/qmk/tests/test_cli_commands.py | |||
| @@ -1,7 +1,11 @@ | |||
| 1 | import platform | ||
| 2 | |||
| 1 | from subprocess import STDOUT, PIPE | 3 | from subprocess import STDOUT, PIPE |
| 2 | 4 | ||
| 3 | from qmk.commands import run | 5 | from qmk.commands import run |
| 4 | 6 | ||
| 7 | is_windows = 'windows' in platform.platform().lower() | ||
| 8 | |||
| 5 | 9 | ||
| 6 | def check_subcommand(command, *args): | 10 | def check_subcommand(command, *args): |
| 7 | cmd = ['bin/qmk', command] + list(args) | 11 | cmd = ['bin/qmk', command] + list(args) |
| @@ -148,7 +152,11 @@ def test_info_keymap_render(): | |||
| 148 | check_returncode(result) | 152 | check_returncode(result) |
| 149 | assert 'Keyboard Name: handwired/onekey/pytest' in result.stdout | 153 | assert 'Keyboard Name: handwired/onekey/pytest' in result.stdout |
| 150 | assert 'Processor: STM32F303' in result.stdout | 154 | assert 'Processor: STM32F303' in result.stdout |
| 151 | assert '│A │' in result.stdout | 155 | |
| 156 | if is_windows: | ||
| 157 | assert '|A |' in result.stdout | ||
| 158 | else: | ||
| 159 | assert '│A │' in result.stdout | ||
| 152 | 160 | ||
| 153 | 161 | ||
| 154 | def test_info_matrix_render(): | 162 | def test_info_matrix_render(): |
| @@ -157,7 +165,12 @@ def test_info_matrix_render(): | |||
| 157 | assert 'Keyboard Name: handwired/onekey/pytest' in result.stdout | 165 | assert 'Keyboard Name: handwired/onekey/pytest' in result.stdout |
| 158 | assert 'Processor: STM32F303' in result.stdout | 166 | assert 'Processor: STM32F303' in result.stdout |
| 159 | assert 'LAYOUT_ortho_1x1' in result.stdout | 167 | assert 'LAYOUT_ortho_1x1' in result.stdout |
| 160 | assert '│0A│' in result.stdout | 168 | |
| 169 | if is_windows: | ||
| 170 | assert '|0A|' in result.stdout | ||
| 171 | else: | ||
| 172 | assert '│0A│' in result.stdout | ||
| 173 | |||
| 161 | assert 'Matrix for "LAYOUT_ortho_1x1"' in result.stdout | 174 | assert 'Matrix for "LAYOUT_ortho_1x1"' in result.stdout |
| 162 | 175 | ||
| 163 | 176 | ||
