Skip to content

Refactor hardware data classes#65

Open
joelspadin wants to merge 8 commits intozmkfirmware:mainfrom
joelspadin:hardware-refactor
Open

Refactor hardware data classes#65
joelspadin wants to merge 8 commits intozmkfirmware:mainfrom
joelspadin:hardware-refactor

Conversation

@joelspadin
Copy link
Collaborator

This implements the design outlined in #47 as well as making a few tangentially related fixes.

Menu rendering is reworked to use Rich's Live object instead of manually printing lines and resetting the cursor to the top of the terminal. The menu is now rendered as a grid, allowing Rich to automatically align columns instead of needing to do that manually, as in the Detail class. Added a new protocol with a function that renders a row in a menu by returning a list of values to display, one per column. Also removed some terminal helper functions that duplicated ones provided by Rich.

Simplified the zmk module remove command so its ProjectWrapper class implements the menu row protocol instead of using Detail.

Added new Revision and BoardTarget classes to simplify parsing and formatting of Zephyr board revisions and board targets, respectively. This now properly formats board targets to insert any revision between the board ID and board qualifiers, which fixes #60.

Extracted the code for discovering hardware and showing hardware selection menus to a new hardware_list.py file, since hardware.py is already very large.

Rewrote all the classes in hardware.py. There are many similarities to the old code, but it is probably easier to review it as if it is a completely new file rather than reviewing the diff. Updated all the zmk keyboard ... commands to use the new classes.

@joelspadin joelspadin added the enhancement New feature or request label Mar 8, 2026
@joelspadin
Copy link
Collaborator Author

There are a bunch of settings fixes here, which could be pulled out to a separate PR if that would make things easier to review, but they're all fairly small so I didn't bother to do that from the start.

@joelspadin
Copy link
Collaborator Author

Put back in the IndexError suppression when confirming a menu selection, as that prevents an error if you type something that filters all items out of the menu and press enter.

@joelspadin
Copy link
Collaborator Author

Added one more fix which isn't really related to the hardware classes, but it depends on the menu refactoring. This should fix the issue some users have reported when trying to use the legacy Windows Console Host instead of Windows Terminal or another more modern terminal. When we detect the console doesn't support VT processing, we now just disable the ability to search menus by typing.

(It's probably possible to make this work since setting the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag did get it to provide a response, but this messed up other parts of the menus, and I don't want to put in the effort to fix something that nobody should really be using anyways.)

@joelspadin joelspadin requested a review from caksoylar March 8, 2026 18:47
@caksoylar
Copy link
Contributor

Giving it an initial try before reviewing, I think backspace handling is not working again, e.g. in zmk keyboard add.

@joelspadin
Copy link
Collaborator Author

That's just because this branch is based off the commit from before that fix. I could rebase it if you want.

The "ruff.enabled" setting is actually named "ruff.enable".

The "python.analysis.typeCheckingMode" setting is ignored when the
corresponding option is set in pyproject.toml, so having it set in
settings.json was unnecessary.
The "source.organizeImports" code action could be handled by other
extensions such as isort. This can result in some strange behaviors
like isort organizing imports on multiple lines, Ruff reformatting them
back to a single line, and the last line of the file getting duplicated.

Explicitly state that we want Ruff to handle organizing imports.
Updated pyright settings to add an exclusion for the "build" directory.
This prevents VS Code from finding copies of zmk files in that
directory and suggesting things from them in code completion.
Menus now use Rich's Live object instead of manually printing lines and
resetting the cursor to the top of the terminal. This also handles
erasing the help line at the bottom of the menu when the menu is closed.

Replaced the hide_cursor(), show_cursor(), and set_cursor_pos()
functions with ones already provided by Rich. Rich doesn't provide a
function to get the cursor position though, so get_cursor_pos() is
still needed. The order of the return values was changed from
(row, col) to (x, y) to match the Rich functions.

Updated the menu to render as a grid. Objects supporting a new MenuRow
protocol can now provide multiple cells of data, which will be aligned
into columns. This replaces the manual padding that was done to align
columns with the Detail class, and it allows Rich to automatically size
the columns based on just the items that are visible.

Also improved the behavior when filtering the menu to try to keep the
focused item in the same spot on the screen, and to prevent cases where
the scroll position is too far down, so there are blank rows even
though there are more items that could be displayed there.
This rewrites the classes for representing hardware (boards, shields,
and interconnects), hardware revisions, and build matrix items to match
the design outlined in zmkfirmware#47.

A new Revision class simplifies the revision handling. It automatically
normalizes revisions to the shortest form for numerical revisions and
uppercase for alphabetical revisions, and it provides operators for
testing equality and ordering.

A new BoardTarget class represents Zephyr board targets. This handles
parsing board IDs, board qualifiers, and revisions from strings and
reassembling them into the expected order with the revision inbetween
the ID and qualifiers.

The old Keyboard class is renamed to KeyboardComponent, since it
represents a component which might or might not be a complete keyboard.
A new Keyboard class now manages combining a board with some number of
shields to create a keyboard.

Code for discovering hardware and prompting the user to select hardware
is extracted to a new hardware_list.py file, since hardware.py is
already very large.

All the "zmk keyboard ..." commands are updated to use the new classes.
There are some minor changes to the messages and formatting of the
output as well.

Fixes zmkfirmware#60.
Fixed an issue where "zmk module remove" would display an error when
attempting to stop Git's fsmonitor--daemon so it can delete the module,
but fsmonitor--daemon was not running. We now silently ignore the error.
Calling terminal.get_cursor_pos() when using the legacy Windows Console
Host resulted in the program hanging waiting for a response on stdin to
an escape sequence that the terminal didn't respond to.

Enabling VT mode temporarily made it respond and provide a cursor
position, but either the return values differed from how a modern
terminal would report them or this interacted strangely with menu
rendering in some other way, as this resulted in parts of menus being
rendered to the wrong locations on any menu with a filter text field.

To work around this, we now simply detect whether VT mode is enabled,
and if it isn't, we disable the filter text field. This allows menus to
mostly work, just without the ability to search by typing.
@joelspadin
Copy link
Collaborator Author

joelspadin commented Mar 9, 2026

Rebased. Also hopefully fixed the prek error. (Not sure why that didn't kick off a CI check though.)

@caksoylar
Copy link
Contributor

caksoylar commented Mar 9, 2026

That's just because this branch is based off the commit from before that fix. I could rebase it if you want.

Thanks for the rebase, I thought it could be an accidental overwrite of the previous fix (didn't check whether patches overlapped).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: CLI Creates Incorrect Revision Format for Zephyr 4+

2 participants