{"id":41223085,"url":"https://github.com/kot149/zmk-layout-shift","last_synced_at":"2026-01-23T00:24:57.460Z","repository":{"id":298345091,"uuid":"998217444","full_name":"kot149/zmk-layout-shift","owner":"kot149","description":"ZMK module to dynamically shift keyboard layouts at runtime","archived":false,"fork":false,"pushed_at":"2025-08-13T14:31:41.000Z","size":85,"stargazers_count":5,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"v1","last_synced_at":"2025-08-13T15:44:37.623Z","etag":null,"topics":["zmk","zmk-module"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kot149.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-08T05:48:44.000Z","updated_at":"2025-08-13T14:31:44.000Z","dependencies_parsed_at":"2025-08-01T03:17:51.274Z","dependency_job_id":"e66b240b-870d-4f4f-9774-765840c08987","html_url":"https://github.com/kot149/zmk-layout-shift","commit_stats":null,"previous_names":["kot149/zmk-layout-shift"],"tags_count":0,"template":false,"template_full_name":"zmkfirmware/zmk-module-template","purl":"pkg:github/kot149/zmk-layout-shift","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kot149%2Fzmk-layout-shift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kot149%2Fzmk-layout-shift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kot149%2Fzmk-layout-shift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kot149%2Fzmk-layout-shift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kot149","download_url":"https://codeload.github.com/kot149/zmk-layout-shift/tar.gz/refs/heads/v1","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kot149%2Fzmk-layout-shift/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28675934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T20:48:19.482Z","status":"ssl_error","status_checked_at":"2026-01-22T20:48:14.968Z","response_time":144,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["zmk","zmk-module"],"created_at":"2026-01-23T00:24:56.977Z","updated_at":"2026-01-23T00:24:57.453Z","avatar_url":"https://github.com/kot149.png","language":"C","readme":"# ZMK Layout Shift Module\n\n[ English / [日本語](README_ja.md) ]\n\nThis module provides a mechanism to dynamically shift keyboard layouts at runtime, primarily intended to solve discrepancies when an OS is configured for a non-US layout (e.g., JIS).\n\nSpecifically, this module provides a behavior `\u0026kpls` that maps keycodes according to the current layout shift state. By overriding the `\u0026kp` behavior with `\u0026kpls`, it works without modifying your keymap, while preserving [Keymap Editor](https://nickcoutsos.github.io/keymap-editor/) compatibility.\n\n## Behaviors\n\nThis module defines the following behaviors:\n\n- `\u0026kpls`: A layout-aware version of `\u0026kp`; maps keycodes according to the current layout shift state. For example, `\u0026kpls EQUAL` normally outputs `=`, but outputs `_` (which is `=` in JIS layout) when JIS layout is enabled.\n- `\u0026tog_ls`: Toggles the layout shift state\n- `\u0026tog_ls_on`: Turns on the layout shift state\n- `\u0026tog_ls_off`: Turns off the layout shift state\n\nOptionally, you can `#include` [`layout_shift_kp_override.dtsi`](dts/layout_shift_kp_override.dtsi) to override the `\u0026kp` behavior with `\u0026kpls`, so that you can use layout shift without modifying your keymap, while preserving [Keymap Editor](https://nickcoutsos.github.io/keymap-editor/) compatibility.\n\n## List of Supported Layouts\n\n- **JIS**: Japanese keyboard layout\n- **Dvorak**: Dvorak keyboard layout\n- **Swap Ctrl and Cmd**: Swap Ctrl / Cmd for Windows / Mac (Note: Currently, this only works with pure modifier key presses (like `\u0026kp LEFT_CONTROL`) or mod-taps (like `\u0026mt LEFT_CONTROL A`). It doesn't work for modifiers applied to non-modifier key presses (like `\u0026kp LCTL(C)`)).\n\n## Usage\n\n### 1. Add the Module to your `west.yml`\n\n```yml\nmanifest:\n  remotes:\n    - name: zmkfirmware\n      url-base: https://github.com/zmkfirmware\n    - name: kot149\n      url-base: https://github.com/kot149\n  projects:\n    - name: zmk\n      remote: zmkfirmware\n      revision: main\n      import: app/west.yml\n    - name: zmk-layout-shift\n      remote: kot149\n      revision: v1\n  self:\n    path: config\n```\n\n### 2. Update your Keymap\n\n1. `#include` [`layout_shift.dtsi`](dts/layout_shift.dtsi) at the top of your keymap:\n   ```c\n   #include \u003clayout_shift.dtsi\u003e\n   ```\n\n2. Select the target layout by selecting one from [`LAYOUT_SHIFT_TARGET_LAYOUT` choice](Kconfig) and add it to your .conf file (e.g., `your_keyboard.conf`):\n   ```kconfig\n   CONFIG_LAYOUT_SHIFT_TARGET_JIS=y # Japanese (JIS) layout\n   # or\n   CONFIG_LAYOUT_SHIFT_TARGET_DVORAK=y # Dvorak layout\n   # etc.\n   ```\n\n3. Add `\u0026tog_ls` / `\u0026tog_ls_on` / `\u0026tog_ls_off` to your keymap and use `\u0026kpls` instead of `\u0026kp` to allow toggling the layout:\n   ```dts\n   #include \u003clayout_shift.dtsi\u003e\n\n   / {\n       keymap {\n           compatible = \"zmk,keymap\";\n\n           default_layer {\n               bindings = \u003c\n                   \u0026kpls EQUAL    // Will output = normally, but _ (which is = on JIS layout) for JIS layout\n                   \u0026tog_ls        // Toggle layout shift on/off\n                   \u0026tog_ls_on     // Turn layout shift on\n                   \u0026tog_ls_off    // Turn layout shift off\n               \u003e;\n           };\n       };\n   };\n   ```\n\n### 3. Override `\u0026kp` Behavior (Optional)\n\nYou can `#include` [`layout_shift_kp_override.dtsi`](dts/layout_shift_kp_override.dtsi) to override the `\u0026kp` behavior with `\u0026kpls`, so that you can use layout shift without modifying your keymap, while preserving [Keymap Editor](https://nickcoutsos.github.io/keymap-editor/) compatibility.\n\n```c\n#include \u003clayout_shift_kp_override.dtsi\u003e\n```\nNote: You can omit `layout_shift.dtsi` as it's also included in `layout_shift_kp_override.dtsi`.\n\n\u003e [!important]\n\u003e You need to add this include \\*\\***below**\\*\\* the `#include \u003cbehaviors.dtsi\u003e` or other includes to make it work.\n\u003e However, [Keymap Editor](https://nickcoutsos.github.io/keymap-editor/) automatically reorders the includes. To avoid this, you can copy-paste the definition of `\u0026kp` from [`layout_shift_kp_override.dtsi`](dts/layout_shift_kp_override.dtsi) directly to your keymap file.\n\n\nNow you can use `\u0026kp` as usual:\n\n```dts\n#include \u003clayout_shift_kp_override.dtsi\u003e\n\n/ {\n    keymap {\n        compatible = \"zmk,keymap\";\n\n        default_layer {\n            bindings = \u003c\n                \u0026kp EQUAL      // Will output = normally, but _ (which is = on JIS layout) for JIS layout\n                \u0026tog_ls        // Toggle layout shift on/off\n                \u0026tog_ls_on     // Turn layout shift on\n                \u0026tog_ls_off    // Turn layout shift off\n            \u003e;\n        };\n    };\n};\n```\n\n## Adding New Layouts\n\n### Step 1: Add Kconfig Option\n\nAdd a new option to the `choice` block in [`Kconfig`](Kconfig):\n\n```kconfig\nchoice LAYOUT_SHIFT_TARGET_LAYOUT\n    prompt \"Target keyboard layout\"\n    default LAYOUT_SHIFT_TARGET_JIS\n\nconfig LAYOUT_SHIFT_TARGET_JIS\n    bool \"Japanese (JIS)\"\n\nconfig LAYOUT_SHIFT_TARGET_DVORAK\n    bool \"Dvorak\"\n\n...\n\nconfig LAYOUT_SHIFT_TARGET_COLEMAK    # Add this line\n    bool \"Colemak\"                    # Add this line\n\nendchoice\n```\n\n### Step 2: Create Layout Definition File\n\nCreate a new layout file in [`src/layouts/`](src/layouts/) (e.g., `layout_colemak.h`):\n\n```c\n#ifdef CONFIG_LAYOUT_SHIFT_TARGET_COLEMAK\n#define LAYOUT_DEFINED\n// Colemak keyboard layout mappings\n// Maps US QWERTY keycodes to their Colemak equivalents\nstatic const struct keycode_mapping layout_map[] = {\n    /* from -\u003e to, optional_modifiers */\n    {E, F, OPTIONAL_ALL},                   // E -\u003e F (all modifiers optional for letters)\n    {R, P, OPTIONAL_ALL},                   // R -\u003e P (all modifiers optional for letters)\n    {T, G, OPTIONAL_ALL},                   // T -\u003e G (all modifiers optional for letters)\n    // ... add more mappings as needed\n    // For symbols, you might want to require certain modifiers:\n    // {COMMA, W, OPTIONAL_CTRL | OPTIONAL_ALT},  // , -\u003e W (Shift required, Ctrl/Alt optional)\n};\n#endif\n```\n\n**Optional Modifier Control Options:**\n- `OPTIONAL_NONE` (0): All modifiers required (exact match)\n- `OPTIONAL_SHIFT`: Shift keys are optional during matching\n- `OPTIONAL_CTRL`: Ctrl keys are optional during matching\n- `OPTIONAL_ALT`: Alt keys are optional during matching\n- `OPTIONAL_GUI`: GUI (Windows/Cmd) keys are optional during matching\n- `OPTIONAL_ALL` (0xFF): All modifiers optional during matching\n- Custom combinations: `OPTIONAL_CTRL | OPTIONAL_ALT` (Ctrl/Alt optional, Shift/GUI required)\n\nReferences:\n- [`zmk/keys.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/keys.h)\n- [`zmk/modifiers.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/modifiers.h)\n\n### Step 3: Include in Index File\n\nAdd the include statement to [`src/layouts/index.h`](src/layouts/index.h):\n\n```c\n// Layout index - includes all available layout definitions\n// Each layout file contains its own conditional compilation directives\n\n#include \"layout_jis.h\"\n#include \"layout_dvorak.h\"\n...\n#include \"layout_colemak.h\"    // Add this line\n\n// Ensure at least one layout is defined\n#ifndef LAYOUT_DEFINED\n#error \"No target layout selected. Please select a layout in Kconfig.\"\n#endif\n```\n\n### Step 4: Update Documentation\n\nUpdate this README.md to list the new layout in the \"List of Supported Layouts\" section.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkot149%2Fzmk-layout-shift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkot149%2Fzmk-layout-shift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkot149%2Fzmk-layout-shift/lists"}