Source code for skim.application.layer_transformer

"""Layer adaptor for transforming keymap layouts between formats.

This module provides the :class:`LayerAdaptor` which transforms keymap layer
data from Keybard and Vial source formats into the internal Skim format.
Different keyboard firmware tools use different key ordering conventions,
and this adaptor handles the necessary reordering.

The Svalboard keyboard has a specific physical layout:
    - 8 finger clusters (4 per hand, 6 keys each)
    - 2 thumb clusters (1 per hand, 6 keys each)
    - Total: 60 keys per layer

Source formats (Keybard/Vial) order keys as:
    Left Thumb → Left Fingers → Right Thumb → Right Fingers

Internal Skim format orders keys as:
    Right Fingers → Left Fingers → Right Thumb → Left Thumb

Example:
    Converting Keybard layers::

        from skim.application.layer_transformer import LayerAdaptor

        keybard_layers = [["KC_A", "KC_B", ...], ...]  # 60 keys per layer
        skim_layers = LayerAdaptor.from_keybard(keybard_layers)

    Converting Vial layers::

        vial_layers = [[[...], [...]], ...]  # Nested cluster format
        skim_layers = LayerAdaptor.from_vial(vial_layers)
"""


[docs] class LayerAdaptor: """Transforms keymap layer layouts from Keybard/Vial to Skim format. This class provides static methods for converting between different keymap file formats. The transformation involves reordering keys from source format conventions to the internal Skim rendering order. The Svalboard's physical layout requires specific cluster ordering for correct visual representation. This adaptor handles the mapping from how keyboard firmware stores keycodes to how Skim needs them for image generation. Note: All methods are class methods and don't require instantiation. The class is used as a namespace for related transformation functions. Example: >>> # Direct usage without instantiation >>> keybard_layer = ["KC_A"] * 60 >>> skim_layers = LayerAdaptor.from_keybard([keybard_layer]) >>> len(skim_layers[0]) 60 """
[docs] @classmethod def from_keybard(cls, layers: list[list[str]]) -> list[list[str]]: """Transform Keybard layer format to internal Skim format. Keybard stores keycodes as a flat list in source order. This method reorders the keys for each layer to match Skim's rendering expectations. Args: layers: List of layers, where each layer is a flat list of 60 keycode strings in Keybard order. Returns: List of layers with keycodes reordered to Skim format. Example: >>> keybard_layers = parser.parse(content) >>> skim_layers = LayerAdaptor.from_keybard(keybard_layers) """ return [cls._single_layer_adaptor(layer) for layer in layers]
[docs] @classmethod def from_vial(cls, layers: list[list[list[str]]]) -> list[list[str]]: """Transform Vial layer format to internal Skim format. Vial stores keycodes grouped by clusters (nested lists). This method flattens the cluster structure and reorders keys for each layer to match Skim's rendering expectations. Args: layers: List of layers, where each layer contains a list of clusters, and each cluster is a list of keycode strings. Returns: List of layers with keycodes flattened and reordered to Skim format. Example: >>> vial_layers = parser.parse(content) >>> skim_layers = LayerAdaptor.from_vial(vial_layers) """ return [ cls._single_layer_adaptor([label for cluster in layer for label in cluster]) for layer in layers ]
@classmethod def _single_layer_adaptor(cls, layer_keycodes: list[str]) -> list[str]: """Transform a single layer's keycodes to Skim rendering order. Remaps key positions from Keybard/Vial physical order to Skim's visual rendering order. The transformation accounts for the Svalboard's split keyboard layout with finger and thumb clusters. Source ordering (Keybard/Vial): - Indices 0-5: Left Thumb cluster - Indices 6-29: Left Finger clusters (4 clusters × 6 keys) - Indices 30-35: Right Thumb cluster - Indices 36-59: Right Finger clusters (4 clusters × 6 keys) Target ordering (Skim): - Indices 0-23: Right Finger clusters - Indices 24-47: Left Finger clusters - Indices 48-53: Right Thumb cluster - Indices 54-59: Left Thumb cluster Within each cluster, keys are also reordered according to specific thumb and finger mapping tables. Args: layer_keycodes: Flat list of 60 keycode strings in source order. Returns: Flat list of 60 keycode strings in Skim rendering order. """ mapped_list: list[str] = [""] * 60 thumb_mapping = [4, 2, -2, -2, -2, 0] finger_mapping = [3, 1, -2, -2, 0, 0] oIdx = 0 for idx, label in enumerate(layer_keycodes[36:]): mapped_list[oIdx + finger_mapping[idx % 6]] = label oIdx += 1 for idx, label in enumerate(layer_keycodes[6:30]): mapped_list[oIdx + finger_mapping[idx % 6]] = label oIdx += 1 for idx, label in enumerate(layer_keycodes[30:36]): mapped_list[oIdx + thumb_mapping[idx % 6]] = label oIdx += 1 for idx, label in enumerate(layer_keycodes[0:6]): mapped_list[oIdx + thumb_mapping[idx % 6]] = label oIdx += 1 return mapped_list