From 4bac5ba261b3c096e4d1c7054c3edc3fe0b011b2 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Fri, 30 Oct 2020 07:17:28 +1100 Subject: [PATCH 1/7] `qmk info`: Add `--ascii` flag --- lib/python/qmk/cli/info.py | 25 +++++++++++++------------ lib/python/qmk/keyboard.py | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index 44ce1186aa79..3ad8e58d6ce1 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -16,7 +16,7 @@ COL_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijilmnopqrstuvwxyz' -def show_keymap(kb_info_json, title_caps=True): +def show_keymap(kb_info_json, render_ascii, title_caps=True): """Render the keymap in ascii art. """ keymap_path = locate_keymap(cli.config.info.keyboard, cli.config.info.keymap) @@ -36,19 +36,19 @@ def show_keymap(kb_info_json, title_caps=True): else: cli.echo('{fg_cyan}layer_%s{fg_reset}:', layer_num) - print(render_layout(kb_info_json['layouts'][layout_name]['layout'], layer)) + print(render_layout(kb_info_json['layouts'][layout_name]['layout'], render_ascii, layer)) -def show_layouts(kb_info_json, title_caps=True): +def show_layouts(kb_info_json, render_ascii, title_caps=True): """Render the layouts with info.json labels. """ - for layout_name, layout_art in render_layouts(kb_info_json).items(): + for layout_name, layout_art in render_layouts(kb_info_json, render_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): +def show_matrix(kb_info_json, render_ascii, title_caps=True): """Render the layout with matrix labels in ascii art. """ for layout_name, layout in kb_info_json['layouts'].items(): @@ -69,7 +69,7 @@ def show_matrix(kb_info_json, title_caps=True): else: cli.echo('{fg_blue}matrix_%s{fg_reset}:', layout_name) - print(render_layout(kb_info_json['layouts'][layout_name]['layout'], labels)) + print(render_layout(kb_info_json['layouts'][layout_name]['layout'], render_ascii, labels)) def print_friendly_output(kb_info_json): @@ -91,13 +91,13 @@ def print_friendly_output(kb_info_json): cli.echo('{fg_blue}Bootloader{fg_reset}: %s', kb_info_json.get('bootloader', 'Unknown')) if cli.config.info.layouts: - show_layouts(kb_info_json, True) + show_layouts(kb_info_json, cli.config.info.ascii, True) if cli.config.info.matrix: - show_matrix(kb_info_json, True) + show_matrix(kb_info_json, cli.config.info.ascii, True) if cli.config_source.info.keymap and cli.config_source.info.keymap != 'config_file': - show_keymap(kb_info_json, True) + show_keymap(kb_info_json, cli.config.info.ascii, True) def print_text_output(kb_info_json): @@ -110,13 +110,13 @@ def print_text_output(kb_info_json): cli.echo('{fg_blue}%s{fg_reset}: %s', key, kb_info_json[key]) if cli.config.info.layouts: - show_layouts(kb_info_json, False) + show_layouts(kb_info_json, cli.config.info.ascii, False) if cli.config.info.matrix: - show_matrix(kb_info_json, False) + show_matrix(kb_info_json, cli.config.info.ascii, False) if cli.config_source.info.keymap and cli.config_source.info.keymap != 'config_file': - show_keymap(kb_info_json, False) + show_keymap(kb_info_json, cli.config.info.ascii, False) @cli.argument('-kb', '--keyboard', help='Keyboard to show info for.') @@ -124,6 +124,7 @@ def print_text_output(kb_info_json): @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', help='Render layout box drawings in ASCII only.') @cli.subcommand('Keyboard information.') @automagic_keyboard @automagic_keymap diff --git a/lib/python/qmk/keyboard.py b/lib/python/qmk/keyboard.py index 9ebb2d77d30c..07f26fee4fd6 100644 --- a/lib/python/qmk/keyboard.py +++ b/lib/python/qmk/keyboard.py @@ -9,6 +9,25 @@ from qmk.c_parse import parse_config_h_file from qmk.makefile import parse_rules_mk_file +BOX_DRAWING_CHARACTERS = { # noqa: this reads better across multiple lines + "unicode": { + "tl": "┌", + "tr": "┐", + "bl": "└", + "br": "┘", + "v": "│", + "h": "─" + }, + "ascii": { + "tl": " ", + "tr": " ", + "bl": "|", + "br": "|", + "v": "|", + "h": "_" + } +} + base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep @@ -72,10 +91,11 @@ def rules_mk(keyboard): return rules -def render_layout(layout_data, key_labels=None): +def render_layout(layout_data, render_ascii, key_labels=None): """Renders a single layout. """ textpad = [array('u', ' ' * 200) for x in range(50)] + style = 'ascii' if render_ascii else 'unicode' for key in layout_data: x = ceil(key.get('x', 0) * 4) @@ -97,13 +117,13 @@ def render_layout(layout_data, key_labels=None): label = label[:label_len] label_blank = ' ' * label_len - label_border = '─' * label_len + label_border = BOX_DRAWING_CHARACTERS[style]['h'] * label_len label_middle = label + ' '*label_leftover # noqa: yapf insists there be no whitespace around * - top_line = array('u', '┌' + label_border + '┐') - lab_line = array('u', '│' + label_middle + '│') - mid_line = array('u', '│' + label_blank + '│') - bot_line = array('u', '└' + label_border + "┘") + top_line = array('u', BOX_DRAWING_CHARACTERS[style]['tl'] + label_border + BOX_DRAWING_CHARACTERS[style]['tr']) + lab_line = array('u', BOX_DRAWING_CHARACTERS[style]['v'] + label_middle + BOX_DRAWING_CHARACTERS[style]['v']) + mid_line = array('u', BOX_DRAWING_CHARACTERS[style]['v'] + label_blank + BOX_DRAWING_CHARACTERS[style]['v']) + bot_line = array('u', BOX_DRAWING_CHARACTERS[style]['bl'] + label_border + BOX_DRAWING_CHARACTERS[style]['br']) textpad[y][x:x + w] = top_line textpad[y + 1][x:x + w] = lab_line @@ -119,13 +139,13 @@ def render_layout(layout_data, key_labels=None): return '\n'.join(lines) -def render_layouts(info_json): +def render_layouts(info_json, render_ascii): """Renders all the layouts from an `info_json` structure. """ layouts = {} for layout in info_json['layouts']: layout_data = info_json['layouts'][layout]['layout'] - layouts[layout] = render_layout(layout_data) + layouts[layout] = render_layout(layout_data, render_ascii) return layouts From 55b929392f88c1bcea53f8ffc1cfcc5d92977a55 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Fri, 30 Oct 2020 07:28:18 +1100 Subject: [PATCH 2/7] Fix typo --- lib/python/qmk/cli/info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index 3ad8e58d6ce1..e18633d89c07 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -133,7 +133,7 @@ def info(cli): """ # Determine our keyboard(s) if not cli.config.info.keyboard: - cli.log.error('Missing paramater: --keyboard') + cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False From 8bbd0b99fcbc8eae34b9611902c09c6bd14467fa Mon Sep 17 00:00:00 2001 From: fauxpark Date: Fri, 30 Oct 2020 07:34:54 +1100 Subject: [PATCH 3/7] Force ASCII for Windows/MSYS2 --- lib/python/qmk/cli/info.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index e18633d89c07..cb7a4218c49f 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -3,6 +3,7 @@ Compile an info.json for a particular keyboard and pretty-print it. """ import json +import platform from milc import cli @@ -141,6 +142,11 @@ def info(cli): cli.log.error('Invalid keyboard: "%s"', cli.config.info.keyboard) return False + platform_id = platform.platform().lower() + + if 'windows' in platform_id: + cli.config.info.ascii = True + # Build the info.json file kb_info_json = info_json(cli.config.info.keyboard) From 9fc4184707965933982dcc30c357472c496919a4 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Fri, 30 Oct 2020 12:21:26 +1100 Subject: [PATCH 4/7] Make it gooder --- lib/python/qmk/cli/info.py | 28 +++++++++++++++------------- lib/python/qmk/keyboard.py | 19 ++++++++++--------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index cb7a4218c49f..5cbc68842874 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -13,11 +13,13 @@ from qmk.info import info_json from qmk.path import is_keyboard +platform_id = platform.platform().lower() + ROW_LETTERS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop' COL_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijilmnopqrstuvwxyz' -def show_keymap(kb_info_json, render_ascii, title_caps=True): +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) @@ -37,19 +39,19 @@ def show_keymap(kb_info_json, render_ascii, title_caps=True): else: cli.echo('{fg_cyan}layer_%s{fg_reset}:', layer_num) - print(render_layout(kb_info_json['layouts'][layout_name]['layout'], render_ascii, layer)) + print(render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, layer)) -def show_layouts(kb_info_json, render_ascii, title_caps=True): +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, render_ascii).items(): + 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, render_ascii, title_caps=True): +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(): @@ -70,7 +72,7 @@ def show_matrix(kb_info_json, render_ascii, title_caps=True): else: cli.echo('{fg_blue}matrix_%s{fg_reset}:', layout_name) - print(render_layout(kb_info_json['layouts'][layout_name]['layout'], render_ascii, labels)) + print(render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, labels)) def print_friendly_output(kb_info_json): @@ -92,13 +94,13 @@ def print_friendly_output(kb_info_json): cli.echo('{fg_blue}Bootloader{fg_reset}: %s', kb_info_json.get('bootloader', 'Unknown')) if cli.config.info.layouts: - show_layouts(kb_info_json, cli.config.info.ascii, True) + show_layouts(kb_info_json, True) if cli.config.info.matrix: - show_matrix(kb_info_json, cli.config.info.ascii, True) + 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, cli.config.info.ascii, True) + show_keymap(kb_info_json, True) def print_text_output(kb_info_json): @@ -111,13 +113,13 @@ def print_text_output(kb_info_json): cli.echo('{fg_blue}%s{fg_reset}: %s', key, kb_info_json[key]) if cli.config.info.layouts: - show_layouts(kb_info_json, cli.config.info.ascii, False) + show_layouts(kb_info_json, False) if cli.config.info.matrix: - show_matrix(kb_info_json, cli.config.info.ascii, False) + 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, cli.config.info.ascii, False) + show_keymap(kb_info_json, False) @cli.argument('-kb', '--keyboard', help='Keyboard to show info for.') @@ -125,7 +127,7 @@ def print_text_output(kb_info_json): @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', help='Render layout box drawings in ASCII only.') +@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 diff --git a/lib/python/qmk/keyboard.py b/lib/python/qmk/keyboard.py index 07f26fee4fd6..a4c2873757b9 100644 --- a/lib/python/qmk/keyboard.py +++ b/lib/python/qmk/keyboard.py @@ -9,14 +9,14 @@ from qmk.c_parse import parse_config_h_file from qmk.makefile import parse_rules_mk_file -BOX_DRAWING_CHARACTERS = { # noqa: this reads better across multiple lines +BOX_DRAWING_CHARACTERS = { "unicode": { "tl": "┌", "tr": "┐", "bl": "└", "br": "┘", "v": "│", - "h": "─" + "h": "─", }, "ascii": { "tl": " ", @@ -24,8 +24,8 @@ "bl": "|", "br": "|", "v": "|", - "h": "_" - } + "h": "_", + }, } base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep @@ -96,6 +96,7 @@ def render_layout(layout_data, render_ascii, key_labels=None): """ textpad = [array('u', ' ' * 200) for x in range(50)] style = 'ascii' if render_ascii else 'unicode' + box_chars = BOX_DRAWING_CHARACTERS[style] for key in layout_data: x = ceil(key.get('x', 0) * 4) @@ -117,13 +118,13 @@ def render_layout(layout_data, render_ascii, key_labels=None): label = label[:label_len] label_blank = ' ' * label_len - label_border = BOX_DRAWING_CHARACTERS[style]['h'] * label_len + label_border = box_chars['h'] * label_len label_middle = label + ' '*label_leftover # noqa: yapf insists there be no whitespace around * - top_line = array('u', BOX_DRAWING_CHARACTERS[style]['tl'] + label_border + BOX_DRAWING_CHARACTERS[style]['tr']) - lab_line = array('u', BOX_DRAWING_CHARACTERS[style]['v'] + label_middle + BOX_DRAWING_CHARACTERS[style]['v']) - mid_line = array('u', BOX_DRAWING_CHARACTERS[style]['v'] + label_blank + BOX_DRAWING_CHARACTERS[style]['v']) - bot_line = array('u', BOX_DRAWING_CHARACTERS[style]['bl'] + label_border + BOX_DRAWING_CHARACTERS[style]['br']) + top_line = array('u', box_chars['tl'] + label_border + box_chars['tr']) + lab_line = array('u', box_chars['v'] + label_middle + box_chars['v']) + mid_line = array('u', box_chars['v'] + label_blank + box_chars['v']) + bot_line = array('u', box_chars['bl'] + label_border + box_chars['br']) textpad[y][x:x + w] = top_line textpad[y + 1][x:x + w] = lab_line From 2fa52c42dd67d4a3286499cf14863ff44a5bd48b Mon Sep 17 00:00:00 2001 From: fauxpark Date: Fri, 30 Oct 2020 12:22:23 +1100 Subject: [PATCH 5/7] Remove redundant windows check --- lib/python/qmk/cli/info.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index 5cbc68842874..e4b65fe9b67c 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -146,9 +146,6 @@ def info(cli): platform_id = platform.platform().lower() - if 'windows' in platform_id: - cli.config.info.ascii = True - # Build the info.json file kb_info_json = info_json(cli.config.info.keyboard) From f4bc456b1de82ff5653259220ef36bfd30d1d04c Mon Sep 17 00:00:00 2001 From: fauxpark Date: Fri, 30 Oct 2020 12:23:09 +1100 Subject: [PATCH 6/7] ...And this too --- lib/python/qmk/cli/info.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index e4b65fe9b67c..9ab299a21e64 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -144,8 +144,6 @@ def info(cli): cli.log.error('Invalid keyboard: "%s"', cli.config.info.keyboard) return False - platform_id = platform.platform().lower() - # Build the info.json file kb_info_json = info_json(cli.config.info.keyboard) From c18ea1794372ff7ced32214110e1b0d9e2af4309 Mon Sep 17 00:00:00 2001 From: fauxpark Date: Fri, 30 Oct 2020 12:34:49 +1100 Subject: [PATCH 7/7] Make pytest work on Windows --- lib/python/qmk/tests/test_cli_commands.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py index 7ac0bcbde7b6..7c261db6cd39 100644 --- a/lib/python/qmk/tests/test_cli_commands.py +++ b/lib/python/qmk/tests/test_cli_commands.py @@ -1,7 +1,11 @@ +import platform + from subprocess import STDOUT, PIPE from qmk.commands import run +is_windows = 'windows' in platform.platform().lower() + def check_subcommand(command, *args): cmd = ['bin/qmk', command] + list(args) @@ -148,7 +152,11 @@ def test_info_keymap_render(): check_returncode(result) assert 'Keyboard Name: handwired/onekey/pytest' in result.stdout assert 'Processor: STM32F303' in result.stdout - assert '│A │' in result.stdout + + if is_windows: + assert '|A |' in result.stdout + else: + assert '│A │' in result.stdout def test_info_matrix_render(): @@ -157,7 +165,12 @@ def test_info_matrix_render(): assert 'Keyboard Name: handwired/onekey/pytest' in result.stdout assert 'Processor: STM32F303' in result.stdout assert 'LAYOUT_ortho_1x1' in result.stdout - assert '│0A│' in result.stdout + + if is_windows: + assert '|0A|' in result.stdout + else: + assert '│0A│' in result.stdout + assert 'Matrix for "LAYOUT_ortho_1x1"' in result.stdout