Full Code of jtroo/kanata for AI

main 3bda1ec9035c cached
272 files
2.3 MB
609.2k tokens
2523 symbols
1 requests
Download .txt
Showing preview only (2,432K chars total). Download the full file or copy to clipboard to get everything.
Repository: jtroo/kanata
Branch: main
Commit: 3bda1ec9035c
Files: 272
Total size: 2.3 MB

Directory structure:
gitextract_lgrqbydp/

├── .devcontainer/
│   └── devcontainer.json
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   └── feature_request.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── build-everything.yml
│       ├── linux-build.yml
│       ├── macos-build.yml
│       ├── rust.yml
│       └── windows-build.yml
├── .gitignore
├── Cargo.toml
├── EnableUIAccess/
│   ├── EnableUIAccess_launch.ahk
│   ├── Lib/
│   │   └── EnableUIAccess.ahk
│   └── README.md
├── LICENSE
├── README.md
├── build.rs
├── cfg_samples/
│   ├── artsey.kbd
│   ├── automousekeys-full-map.kbd
│   ├── automousekeys-only.kbd
│   ├── chords.tsv
│   ├── colemak.kbd
│   ├── deflayermap.kbd
│   ├── f13_f24.kbd
│   ├── fancy_symbols.kbd
│   ├── home-row-mod-advanced.kbd
│   ├── home-row-mod-basic.kbd
│   ├── home-row-mod-prior-idle.kbd
│   ├── included-file.kbd
│   ├── japanese_mac_eisu_kana.kbd
│   ├── jtroo.kbd
│   ├── kanata.kbd
│   ├── key-toggle_press-only_release-only.kbd
│   ├── minimal.kbd
│   ├── opposite-hand-hrm.kbd
│   ├── push-msg.kbd
│   ├── simple.kbd
│   └── tray-icon/
│       ├── license_icons.txt
│       └── tray-icon.kbd
├── docs/
│   ├── README.md
│   ├── config-stylesheet.css
│   ├── config.adoc
│   ├── design.md
│   ├── fancy_symbols.md
│   ├── interception.md
│   ├── kmonad_comparison.md
│   ├── locales.adoc
│   ├── platform-known-issues.adoc
│   ├── release-template.md
│   ├── sequence-adding-chords-ideas.md
│   ├── setup-linux.md
│   ├── simulated_output/
│   │   ├── sim.kbd
│   │   ├── sim.txt
│   │   └── sim_out.txt
│   ├── simulated_passthru_ahk/
│   │   ├── [COPY HERE] kanata_passthru.dll _
│   │   ├── kanata_dll.kbd
│   │   └── kanata_passthru.ahk
│   └── switch-design
├── example_tcp_client/
│   ├── .gitignore
│   ├── Cargo.toml
│   └── src/
│       └── main.rs
├── interception/
│   ├── Cargo.toml
│   └── src/
│       ├── lib.rs
│       └── scancode.rs
├── justfile
├── key-sort-add/
│   ├── Cargo.toml
│   ├── README.md
│   ├── mapping.txt
│   └── src/
│       └── main.rs
├── keyberon/
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── Cargo.toml
│   ├── KEYBOARDS.md
│   ├── LICENSE
│   ├── README.md
│   ├── keyberon-macros/
│   │   ├── Cargo.toml
│   │   ├── README.md
│   │   └── src/
│   │       └── lib.rs
│   └── src/
│       ├── action/
│       │   └── switch.rs
│       ├── action.rs
│       ├── chord.rs
│       ├── key_code.rs
│       ├── layout/
│       │   └── contextual_execution.rs
│       ├── layout.rs
│       ├── lib.rs
│       ├── multikey_buffer.rs
│       └── tap_hold_tracker.rs
├── parser/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── LICENSE
│   ├── README.md
│   ├── src/
│   │   ├── cfg/
│   │   │   ├── alloc.rs
│   │   │   ├── arbitrary_code.rs
│   │   │   ├── caps_word.rs
│   │   │   ├── chord.rs
│   │   │   ├── chord_v1.rs
│   │   │   ├── clipboard.rs
│   │   │   ├── cmd.rs
│   │   │   ├── custom_tap_hold.rs
│   │   │   ├── defcfg.rs
│   │   │   ├── defhands.rs
│   │   │   ├── deflayer.rs
│   │   │   ├── deflocalkeys.rs
│   │   │   ├── defsrc.rs
│   │   │   ├── deftemplate.rs
│   │   │   ├── error.rs
│   │   │   ├── fake_key.rs
│   │   │   ├── fork.rs
│   │   │   ├── is_a_button.rs
│   │   │   ├── key_outputs.rs
│   │   │   ├── key_override.rs
│   │   │   ├── layer_opts.rs
│   │   │   ├── list_actions.rs
│   │   │   ├── live_reload.rs
│   │   │   ├── macro.rs
│   │   │   ├── mod.rs
│   │   │   ├── mouse.rs
│   │   │   ├── multi.rs
│   │   │   ├── oneshot.rs
│   │   │   ├── override.rs
│   │   │   ├── permutations.rs
│   │   │   ├── platform.rs
│   │   │   ├── push_msg.rs
│   │   │   ├── releases.rs
│   │   │   ├── sequence.rs
│   │   │   ├── sexpr.rs
│   │   │   ├── str_ext.rs
│   │   │   ├── switch.rs
│   │   │   ├── tap_dance.rs
│   │   │   ├── tap_hold.rs
│   │   │   ├── tests/
│   │   │   │   ├── ambiguous.rs
│   │   │   │   ├── defcfg.rs
│   │   │   │   ├── defhands.rs
│   │   │   │   ├── device_detect.rs
│   │   │   │   ├── environment.rs
│   │   │   │   └── macros.rs
│   │   │   ├── tests.rs
│   │   │   ├── unicode.rs
│   │   │   ├── unmod.rs
│   │   │   ├── vars.rs
│   │   │   └── zippychord.rs
│   │   ├── custom_action.rs
│   │   ├── keys/
│   │   │   ├── linux.rs
│   │   │   ├── macos.rs
│   │   │   ├── mappings.rs
│   │   │   ├── mod.rs
│   │   │   └── windows.rs
│   │   ├── layers.rs
│   │   ├── lib.rs
│   │   ├── lsp_hints.rs
│   │   ├── sequences.rs
│   │   ├── subset.rs
│   │   └── trie.rs
│   └── test_cfgs/
│       ├── all_keys_in_defsrc.kbd
│       ├── ancestor_seq.kbd
│       ├── bad_multi.kbd
│       ├── descendant_seq.kbd
│       ├── icon_bad_dupe.kbd
│       ├── icon_good.kbd
│       ├── include-bad.kbd
│       ├── include-bad2.kbd
│       ├── include-good-optional-absent.kbd
│       ├── include-good.kbd
│       ├── included-bad.kbd
│       ├── included-bad2.kbd
│       ├── included-good.kbd
│       ├── macro-chord-dont-panic.kbd
│       ├── multiline_comment.kbd
│       ├── nested_tap_hold.kbd
│       ├── test.zch
│       ├── testzch.kbd
│       ├── unknown_defcfg_opt.kbd
│       ├── utf8bom-included.kbd
│       └── utf8bom.kbd
├── rustfmt.toml
├── scripts/
│   └── test_linux_list_devices.sh
├── simulated_input/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       └── sim.rs
├── simulated_passthru/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── ReadMe.md
│   └── src/
│       ├── key_in.rs
│       ├── key_out.rs
│       ├── lib_passthru.rs
│       └── log_win.rs
├── src/
│   ├── gui/
│   │   ├── mod.rs
│   │   ├── win.rs
│   │   ├── win_dbg_logger/
│   │   │   ├── mod.rs
│   │   │   └── win_dbg_logger.toml
│   │   └── win_nwg_ext/
│   │       ├── license-MIT
│   │       ├── license-nwg-MIT
│   │       └── mod.rs
│   ├── kanata/
│   │   ├── caps_word.rs
│   │   ├── cfg_forced.rs
│   │   ├── clipboard.rs
│   │   ├── cmd.rs
│   │   ├── dynamic_macro.rs
│   │   ├── key_repeat.rs
│   │   ├── linux.rs
│   │   ├── macos.rs
│   │   ├── millisecond_counting.rs
│   │   ├── mod.rs
│   │   ├── output_logic/
│   │   │   └── zippychord.rs
│   │   ├── output_logic.rs
│   │   ├── scroll.rs
│   │   ├── sequences.rs
│   │   ├── unknown.rs
│   │   └── windows/
│   │       ├── exthook.rs
│   │       ├── interception.rs
│   │       ├── llhook.rs
│   │       └── mod.rs
│   ├── kanata.exe.manifest.rc
│   ├── lib.rs
│   ├── main.rs
│   ├── main_lib/
│   │   ├── args.rs
│   │   ├── mod.rs
│   │   └── win_gui.rs
│   ├── oskbd/
│   │   ├── linux.rs
│   │   ├── macos.rs
│   │   ├── mod.rs
│   │   ├── sim_passthru.rs
│   │   ├── simulated.rs
│   │   └── windows/
│   │       ├── exthook_os.rs
│   │       ├── interception.rs
│   │       ├── interception_convert.rs
│   │       ├── llhook/
│   │       │   └── mouse.rs
│   │       ├── llhook.rs
│   │       ├── mod.rs
│   │       └── scancode_to_usvk.rs
│   ├── tcp_server.rs
│   ├── tests/
│   │   ├── passthru_macos_tests.rs
│   │   └── sim_tests/
│   │       ├── block_keys_tests.rs
│   │       ├── capsword_sim_tests.rs
│   │       ├── chord_sim_tests.rs
│   │       ├── delay_tests.rs
│   │       ├── layer_sim_tests.rs
│   │       ├── macro_sim_tests.rs
│   │       ├── mod.rs
│   │       ├── oneshot_tests.rs
│   │       ├── output_chord_tests.rs
│   │       ├── override_tests.rs
│   │       ├── release_sim_tests.rs
│   │       ├── repeat_sim_tests.rs
│   │       ├── seq_sim_tests.rs
│   │       ├── switch_sim_tests.rs
│   │       ├── tap_dance_tests.rs
│   │       ├── tap_hold_tests.rs
│   │       ├── template_sim_tests.rs
│   │       ├── timing_tests.rs
│   │       ├── unicode_sim_tests.rs
│   │       ├── unmod_sim_tests.rs
│   │       ├── use_defsrc_sim_tests.rs
│   │       ├── vkey_sim_tests.rs
│   │       └── zippychord_sim_tests.rs
│   └── tests.rs
├── tcp_protocol/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── wasm/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       └── lib.rs
└── windows_key_tester/
    ├── .gitignore
    ├── Cargo.toml
    ├── README.md
    └── src/
        ├── main.rs
        ├── windows/
        │   ├── interception.rs
        │   └── llhook.rs
        └── windows.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .devcontainer/devcontainer.json
================================================
{
	"name": "Rust",
	"image": "mcr.microsoft.com/devcontainers/rust:1-buster"

	// Features to add to the dev container. More info: https://containers.dev/implementors/features.
	// "features": {},

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// "forwardPorts": [],

	// Use 'postCreateCommand' to run commands after the container is created.
	// "postCreateCommand": "rustc --version",

	// Configure tool-specific properties.
	// "customizations": {},

	// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
	// "remoteUser": "root"
}


================================================
FILE: .gitattributes
================================================
* text=auto eol=lf


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: "Bug report"
description: Create a report to help the project improve.
labels: ["bug"]
assignees: ["jtroo"]
title: "Bug: title_goes_here"
body:
  - type: checkboxes
    attributes:
      label: Requirements
      description: Before you create a bug report, please check the following
      options:
        - label: I've searched [platform-specific issues](https://github.com/jtroo/kanata/blob/main/docs/platform-known-issues.adoc), [issues](https://github.com/jtroo/kanata/issues) and [discussions](https://github.com/jtroo/kanata/discussions) to see if this has been reported before.
          required: true
        - label: My issue does not involve multiple simultaneous key presses, OR it does but I've confirmed it is not [key rollover or ghosting](https://github.com/jtroo/kanata/discussions/822).
          required: true
  - type: textarea
    id: summary
    attributes:
      label: Describe the bug
      description: |
        A clear and concise description of what the bug is.
        Ensure any config snippets are either in the next section or are code formatted.
    validations:
      required: true
  - type: textarea
    id: config
    attributes:
      label: Relevant kanata config
      render: text
      description: E.g. defcfg, defsrc, deflayer, defalias items. If in doubt, feel free to include your entire config.
    validations:
      required: false
  - type: textarea
    id: reproduce
    attributes:
      label: To Reproduce
      description: |
        Walk through the steps needed to reproduce the bug.
        Use the simulator if it is not device/OS related: https://jtroo.github.io/.
    validations:
      required: true
  - type: textarea
    id: expected
    attributes:
      label: Expected behavior
      description: A clear and concise description of what you expected to happen.
    validations:
      required: true
  - type: input
    id: version
    attributes:
      label: Kanata version
      description: The kanata version prints in the log on startup, or you can also print it by passing the `--version` flag when running on the command line.
      placeholder: e.g. kanata 1.3.0
    validations:
      required: true
  - type: textarea
    id: logs
    attributes:
      label: Debug logs
      description: If you think it might help with a non-obvious issue, run kanata from the command line and pass the `--debug` flag. This will print more info. Include the relevant log outputs this section if you did so.
      render: text
    validations:
      required: false
  - type: input
    id: os
    attributes:
      label: Operating system and I/O mechanism
      description: E.g. Linux, macOS, Windows 10, Windows 11 with Interception driver
      placeholder: e.g. Linux
    validations:
      required: true
  - type: textarea
    id: additional
    attributes:
      label: Additional context
      description: Add any other context about the problem here.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
  - name: Discussions
    url: https://github.com/jtroo/kanata/discussions
    about: Ask for help or interact with the community.

================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: "Feature request"
description: Suggest an idea for this project
title: 'Feature request: feature_summary_goes_here'
labels: ["enhancement"]
assignees: []
body:
  - type: textarea
    attributes:
      label: Is your feature request related to a problem? Please describe.
      description: |
        A clear and concise description of what the problem is.
      placeholder: Ex. I'm always frustrated when [...]
    validations:
      required: true
  - type: textarea
    attributes:
      label: Describe the solution you'd like.
      description: |
        A clear and concise description of what you want to happen.
    validations:
      required: true
  - type: textarea
    attributes:
      label: Describe alternatives you've considered.
      description: |
        A clear and concise description of any alternative solutions or features you've considered.
    validations:
      required: true
  - type: textarea
    attributes:
      label: Additional context
      description: |
        Add any other context or screenshots about the feature request here.
    validations:
      required: false


================================================
FILE: .github/pull_request_template.md
================================================
## Describe your changes. Use imperative present tense.

## Checklist

- Add documentation to docs/config.adoc
  - [ ] Yes or N/A
- Add example and basic docs to cfg_samples/kanata.kbd
  - [ ] Yes or N/A
- Update error messages
  - [ ] Yes or N/A
- Added tests, or did manual testing
  - [ ] Yes


================================================
FILE: .github/workflows/build-everything.yml
================================================
name: build-everything

on:
  workflow_dispatch:
    branches: [ "main" ]

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: "-Dwarnings"

jobs:
  build-linux:
    uses: ./.github/workflows/linux-build.yml
  build-windows:
    uses: ./.github/workflows/windows-build.yml
  build-macos:
    uses: ./.github/workflows/macos-build.yml


================================================
FILE: .github/workflows/linux-build.yml
================================================
name: linux-build

on:
  workflow_dispatch:
    branches: [ "main" ]
  workflow_call:

env:
  CARGO_TERM_COLOR: always

jobs:
  build-linux-x64:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: "persist-cross-job-linux-x64"
      - name: Do the stuff on x64 ubuntu linux
        shell: bash
        run: |
          mkdir -p artifacts-x64
          cargo build --release
          mv target/release/kanata artifacts-x64/kanata_linux_x64
          cargo build --release --features cmd
          mv target/release/kanata artifacts-x64/kanata_linux_cmd_allowed_x64
      - uses: actions/upload-artifact@v4
        with:
          name: linux-binaries-x64
          path: |
            artifacts-x64/kanata_linux_x64
            artifacts-x64/kanata_linux_cmd_allowed_x64


================================================
FILE: .github/workflows/macos-build.yml
================================================
name: macos-build

on:
  workflow_dispatch:
    branches: [ "main" ]
  workflow_call:

env:
  CARGO_TERM_COLOR: always

jobs:
  build-macos-arm64:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable
          target: aarch64-apple-darwin
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: "persist-cross-job-macos-aarch64"
      - name: Do the stuff on arm64
        shell: bash
        run: |
          mkdir -p artifacts-arm64
          cargo build --release --target aarch64-apple-darwin
          mv target/aarch64-apple-darwin/release/kanata artifacts-arm64/kanata_macos_arm64
          cargo build --release --features cmd --target aarch64-apple-darwin
          mv target/aarch64-apple-darwin/release/kanata artifacts-arm64/kanata_macos_cmd_allowed_arm64
      - uses: actions/upload-artifact@v4
        with:
          name: macos-binaries-arm64
          path: |
            artifacts-arm64/kanata_macos_arm64
            artifacts-arm64/kanata_macos_cmd_allowed_arm64

  build-macos-x64:
    runs-on: macos-15-intel

    steps:
    - uses: actions/checkout@v3
    - uses: Swatinem/rust-cache@v2
      with:
        shared-key: "persist-cross-job-macos-x64"
    - name: Do the stuff on x64
      shell: bash
      run: |
        mkdir -p artifacts
        cargo build --release
        mv target/release/kanata artifacts/kanata_macos_x64
        cargo build --release --features cmd
        mv target/release/kanata artifacts/kanata_macos_cmd_allowed_x64
    - uses: actions/upload-artifact@v4
      with:
        name: macos-binaries-x64
        path: |
          artifacts/kanata_macos_x64
          artifacts/kanata_macos_cmd_allowed_x64



================================================
FILE: .github/workflows/rust.yml
================================================
name: cargo-checks

on:
  push:
    branches: [ "main" ]
    paths:
      - Cargo.*
      - src/**/*
      - keyberon/**/*
      - cfg_samples/**/*
      - parser/**/*
      - tcp_protocol/**/*
      - wasm/**/*
      - .github/workflows/rust.yml
  pull_request:
    branches: [ "main" ]
    paths:
      - Cargo.*
      - src/**/*
      - keyberon/**/*
      - parser/**/*
      - cfg_samples/**/*
      - tcp_protocol/**/*
      - wasm/**/*
      - .github/workflows/rust.yml

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: "-Dwarnings"

jobs:

  fmt:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Check fmt
      run: cargo fmt --all --check

  build-android:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - build: linux
            os: ubuntu-latest
            target: aarch64-linux-android

    steps:
    - uses: actions/checkout@v3
    - uses: Swatinem/rust-cache@v2
      with:
        shared-key: "persist-cross-job"
        workspaces: ./
    - run: rustup target add aarch64-linux-android

    - name: Build for Android
      run: cargo check --target aarch64-linux-android

  build-test-clippy-linux:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - build: linux
            os: ubuntu-latest
            target: x86_64-unknown-linux-musl

    steps:
    - uses: actions/checkout@v3
    - uses: Swatinem/rust-cache@v2
      with:
        shared-key: "persist-cross-job"
        workspaces: ./
    - run: rustup component add clippy

    - name: Run tests no features
      run: cargo test --all --no-default-features
    - name: Run clippy no features
      run: cargo clippy --all --no-default-features -- -D warnings

    - name: Run tests default features
      run: cargo test --all
    - name: Run clippy default features
      run: cargo clippy --all -- -D warnings

    - name: Run tests cmd
      run: cargo test --all --features=cmd
    - name: Run clippy cmd
      run: cargo clippy --all --features=cmd -- -D warnings

    - name: Run tests simulated output
      run: cargo test --features=simulated_output -- sim_tests
    - name: Run tests simulated output on_idle
      run: cargo test --features=simulated_output -- must_be_single_threaded --ignored --test-threads=1
    - name: Run clippy simulated output
      run: cargo clippy --all --features=simulated_output,cmd -- -D warnings

    - name: Run clippy for parser with lsp feature
      run: cargo clippy -p kanata-parser --features=lsp -- -D warnings

  build-test-clippy-windows:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - build: windows
            os: windows-latest
            target: x86_64-pc-windows-msvc

    steps:
    - uses: actions/checkout@v3
    - uses: Swatinem/rust-cache@v2
      with:
        shared-key: "persist-cross-job"
        workspaces: ./
    - run: rustup component add clippy

    - name: Run tests no features
      run: cargo test --all --no-default-features
    - name: Run clippy no features
      run: cargo clippy --all --no-default-features -- -D warnings

    - name: Run tests default features
      run: cargo test --all
    - name: Run clippy default features
      run: cargo clippy --all -- -D warnings

    - name: Run tests winIOv2
      run: cargo test --all --features=cmd,win_llhook_read_scancodes,win_sendinput_send_scancodes
    - name: Run clippy all winIOv2
      run: cargo clippy --all --features=cmd,win_llhook_read_scancodes,win_sendinput_send_scancodes -- -D warnings

    - name: Run tests all features
      run: cargo test  -p kanata -p kanata-parser -p kanata-keyberon -p kanata-tcp-protocol --features=cmd,interception_driver,win_sendinput_send_scancodes
    - name: Run clippy all features
      run: cargo clippy --all --features=cmd,interception_driver,win_sendinput_send_scancodes -- -D warnings

    - name: Run tests simulated output
      run: cargo test --features=simulated_output -- sim_tests
    - name: Run tests simulated output on_idle
      run: cargo test --features=simulated_output -- sim_tests::vkey_sim_tests::on_idle --ignored
    - name: Run clippy simulated output
      run: cargo clippy --all --features=simulated_output,cmd -- -D warnings

    - name: Run tests gui
      run: cargo test --all --features=gui
    - name: Run clippy gui
      run: cargo clippy --all --features=gui -- -D warnings

    - name: Check gui+cmd+interception
      run: cargo check --features gui,cmd,interception_driver

  build-test-clippy-macos:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - build: macos
            os: macos-latest
            target: x86_64-apple-darwin

    steps:
    - uses: actions/checkout@v3
    - uses: Swatinem/rust-cache@v2
      with:
        shared-key: "persist-cross-job"
        workspaces: ./
    - run: rustup component add clippy

    - name: Run tests default features
      run: cargo test --all
    - name: Run clippy default features
      run: cargo clippy --all -- -D warnings

    - name: Run tests cmd
      run: cargo test --all --features=cmd
    - name: Run clippy all features
      run: cargo clippy --all --features=cmd -- -D warnings


================================================
FILE: .github/workflows/windows-build.yml
================================================
name: windows-build

on:
  workflow_dispatch:
    branches: [ "main" ]
  workflow_call:

env:
  CARGO_TERM_COLOR: always

jobs:
  build-windows-x64:
    runs-on: windows-latest

    steps:
      - uses: actions/checkout@v3
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: "persist-cross-job-win-x64"
      - name: Build x64
        shell: powershell
        run: |
          md artifacts
          cargo build --release --features win_manifest,win_sendinput_send_scancodes,win_llhook_read_scancodes --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_tty_winIOv2_x64.exe
          cargo build --release --features win_manifest,win_sendinput_send_scancodes,win_llhook_read_scancodes,cmd --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_tty_winIOv2_cmd_allowed_x64.exe
          cargo build --release --features win_manifest,interception_driver --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_tty_wintercept_x64.exe
          cargo build --release --features win_manifest,cmd,interception_driver --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_tty_wintercept_cmd_allowed_x64.exe
          cargo build --release --features gui,win_manifest,win_sendinput_send_scancodes,win_llhook_read_scancodes --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_gui_winIOv2_x64.exe
          cargo build --release --features gui,win_manifest,win_sendinput_send_scancodes,win_llhook_read_scancodes,cmd --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_gui_winIOv2_cmd_allowed_x64.exe
          cargo build --release --features gui,win_manifest,interception_driver --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_gui_wintercept_x64.exe
          cargo build --release --features gui,win_manifest,cmd,interception_driver --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_gui_wintercept_cmd_allowed_x64.exe
          cargo build --release --features passthru_ahk --package=simulated_passthru --target x86_64-pc-windows-msvc
          mv target/x86_64-pc-windows-msvc/release/kanata_passthru.dll artifacts/kanata_passthru_x64.dll
      - uses: actions/upload-artifact@v4
        with:
          name: windows-binaries-x64
          path: |
            artifacts/kanata_windows_tty_winIOv2_x64.exe
            artifacts/kanata_windows_tty_winIOv2_cmd_allowed_x64.exe
            artifacts/kanata_windows_tty_wintercept_x64.exe
            artifacts/kanata_windows_tty_wintercept_cmd_allowed_x64.exe
            artifacts/kanata_windows_gui_winIOv2_x64.exe
            artifacts/kanata_windows_gui_winIOv2_cmd_allowed_x64.exe
            artifacts/kanata_windows_gui_wintercept_x64.exe
            artifacts/kanata_windows_gui_wintercept_cmd_allowed_x64.exe
            artifacts/kanata_passthru_x64.dll

  build-windows-arm64:
    runs-on: windows-11-arm

    steps:
      - uses: actions/checkout@v3
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: "persist-cross-job-win-arm64"
      - name: Build arm64
        shell: powershell
        run: |
          md artifacts
          cargo build --release --features win_manifest,win_sendinput_send_scancodes,win_llhook_read_scancodes --target aarch64-pc-windows-msvc
          mv target/aarch64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_tty_winIOv2_arm64.exe
          cargo build --release --features win_manifest,win_sendinput_send_scancodes,win_llhook_read_scancodes,cmd --target aarch64-pc-windows-msvc
          mv target/aarch64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_tty_winIOv2_cmd_allowed_arm64.exe
          cargo build --release --features gui,win_manifest,win_sendinput_send_scancodes,win_llhook_read_scancodes --target aarch64-pc-windows-msvc
          mv target/aarch64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_gui_winIOv2_arm64.exe
          cargo build --release --features gui,win_manifest,win_sendinput_send_scancodes,win_llhook_read_scancodes,cmd --target aarch64-pc-windows-msvc
          mv target/aarch64-pc-windows-msvc/release/kanata.exe artifacts/kanata_windows_gui_winIOv2_cmd_allowed_arm64.exe
      - uses: actions/upload-artifact@v4
        with:
          name: windows-binaries-arm64
          path: |
            artifacts/kanata_windows_tty_winIOv2_arm64.exe
            artifacts/kanata_windows_tty_winIOv2_cmd_allowed_arm64.exe
            artifacts/kanata_windows_gui_winIOv2_arm64.exe
            artifacts/kanata_windows_gui_winIOv2_cmd_allowed_arm64.exe


================================================
FILE: .gitignore
================================================
**/target
.vscode/
CLAUDE.md
.DS_Store
PLAN.md

# Manual testing files
test_*.kbd
manual_test/
*.test.kbd


================================================
FILE: Cargo.toml
================================================
[workspace]
members = [
	"./",
	"parser",
	"keyberon",
	"example_tcp_client",
	"tcp_protocol",
	"windows_key_tester",
	"simulated_input",
	"simulated_passthru",
	"wasm",
]
exclude = [
	"interception",
	"key-sort-add",
]
resolver = "2"

[package]
name = "kanata"
version = "1.11.0"
authors = ["jtroo <j.andreitabs@gmail.com>"]
description = "Multi-layer keyboard customization"
keywords = ["keyboard", "layout", "remapping"]
categories = ["command-line-utilities"]
homepage = "https://github.com/jtroo/kanata"
repository = "https://github.com/jtroo/kanata"
readme = "README.md"
license = "LGPL-3.0-only"
edition = "2024"
default-run = "kanata"

[lib]
name = "kanata_state_machine"
path = "src/lib.rs"
crate-type = ["rlib", "staticlib"]

[[bin]]
name = "kanata"
path = "src/main.rs"

[dependencies]
anyhow = "1"
clap = { version = "4", features = [ "std", "derive", "help", "suggestions" ], default-features = false }
dirs = "5.0.1"
indoc = { version = "2.0.4", optional = true }
log = { version = "0.4.8", default-features = false }
miette = { version = "5.7.0", features = ["fancy"] }
once_cell = "1"
parking_lot = "0.12"
radix_trie = "0.2"
rustc-hash = "1.1.0"
simplelog = "0.12.0"
serde_json = { version = "1", features = ["std"], default-features = false, optional = true }
time = "0.3.47"
web-time = "1.1.0"

kanata-keyberon = { path = "keyberon", version = "0.1110.0" }
kanata-parser =   { path = "parser", version = "0.1110.0" }
kanata-tcp-protocol = { path = "tcp_protocol", version = "0.1110.0" }

[target.'cfg(not(any(target_arch = "wasm32", target_os = "android")))'.dependencies]
arboard = "3.4"

[target.'cfg(target_os = "macos")'.dependencies]
karabiner-driverkit = "0.2.1"
objc = "0.2.7"
core-graphics = "0.24.0"
open = { version = "5", optional = true }
libc = "0.2"
os_pipe = "1.2.1"

[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
evdev = "0.13.0"
inotify = { version = "0.10.0", default-features = false }
mio = { version = "0.8.11", features = ["os-poll", "os-ext"] }
nix = { version = "0.26.1", features = ["ioctl"] }
open = { version = "5", optional = true }
signal-hook = "0.3.14"
sd-notify = "0.4.1"

[target.'cfg(target_os = "windows")'.dependencies]
encode_unicode = "0.3.6"
winapi = { version = "0.3.9", features = [
    "wincon",
    "timeapi",
    "mmsystem",
    "winuser",
    "windef",
    "minwindef",
] }
windows-sys = { version = "0.52.0", features = [
    "Win32_Devices_DeviceAndDriverInstallation",
    "Win32_Devices_Usb",
    "Win32_Foundation",
    "Win32_Graphics_Gdi",
    "Win32_Security",
    "Win32_System_Diagnostics_Debug",
    "Win32_System_Registry",
    "Win32_System_Threading",
    "Win32_UI_Controls",
    "Win32_UI_Shell",
    "Win32_UI_HiDpi",
    "Win32_UI_WindowsAndMessaging",
    "Win32_System_SystemInformation",
    "Wdk",
    "Wdk_System",
    "Wdk_System_SystemServices",
], optional=true }
native-windows-gui = { version = "1.0.13", default-features = false}
regex = { version = "1.10.4", optional = true }
kanata-interception = { version = "0.3.0", optional = true }
muldiv = { version = "1.0.1", optional = true }
strip-ansi-escapes = { version = "0.2.0", optional = true }
open = { version = "5", features = ["shellexecute-on-windows"], optional = true}
# shellexecute fix allows opening files already opened for writing, needs _detached mode

[build-dependencies]
embed-resource = { version = "2.4.2", optional = true }
indoc = { version = "2.0.4", optional = true }
regex = { version = "1.10.4", optional = true }

[features]
default = ["tcp_server","win_sendinput_send_scancodes", "zippychord"]
perf_logging = []
tcp_server = ["dep:serde_json", "kanata-keyberon/tap_hold_tracker"]
win_sendinput_send_scancodes = ["kanata-parser/win_sendinput_send_scancodes"]
win_llhook_read_scancodes = ["kanata-parser/win_llhook_read_scancodes"]
winiov2 = ["win_llhook_read_scancodes","win_sendinput_send_scancodes"]
win_manifest = ["dep:embed-resource", "dep:indoc", "dep:regex"]
# delete cargo-clippy when the objc crate is replaced
cargo-clippy = []
cmd = ["kanata-parser/cmd"]
interception_driver = ["dep:kanata-interception", "kanata-parser/interception_driver"]
simulated_output = ["dep:indoc"]
simulated_input = ["dep:indoc"]
passthru_ahk = ["simulated_input","simulated_output"]
gui = ["win_manifest","kanata-parser/gui",
  "win_sendinput_send_scancodes","win_llhook_read_scancodes",
  "dep:muldiv","dep:strip-ansi-escapes","dep:open",
  "dep:windows-sys",
  "winapi/processthreadsapi",
  "native-windows-gui/tray-notification","native-windows-gui/message-window","native-windows-gui/menu","native-windows-gui/cursor","native-windows-gui/high-dpi","native-windows-gui/embed-resource","native-windows-gui/image-decoder","native-windows-gui/notice","native-windows-gui/animation-timer",
]
zippychord = ["kanata-parser/zippychord"]

[profile.release]
opt-level = "z"
lto = "fat"
panic = "abort"
codegen-units = 1


================================================
FILE: EnableUIAccess/EnableUIAccess_launch.ahk
================================================
#requires AutoHotkey v2.0
#SingleInstance Off ; Needed for elevation with *runas.
/* v2 based on EnableUIAccess.ahk v1.01 by Lexikos USE AT YOUR OWN RISK
  Enables the uiAccess flag in an application's embedded manifest and signs the file with a self-signed digital certificate. If the file is in a trusted location (A_ProgramFiles or A_WinDir), this allows the application to bypass UIPI (User Interface Privilege Isolation, a part of User Account Control in Vista/7). It also enables the journal playback hook (SendPlay).
  Command line params (mutually exclusive):
    SkipWarning     - don't display the initial warning
    "<in>" "<out>"  - attempt to run silently using the given file(s)
  This script and the provided Lib files may be used, modified, copied, etc. without restriction.
*/
#include <EnableUIAccess>

in_file  := (A_Args.Has(1))?A_Args[1]:'' ; Command line args
out_file := (A_Args.Has(2))?A_Args[2]:''

if (in_file = ""){
  msgResult := MsgBox("Enable the selected EXE to bypass UAC-UIPI security restrictions imposed by modifying 'UIAccess' attribute in the file's embedded manifest and signing the file using a self-signed digital certificate, which is then installed in the local machine's Trusted Root Certification Authorities store.`n`nThe resulting EXE is unusable on a system without this certificate installed!`n`nContinue at your own risk", "", 49)
  if (msgResult = "Cancel"){
    ExitApp()
  }
}

if !A_IsAdmin {
  if (in_file = "") {
    in_file := "SkipWarning"
  }
  cmd := "`"" . A_ScriptFullPath . "`""
  if !A_IsCompiled {   ; Use A_AhkPath in case the "runas" verb isn't registered for ahk files.
    cmd := "`"" . A_AhkPath . "`" " . cmd
  }
  Try Run("*RunAs " cmd " `"" in_file "`" `"" out_file "`"", , "", )
  ExitApp()
}
global user_specified_files := false
if (in_file = "" || in_file = "SkipWarning") { ; Find AutoHotkey installation.
  InstallDir := RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\AutoHotkey", "InstallDir")
  if A_LastError && A_PtrSize=8 {
    InstallDir := RegRead("HKLM\SOFTWARE\Wow6432Node\AutoHotkey", "InstallDir")
  }
  ; Let user confirm or select file(s).
  in_file := FileSelect(1, InstallDir "\AutoHotkey.exe", "Select Source File", "Executable Files (*.exe)")
  if A_LastError {
    ExitApp()
  }
  out_file := FileSelect("S16", in_file, "Select Destination File", "Executable Files (*.exe)")
  if A_LastError {
    ExitApp()
  }
  user_specified_files := true
}

Loop in_file { ; Convert short paths to long paths
  in_file := A_LoopFileFullPath
}
if (out_file = "") {   ; i.e. only one file was given via command line
  out_file := in_file
} else {
  Loop out_file {
    out_file := A_LoopFileFullPath
  }
}
if Crypt.IsSigned(in_file) {
  msgResult := MsgBox("Input file is already signed.  The script will now exit" in_file,"", 48)
  ExitApp()
}

if user_specified_files && !IsTrustedLocation(out_file) {
  msgResult := MsgBox("Target path is not a trusted location (Program Files or Windows\System32), so 'uiAccess'  will have no effect until the file is moved there","", 49)
  if (msgResult = "Cancel") {
    ExitApp()
  }
}

if (in_file = out_file) { ; The following should typically work even if the file is in use
  bak_file := in_file "~" A_Now ".bak"
  FileMove(in_file, bak_file, 1)
  if A_LastError {
    Fail("Failed to rename selected file.")
  }
  in_file := bak_file
}
Try {
  FileCopy(in_file, out_file, 1)
} Catch as Err {
  throw OSError(Err)
}
if A_LastError {
  Fail("Failed to copy file to destination.")
}

if !EnableUIAccess(out_file) { ; Set the uiAccess attribute in the file's manifest
  Fail("Failed to set uiAccess attribute in manifest")
}


if (user_specified_files && in_file != out_file) { ; in interactive mode, if not overwriting the original file, offer to create an additional context menu item for AHK files
  uiAccessVerb := RegRead("HKCR\AutoHotkeyScript\Shell\uiAccess\Command")
  if A_LastError {
    msgResult := MsgBox("Register `"Run Script with UI Access`" context menu item?", "", 3)
    if (msgResult = "Yes") {
      RegWrite("Run with UI Access", "REG_SZ", "HKCR\AutoHotkeyScript\Shell\uiAccess")
      RegWrite("`"" out_file "`" `"`%1`" `%*", "REG_SZ", "HKCR\AutoHotkeyScript\Shell\uiAccess\Command")
    }
    if (msgResult = "Cancel")
      ExitApp()
  }
}

IsTrustedLocation(path) { ; IsTrustedLocation  →true if path is a valid location for uiAccess="true"
  ; http://msdn.microsoft.com/en-us/library/bb756929 "\Program Files\ and \windows\system32\ are currently 2 allowable protected locations." However, \Program Files (x86)\ also appears to be allowed
  if InStr(path, A_ProgramFiles "\") = 1 {
    return true
  }
  if InStr(path, A_WinDir "\System32\") = 1 {
    return true
  }
  other := EnvGet(A_PtrSize=8 ? "ProgramFiles(x86)" : "ProgramW6432") ; On 64-bit systems, if this script is 32-bit, A_ProgramFiles is %ProgramFiles(x86)%, otherwise it is %ProgramW6432%. So check the opposite "Program Files" folder:
  if (other != "" && InStr(path, other "\") = 1) {
    return true
  }
  return   false
}

Fail(msg) {
  ; if (%True% != "Silent") { ;???
    MsgBox(msg "`nA_LastError: " A_LastError, "", 16)
  ; }
  ExitApp()
}

Warn(msg) {
  msg .= " (Err " A_LastError ")`n"
  OutputDebug(msg)
  FileAppend(msg, "*")
}


================================================
FILE: EnableUIAccess/Lib/EnableUIAccess.ahk
================================================
#requires AutoHotkey v2.0

EnableUIAccess(ExePath) {
  static CertName := "AutoHotkey"
  hStore := DllCall("Crypt32\CertOpenStore", "ptr",10 ; STORE_PROV_SYSTEM_W
    , "uint",0, "ptr",0, "uint",0x20000 ; SYSTEM_STORE_LOCAL_MACHINE
    , "wstr","Root", "ptr")
  if !hStore {
    throw OSError()
  }
  store := CertStore(hStore)
  cert := CertContext() ; Find or create certificate for signing.
  while (cert.ptr := DllCall("Crypt32\CertFindCertificateInStore", "ptr",hStore
      , "uint",0x10001 ; X509_ASN_ENCODING|PKCS_7_ASN_ENCODING
      , "uint",0, "uint",0x80007 ; FIND_SUBJECT_STR
      , "wstr", CertName, "ptr",cert.ptr, "ptr"))
    && !(DllCall("Crypt32\CryptAcquireCertificatePrivateKey"
      , "ptr",cert, "uint",5 ; CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG
      , "ptr",0, "ptr*", 0, "uint*", &keySpec:=0, "ptr",0)
      && (keySpec & 2)) { ; AT_SIGNATURE ; Keep looking for a certificate with a private key.
  }
  if !cert.ptr {
    cert := EnableUIAccess_CreateCert(CertName, hStore)
  }
  EnableUIAccess_SetManifest(ExePath)             	; Set uiAccess attribute in manifest
  EnableUIAccess_SignFile(ExePath, cert, CertName)	; Sign the file (otherwise uiAccess attribute is ignored)
  return true
}

EnableUIAccess_SetManifest(ExePath) {
  xml := ComObject("Msxml2.DOMDocument")
  xml.async := false
  xml.setProperty("SelectionLanguage", "XPath")
  xml.setProperty("SelectionNamespaces"
    , "xmlns:v1='urn:schemas-microsoft-com:asm.v1' "
    . "xmlns:v3='urn:schemas-microsoft-com:asm.v3'")
  try {
    if !xml.loadXML(EnableUIAccess_ReadManifest(ExePath)) {
      throw Error("Invalid manifest")
    }
  } catch as e {
    throw Error("Error loading manifest from " ExePath,, e.Message "`n  @ " e.File ":" e.Line)
  }


  node := xml.selectSingleNode("/v1:assembly/v3:trustInfo/v3:security"
    .                          "/v3:requestedPrivileges/v3:requestedExecutionLevel")
  if !node ; Not AutoHotkey?
    throw Error("Manifest is missing required elements")

  node.setAttribute("uiAccess", "true")
  xml := RTrim(xml.xml, "`r`n")

  data := Buffer(StrPut(xml, "utf-8") - 1)
  StrPut(xml, data, "utf-8")

  if !(hupd := DllCall("BeginUpdateResource", "str",ExePath, "int",false))
    throw OSError()
  r := DllCall("UpdateResource", "ptr",hupd, "ptr",24, "ptr",1
          , "ushort", 1033, "ptr",data, "uint",data.size)

  ; Retry loop to work around file locks (especially by antivirus)
  for delay in [0, 100, 500, 1000, 3500] {
    Sleep delay
    if DllCall("EndUpdateResource", "ptr",hupd, "int",!r) || !r
      return
    if !(A_LastError = 5 || A_LastError = 110) ; ERROR_ACCESS_DENIED || ERROR_OPEN_FAILED
      break
  }
  throw OSError(A_LastError, "EndUpdateResource")
}

EnableUIAccess_ReadManifest(ExePath) {
  if !(hmod := DllCall("LoadLibraryEx", "str",ExePath, "ptr",0, "uint",2, "ptr"))
    throw OSError()
  try {
    if !(hres := DllCall("FindResource", "ptr",hmod, "ptr",1, "ptr",24, "ptr")) {
      throw OSError()
    }
    size := DllCall("SizeofResource", "ptr",hmod, "ptr",hres, "uint")
    if !(hglb := DllCall("LoadResource", "ptr",hmod, "ptr",hres, "ptr")) {
      throw OSError()
    }
    if !(pres := DllCall("LockResource", "ptr",hglb, "ptr")) {
      throw OSError()
    }
    return StrGet(pres, size, "utf-8")
  }
  finally {
    DllCall("FreeLibrary", "ptr",hmod)
  }
}

EnableUIAccess_CreateCert(Name, hStore) {
  prov := CryptContext() ; Here Name is used as the key container name.
  if !DllCall("Advapi32\CryptAcquireContext", "ptr*", prov
    , "str",Name, "ptr",0, "uint",1, "uint",0) { ; PROV_RSA_FULL=1, open existing=0
    if !DllCall("Advapi32\CryptAcquireContext", "ptr*", prov
      , "str",Name, "ptr",0, "uint",1, "uint",8) { ; PROV_RSA_FULL=1, CRYPT_NEWKEYSET=8
      throw OSError()
    }
    if !DllCall("Advapi32\CryptGenKey", "ptr",prov
        , "uint",2, "uint",0x4000001, "ptr*", CryptKey()) { ; AT_SIGNATURE=2, EXPORTABLE=..01
      throw OSError()
    }
  }

  ; Here Name is used as the certificate subject and name.
  Loop 2 {
    if A_Index = 1 {
      pbName := cbName := 0
    } else {
      bName := Buffer(cbName), pbName := bName.ptr
    }
    if !DllCall("Crypt32\CertStrToName", "uint",1, "str","CN=" Name
      , "uint",3, "ptr",0, "ptr",pbName, "uint*", &cbName, "ptr",0) ; X509_ASN_ENCODING=1, CERT_X500_NAME_STR=3
      throw OSError()
  }
  cnb := Buffer(2*A_PtrSize), NumPut("ptr",cbName, "ptr",pbName, cnb)

  ; Set expiry to 9999-01-01 12pm +0.
  NumPut("short", 9999, "sort", 1, "short", 5, "short", 1, "short", 12, endTime := Buffer(16, 0))

  StrPut("2.5.29.4", szOID_KEY_USAGE_RESTRICTION := Buffer(9),, "cp0")
  StrPut("2.5.29.37", szOID_ENHANCED_KEY_USAGE := Buffer(10),, "cp0")
  StrPut("1.3.6.1.5.5.7.3.3", szOID_PKIX_KP_CODE_SIGNING := Buffer(18),, "cp0")

  ; CERT_KEY_USAGE_RESTRICTION_INFO key_usage;
  key_usage := Buffer(6*A_PtrSize, 0)
  NumPut('ptr', 0, 'ptr', 0, 'ptr', 1, 'ptr', key_usage.ptr + 5*A_PtrSize, 'ptr', 0
    , 'uchar', (CERT_DATA_ENCIPHERMENT_KEY_USAGE := 0x10)
         | (CERT_DIGITAL_SIGNATURE_KEY_USAGE := 0x80), key_usage)

  ; CERT_ENHKEY_USAGE enh_usage;
  enh_usage := Buffer(3*A_PtrSize)
  NumPut("ptr",1, "ptr",enh_usage.ptr + 2*A_PtrSize, "ptr",szOID_PKIX_KP_CODE_SIGNING.ptr, enh_usage)

  key_usage_data := EncodeObject(szOID_KEY_USAGE_RESTRICTION, key_usage)
  enh_usage_data := EncodeObject(szOID_ENHANCED_KEY_USAGE, enh_usage)

  EncodeObject(structType, structInfo) {
    encoder := DllCall.Bind("Crypt32\CryptEncodeObject", "uint",X509_ASN_ENCODING := 1
      , "ptr",structType, "ptr",structInfo)
    if !encoder("ptr",0, "uint*", &enc_size := 0)
      throw OSError()
    enc_data := Buffer(enc_size)
    if !encoder("ptr",enc_data, "uint*", &enc_size)
      throw OSError()
    enc_data.Size := enc_size
    return enc_data
  }

  ; CERT_EXTENSION extension[2]; CERT_EXTENSIONS extensions;
  NumPut("ptr",szOID_KEY_USAGE_RESTRICTION.ptr, "ptr",true, "ptr",key_usage_data.size, "ptr",key_usage_data.ptr
    ,    "ptr",szOID_ENHANCED_KEY_USAGE.ptr   , "ptr",true, "ptr",enh_usage_data.size, "ptr",enh_usage_data.ptr
    , extension := Buffer(8*A_PtrSize))
  NumPut("ptr",2, "ptr",extension.ptr, extensions := Buffer(2*A_PtrSize))

  if !hCert := DllCall("Crypt32\CertCreateSelfSignCertificate"
    , "ptr",prov, "ptr",cnb, "uint",0, "ptr",0
    , "ptr",0, "ptr",0, "ptr",endTime, "ptr",extensions, "ptr") {
    throw OSError()
  }
  cert := CertContext(hCert)

  if !DllCall("Crypt32\CertAddCertificateContextToStore", "ptr",hStore
    , "ptr",hCert, "uint",1, "ptr",0) { ; STORE_ADD_NEW=1
    throw OSError()
  }

  return cert
}

EnableUIAccess_DeleteCertAndKey(Name) {
  ; This first call "acquires" the key container but also deletes it.
  DllCall("Advapi32\CryptAcquireContext", "ptr*", 0, "str",Name
    , "ptr",0, "uint",1, "uint",16) ; PROV_RSA_FULL=1, CRYPT_DELETEKEYSET=16
  if !hStore := DllCall("Crypt32\CertOpenStore", "ptr",10 ; STORE_PROV_SYSTEM_W
    , "uint",0, "ptr",0, "uint",0x20000 ; SYSTEM_STORE_LOCAL_MACHINE
    , "wstr", "Root", "ptr")
    throw OSError()
  store := CertStore(hStore)
  deleted := 0
  ; Multiple certificates might be created over time as keys become inaccessible
  while p := DllCall("Crypt32\CertFindCertificateInStore", "ptr",hStore
    , "uint",0x10001 ; X509_ASN_ENCODING|PKCS_7_ASN_ENCODING
    , "uint",0, "uint",0x80007 ; FIND_SUBJECT_STR
    , "wstr", Name, "ptr",0, "ptr") {
    if !DllCall("Crypt32\CertDeleteCertificateFromStore", "ptr",p) {
      throw OSError()
    }
    deleted++
  }
  return deleted
}

class Crypt {
  static IsSigned(FilePath) {
    return DllCall("Crypt32\CryptQueryObject"
      ,"uint" 	, CERT_QUERY_OBJECT_FILE := 1
      ,"wstr" 	, FilePath
      ,"uint" 	, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED := 1<<10
      ,"uint" 	, CERT_QUERY_FORMAT_FLAG_BINARY := 2
      ,"uint" 	, 0
      ,"uint*"	, &dwEncoding:=0
      ,"uint*"	, &dwContentType:=0
      ,"uint*"	, &dwFormatType:=0
      ,"ptr"  	, 0
      ,"ptr"  	, 0
      ,"ptr"  	, 0)
  }
}
class CryptPtrBase {
  __new(p:=0) => this.ptr := p
  __delete() => this.ptr && this.Dispose()
}
class CryptContext extends CryptPtrBase {
  Dispose() => DllCall("Advapi32\CryptReleaseContext", "ptr",this, "uint",0)
}
class CertContext extends CryptPtrBase {
  Dispose() => DllCall("Crypt32\CertFreeCertificateContext", "ptr",this)
}
class CertStore extends CryptPtrBase {
  Dispose() => DllCall("Crypt32\CertCloseStore", "ptr",this, "uint",0)
}
class CryptKey extends CryptPtrBase {
  Dispose() => DllCall("Advapi32\CryptDestroyKey", "ptr",this)
}

EnableUIAccess_SignFile(ExePath, CertCtx, Name) {
  file_info := struct( ; SIGNER_FILE_INFO
    "ptr",A_PtrSize*3, "ptr",StrPtr(ExePath))
  dwIndex := Buffer(4, 0) ; DWORD
  subject_info := struct( ; SIGNER_SUBJECT_INFO
    "ptr",A_PtrSize*4, "ptr",dwIndex.ptr, "ptr",SIGNER_SUBJECT_FILE:=1,
    "ptr",file_info.ptr)
  cert_store_info := struct( ; SIGNER_CERT_STORE_INFO
    "ptr",A_PtrSize*4, "ptr",CertCtx.ptr, "ptr",SIGNER_CERT_POLICY_CHAIN:=2)
  cert_info := struct( ; SIGNER_CERT
    "uint",8+A_PtrSize*2, "uint",SIGNER_CERT_STORE:=2,
    "ptr",cert_store_info.ptr)
  authcode_attr := struct( ; SIGNER_ATTR_AUTHCODE
    "uint",8+A_PtrSize*3, "int",false, "ptr",true, "ptr",StrPtr(Name))
  sig_info := struct( ; SIGNER_SIGNATURE_INFO
    "uint",8+A_PtrSize*4, "uint",CALG_SHA1:=0x8004,
    "ptr",SIGNER_AUTHCODE_ATTR:=1, "ptr",authcode_attr.ptr)

  hr := DllCall("MSSign32\SignerSign"
    , "ptr",subject_info, "ptr",cert_info, "ptr",sig_info
    , "ptr",0, "ptr",0, "ptr",0, "ptr",0, "hresult") ; pProviderInfo pwszHttpTimeStamp psRequest pSipData

  struct(args*) => (
    args.Push(b := Buffer(args[2], 0)),
    NumPut(args*),
    b
  )
}

EnableUIAccess_Verify(ExePath) { ; Verifies a signed executable file.  Returns 0 on success, or a standard OS error number.
  wfi := Buffer(4*A_PtrSize) ; WINTRUST_FILE_INFO
  NumPut('ptr', wfi.size, 'ptr', StrPtr(ExePath), 'ptr', 0, 'ptr', 0, wfi)
  NumPut('int64', 0x11d0cd4400aac56b, 'int64', 0xee95c24fc000c28c, actionID := Buffer(16)) ; WINTRUST_ACTION_GENERIC_VERIFY_V2

  wtd := Buffer(9*A_PtrSize+16) ; WINTRUST_DATA
  NumPut(
    'ptr', wtd.Size, 'ptr', 0, 'ptr', 0, 'int', WTD_UI_NONE:=2, 'int', WTD_REVOKE_NONE:=0,
    'ptr', WTD_CHOICE_FILE:=1, 'ptr', wfi.ptr, 'ptr', WTD_STATEACTION_VERIFY:=1,
    'ptr', 0, 'ptr', 0, 'int', 0, 'int', 0, 'ptr', 0, wtd
  )
  return DllCall('wintrust\WinVerifyTrust', 'ptr', 0, 'ptr', actionID, 'ptr', wtd, 'int')
}


================================================
FILE: EnableUIAccess/README.md
================================================
# EnableUIAccess

See [the guide documentation for context](https://github.com/jtroo/kanata/blob/main/docs/config.adoc#windows-only-work-elevated).


================================================
FILE: LICENSE
================================================
                   GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

  0. Additional Definitions.

  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

  The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

  The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

  1. Exception to Section 3 of the GNU GPL.

  You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

  2. Conveying Modified Versions.

  If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

   a) under this License, provided that you make a good faith effort to
   ensure that, in the event an Application does not supply the
   function or data, the facility still operates, and performs
   whatever part of its purpose remains meaningful, or

   b) under the GNU GPL, with none of the additional permissions of
   this License applicable to that copy.

  3. Object Code Incorporating Material from Library Header Files.

  The object code form of an Application may incorporate material from
a header file that is part of the Library.  You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

   a) Give prominent notice with each copy of the object code that the
   Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the object code with a copy of the GNU GPL and this license
   document.

  4. Combined Works.

  You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

   a) Give prominent notice with each copy of the Combined Work that
   the Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the Combined Work with a copy of the GNU GPL and this license
   document.

   c) For a Combined Work that displays copyright notices during
   execution, include the copyright notice for the Library among
   these notices, as well as a reference directing the user to the
   copies of the GNU GPL and this license document.

   d) Do one of the following:

       0) Convey the Minimal Corresponding Source under the terms of this
       License, and the Corresponding Application Code in a form
       suitable for, and under terms that permit, the user to
       recombine or relink the Application with a modified version of
       the Linked Version to produce a modified Combined Work, in the
       manner specified by section 6 of the GNU GPL for conveying
       Corresponding Source.

       1) Use a suitable shared library mechanism for linking with the
       Library.  A suitable mechanism is one that (a) uses at run time
       a copy of the Library already present on the user's computer
       system, and (b) will operate properly with a modified version
       of the Library that is interface-compatible with the Linked
       Version.

   e) Provide Installation Information, but only if you would otherwise
   be required to provide such information under section 6 of the
   GNU GPL, and only to the extent that such information is
   necessary to install and execute a modified version of the
   Combined Work produced by recombining or relinking the
   Application with a modified version of the Linked Version. (If
   you use option 4d0, the Installation Information must accompany
   the Minimal Corresponding Source and Corresponding Application
   Code. If you use option 4d1, you must provide the Installation
   Information in the manner specified by section 6 of the GNU GPL
   for conveying Corresponding Source.)

  5. Combined Libraries.

  You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

   a) Accompany the combined library with a copy of the same work based
   on the Library, uncombined with any other library facilities,
   conveyed under the terms of this License.

   b) Give prominent notice with the combined library that part of it
   is a work based on the Library, and explaining where to find the
   accompanying uncombined form of the same work.

  6. Revised Versions of the GNU Lesser General Public License.

  The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

  Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

  If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

================================================
FILE: README.md
================================================
<h1 align="center">Kanata</h1>

<h3 align="center">
  <img
    alt="Image of a keycap with the letter K on it in pink tones"
    title="Kanata"
    height="160"
    src="assets/kanata-icon.svg"
  />
</h3>

<div align="center">
  Improve your keyboard comfort
</div>

## What does this do?

This is a cross-platform software keyboard remapper for Linux, macOS and Windows.
A short summary of the features:

- multiple layers of key functionality
- advanced key behaviour customization (e.g. tap-hold, macros, unicode)

To see all of the features, see the [configuration guide](./docs/config.adoc).

You can find pre-built binaries in the [releases page](https://github.com/jtroo/kanata/releases)
or read on for build instructions.

You can see a [list of known issues here](./docs/platform-known-issues.adoc).

### Demo

#### Demo video

[Showcase of multi-layer functionality (30s, 1.7 MB)](https://user-images.githubusercontent.com/6634136/183001314-f64a7e26-4129-4f20-bf26-7165a6e02c38.mp4).

#### Online simulator

You can check out the [online simulator](https://jtroo.github.io)
to test configuration validity and test input simulation.

## Why is this useful?

Imagine if, instead of pressing Shift to type uppercase letters, we had giant
keyboards with separate keys for lowercase and uppercase letters. I hope we can
all agree: that would be a terrible user experience!

A way to think of how Shift keys work is that they switch your input to another
layer of functionality where you now type uppercase letters and symbols
instead of lowercase letters and numbers.

What kanata allows you to do is take this alternate layer concept that Shift
keys have and apply it to any key. You can then customize what those layers do
to suit your exact needs and workflows.

## Usage

Running kanata currently does not start it in a background process.
You will need to keep the window that starts kanata running to keep kanata active.
Some tips for running kanata in the background:

- Windows: https://github.com/jtroo/kanata/discussions/193
- Linux: https://github.com/jtroo/kanata/discussions/130#discussioncomment-10227272
- Run from tray icon: [kanata-tray](https://github.com/rszyma/kanata-tray)

### Pre-built executables

See the
[releases page](https://github.com/jtroo/kanata/releases)
for executables and instructions.

### Build it yourself

This project uses the latest Rust stable toolchain. If you installed the
Rust toolchain using `rustup`, e.g. by using the instructions from the
[official website](https://www.rust-lang.org/learn/get-started),
you can get the latest stable toolchain with `rustup update stable`.

<details>
<summary>Instructions</summary>

Using `cargo install`:

    cargo install kanata

    # On Linux and macOS, this may not work without `sudo`, see below
    kanata --cfg <your_configuration_file>

Build and run yourself in Linux:

    git clone https://github.com/jtroo/kanata && cd kanata
    cargo build   # --release optional, not really perf sensitive

    # sudo is used because kanata opens /dev/ files
    #
    # See below if you want to avoid needing sudo:
    # https://github.com/jtroo/kanata/wiki/Avoid-using-sudo-on-Linux
    sudo target/debug/kanata --cfg <your_configuration_file>

Build and run yourself in Windows.

    git clone https://github.com/jtroo/kanata; cd kanata
    cargo build   # --release optional, not really perf sensitive
    target\debug\kanata --cfg <your_configuration_file>

Build and run yourself in macOS:

First install the Karabiner driver by following the macOS documentation
in the [releases page](https://github.com/jtroo/kanata/releases/).

Then you can compile and run with the instructions below:

    git clone https://github.com/jtroo/kanata && cd kanata
    cargo build   # --release optional, not really perf sensitive

    # sudo is needed to gain permission to intercept the keyboard

    sudo target/debug/kanata --cfg <your_configuration_file>

The full configuration guide is [found here](./docs/config.adoc).

Sample configuration files are found in [cfg_samples](./cfg_samples). The
[simple.kbd](./cfg_samples/simple.kbd) file contains a basic configuration file
that is hopefully easy to understand but does not contain all features. The
`kanata.kbd` contains an example of all features with documentation. The
release assets also have a `kanata.kbd` file that is tested to work with that
release. All key names can be found in the [keys module](./parser/src/keys/mod.rs),
and you can also define your own key names.

</details>

### Feature flags

When either building yourself or using `cargo install`,
you can add feature flags that
enable functionality that is turned off by default.

<details>
<summary>Instructions</summary>

If you want to enable the `cmd` actions,
add the flag `--features cmd`.
For example:

```
cargo build --release --features cmd
cargo install --features cmd
```

On Windows,
if you want to compile a binary that uses the Interception driver,
you should add the flag `--features interception_driver`.
For example:

```
cargo build --release --features interception_driver
cargo install --features interception_driver
```

To combine multiple flags,
use a single `--features` flag
and use a comma to separate the features.
For example:

```
cargo build --release --features cmd,interception_driver
cargo install --features cmd,interception_driver
```

</details>

## Other installation methods

<details>
<summary>Repositories for kanata</summary>

[![Packaging status](https://repology.org/badge/vertical-allrepos/kanata.svg)](https://repology.org/project/kanata/versions)

</details>

## Notable features

- Human-readable configuration file.
  - [Minimal example](./cfg_samples/minimal.kbd)
  - [Full guide](./docs/config.adoc)
  - [Simple example with explanations](./cfg_samples/simple.kbd)
  - [All features showcase](./cfg_samples/kanata.kbd)
- Live reloading of the configuration for easy testing of your changes.
- Multiple layers of key functionality
- Advanced actions such as tap-hold, unicode output, dynamic and static macros
- Vim-like leader sequences to execute other actions
- Optionally run a TCP server to interact with other programs
  - Other programs can respond to [layer changes or trigger layer changes](https://github.com/jtroo/kanata/issues/47)
- [Interception driver](https://web.archive.org/web/20240209172129/http://www.oblita.com/interception) support (use `kanata_wintercept.exe`)
  - Note that this issue exists, which is outside the control of this project:
    https://github.com/oblitum/Interception/issues/25

## Contributing

Contributions are welcome!

Unless explicitly stated otherwise, your contributions to kanata will be made
under the LGPL-3.0-only[*] license.

Some directories are exceptions:

- [keyberon](./keyberon): MIT License
- [interception](./interception): MIT or Apache-2.0 Licenses

[Here's a basic low-effort design doc of kanata](./docs/design.md)

[*]: https://www.gnu.org/licenses/identify-licenses-clearly.html

## How you can help

- Try it out and let me know what you think. Feel free to file an issue or
  start a discussion.
- Usability issues and unhelpful error messages are considered bugs that should
  be fixed. If you encounter any, I would be thankful if you file an issue.
- Browse the open issues and help out if you are able and/or would like to. If
  you want to try contributing, feel free to ping jtroo for some pointers.
- If you know anything about writing a keyboard driver for Windows, starting an
  open-source alternative to the Interception driver would be lovely.

## Community projects related to kanata

- [vscode-kanata](https://github.com/rszyma/vscode-kanata): Language support for kanata configuration files in VS Code
- [komokana](https://github.com/LGUG2Z/komokana): Automatic application-aware layer switching for [`komorebi`](https://github.com/LGUG2Z/komorebi) (Windows)
- [kanata-tray](https://github.com/rszyma/kanata-tray): Control kanata from a tray icon
- [OverKeys](https://github.com/conventoangelo/overkeys): Visual layer display for kanata - see your active layers and keymaps in real-time (Windows)
- Application-aware layer switching:
  - [qanata (Linux)](https://github.com/veyxov/qanata)
  - [kanawin (Windows)](https://github.com/Aqaao/kanawin)
  - [window_tools (Windows)](https://github.com/reidprichard/window_tools)
  - [nata (Linux)](https://github.com/mdSlash/nata)
  - [kanata-vk-agent (macOS)](https://github.com/devsunb/kanata-vk-agent)
  - [hyprkan (Linux)](https://github.com/mdSlash/hyprkan)
  - [kanata-switcher (Linux, all DEs)](https://github.com/7mind/kanata-switcher)
  - [kwanata (Linux-KDE)](https://github.com/jfsicilia/kwanata): A KDE Plasma companion for Kanata - Automatically activates Kanata's layers/virtualkeys and launches or raises apps.

## What does the name mean?

I wanted a "k" word since this relates to keyboards. According to Wikipedia,
kanata is an indigenous Iroquoian word meaning "village" or "settlement" and is
the origin of Canada's name.

There's also PPT✧.

## Motivation

TLDR: QMK features but for any keyboard, not just fancy mechanical ones.

<details>
  <summary>Long version</summary>

I have a few keyboards that run [QMK](https://docs.qmk.fm/#/). QMK allows the
user to customize the functionality of their keyboard to their heart's content.

One great use case of QMK is its ability map keys so that they overlap with the
home row keys but are accessible on another layer. I won't comment on
productivity, but I find this greatly helps with my keyboard comfort.

For example, these keys are on the right side of the keyboard:

    7 8 9
    u i o
    j k l
    m , .

On one layer I have arrow keys in the same position, and on another layer I
have a numpad.

    arrows:       numpad:
    - - -         7 8 9
    - ↑ -         4 5 6
    ← ↓ →         1 2 3
    - - -         0 * .

One could add as many customizations as one likes to improve comfort, speed,
etc. Personally my main motivator is comfort due to a repetitive strain injury
in the past.

However, QMK doesn't run everywhere. In fact, it doesn't run on **most**
hardware you can get. You can't get it to run on a laptop keyboard or any
mainstream office keyboard. I believe that the comfort and empowerment QMK
provides should be available to anyone with a computer on their existing
hardware, instead of having to purchase an enthusiast mechanical keyboard
(which are admittedly very nice — I own a few — but can be costly).

The best alternative solution that I found for keyboards that don't run QMK was
[kmonad](https://github.com/kmonad/kmonad). This is an excellent project
and I recommend it if you want to try something similar.

The reason for this project's existence is that kmonad is written in Haskell
and I have no idea how to begin contributing to a Haskell project. From an
outsider's perspective I think Haskell is a great language but I really can't
wrap my head around it. And there are a few [outstanding issues](./docs/kmonad_comparison.md)
at the time of writing that make kmonad suboptimal for my personal workflows.

This project is written in Rust because Rust is my favourite programming
language and the prior work of the awesome [keyberon crate](https://github.com/TeXitoi/keyberon)
exists.

</details>

## Similar Projects

The most similar project is [kmonad](https://github.com/kmonad/kmonad),
which served as the inspiration for kanata. [Here's a comparison document](./docs/kmonad_comparison.md).
Other similar projects:

- [QMK](https://docs.qmk.fm/#/): Open source keyboard firmware
- [keyberon](https://github.com/TeXitoi/keyberon): Rust `#[no_std]` library intended for keyboard firmware
- [ktrl](https://github.com/ItayGarin/ktrl): Linux-only keyboard customizer with layers, a TCP server, and audio support
- [kbremap](https://github.com/timokroeger/kbremap): Windows-only keyboard customizer with layers and unicode
- [xcape](https://github.com/alols/xcape): Linux-only tap-hold modifiers
- [karabiner-elements](https://karabiner-elements.pqrs.org/): Mac-only keyboard customizer
- [capsicain](https://github.com/cajhin/capsicain): Windows-only key remapper with driver-level key interception
- [keyd](https://github.com/rvaiya/keyd): Linux-only key remapper very similar to QMK, kmonad, and kanata
- [xremap](https://github.com/k0kubun/xremap): Linux-only application-aware key remapper inspired more by Emacs key sequences vs. QMK layers/Vim modes
- [keymapper](https://github.com/houmain/keymapper): Context-aware cross-platform key remapper with a different transformation model (Linux, Windows, Mac)
- [mouseless](https://github.com/jbensmann/mouseless): Linux-only mouse-focused key remapper that also has layers, key combo and tap-hold capabilities

### Why the list?

While kanata is the best tool for some, it may not be the best tool for
you. I'm happy to introduce you to tools that may better suit your needs. This
list is also useful as reference/inspiration for functionality that could be
added to kanata.

## Donations/Support?

The author (jtroo) will not accept monetary donations for work on kanata.
Please instead donate your time and/or money to charity.

Some links are below. These links are provided for learning and as interesting
reads. They are **not** an endorsement.

- https://www.effectivealtruism.org/
- https://www.givewell.org/


================================================
FILE: build.rs
================================================
fn main() -> std::io::Result<()> {
    #[cfg(feature = "win_manifest")]
    {
        windows::build()?;
    }
    Ok(())
}

#[cfg(feature = "win_manifest")]
mod windows {
    use indoc::formatdoc;
    use regex::Regex;
    use std::fs::File;
    use std::io::Write;
    extern crate embed_resource;

    // println! during build
    macro_rules! pb {
      ($($tokens:tt)*) => {println!("cargo:warning={}", format!($($tokens)*))}}

    pub(super) fn build() -> std::io::Result<()> {
        let manifest_path: &str = "./target/kanata.exe.manifest";

        // Note about expected version format:
        // MS says "Use the four-part version format: mmmmm.nnnnn.ooooo.ppppp"
        // https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests

        let re_ver_build = Regex::new(r"^(?<vpre>(\d+\.){2}\d+)[-a-zA-Z]+(?<vpos>\d+)$").unwrap();
        let re_ver_build2 = Regex::new(r"^(?<vpre>(\d+\.){2}\d+)[-a-zA-Z]+$").unwrap();
        let re_version3 = Regex::new(r"^(\d+\.){2}\d+$").unwrap();
        let mut version: String = env!("CARGO_PKG_VERSION").to_string();

        if re_version3.find(&version).is_some() {
            version = format!("{version}.0");
        } else if re_ver_build.find(&version).is_some() {
            version = re_ver_build
                .replace_all(&version, r"$vpre.$vpos")
                .to_string();
        } else if re_ver_build2.find(&version).is_some() {
            version = re_ver_build2.replace_all(&version, r"$vpre.0").to_string();
        } else {
            pb!("unknown version format '{}', using '0.0.0.0'", version);
            version = "0.0.0.0".to_string();
        }

        let manifest_str = formatdoc!(
            r#"<?xml version="1.0" encoding="utf-8" standalone="yes"?>
               <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:v3="urn:schemas-microsoft-com:asm.v3">
                 <assemblyIdentity name="kanata.exe" version="{}" type="win32"></assemblyIdentity>
                 <v3:trustInfo><v3:security>
                   <v3:requestedPrivileges><v3:requestedExecutionLevel level="asInvoker" uiAccess="false"></v3:requestedExecutionLevel></v3:requestedPrivileges>
                 </v3:security></v3:trustInfo>
                 <v3:application>
                   <v3:windowsSettings>
                     <dpiAware     xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
                     <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
                   </v3:windowsSettings>
                 </v3:application>
                 <dependency><dependentAssembly>
                   <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls"
                     version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly>
                 </dependency>
               </assembly>
            "#,
            version
        );
        let mut manifest_f = File::create(manifest_path)?;
        write!(manifest_f, "{manifest_str}")?;
        embed_resource::compile("./src/kanata.exe.manifest.rc", embed_resource::NONE);
        Ok(())
    }
}


================================================
FILE: cfg_samples/artsey.kbd
================================================
;; ARTSEY MINI 0.2 https://github.com/artseyio/artsey/issues/7

;; Exactly one defcfg entry is required. This is used for configuration key-pairs.
(defcfg
  ;; Your keyboard device will likely differ from this.
  linux-dev /dev/input/event1

  ;; Windows doesn't need any input/output configuration entries; however, there
  ;; must still be a defcfg entry. You can keep the linux-dev entry or delete
  ;; it and leave it empty.
)

(defsrc
  q    w    e
  a    s    d
)

(deflayer base
  (chord base A) (chord base R) (chord base T)
  (chord base S) (chord base E) (chord base Y)
)

(deflayer meta
  (chord meta A) (chord meta R) (chord meta T)
  (chord meta S) (chord meta E) (chord meta Y)
)

(defchords base 5000
  (A R T S E Y) (layer-switch meta)
  (A R T      ) (one-shot 2000 lsft)
  (      S E Y) spc
  (A          ) a
  (  R T S    ) b
  (  R   S    ) c
  (A       E Y) d
  (        E  ) e
  (A R        ) f
  (A       E  ) g
  (      S   Y) h
  (  R     E  ) i
  (    T S E  ) j
  (    T   E  ) k
  (      S E  ) l
  (  R T      ) m
  (        E Y) n
  (A     S    ) o
  (A R       Y) p
  (    T     Y) q
  (  R        ) r
  (      S    ) s
  (    T      ) t
  (A   T      ) u
  (A   T   E  ) v
  (    T S    ) w
  (A         Y) x
  (          Y) y
  (  R   S E  ) z
)

(defchords meta 5000
  (A R T S E Y) (layer-switch base)
  (      S E Y) spc
  (A R T      ) caps ;; should technically be shift lock, probably need to use fake keys for that 
  (A R        ) bspc
  (  R T      ) del
  (      S E  ) C-c
  (        E Y) C-v
  (A          ) home
  (  R        ) up
  (    T      ) end
  (      S    ) left
  (        E  ) down
  (          Y) rght
)


================================================
FILE: cfg_samples/automousekeys-full-map.kbd
================================================
(defcfg
  ;; F* keys and arrow keys are left unmapped
  process-unmapped-keys yes

  ;; you may wish to only capture a trackpoint and keyboard
  ;; but not e.g. a trackpad or external mouse
  ;;linux-dev-names-include (
  ;;                         "AT Translated Set 2 keyboard"
  ;;                         "TPPS/2 Elan TrackPoint"
  ;;)
  ;; optional, but useful with the trackpoint
  ;;linux-use-trackpoint-property yes

  mouse-movement-key mvmt
)

;; ANSI layout for eg thinkpad internal or external keyboard
(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt menu rctl
  mvmt
)

(defvirtualkeys
  mouse (layer-while-held mouse-layer)
)

(defalias
  mhld (hold-for-duration 750 mouse)

  moff (on-press release-vkey mouse)

  _ (multi
     @moff
     _
  )

   ;; mouse click extended time out for double tap
  mdbt (hold-for-duration 500 mouse)
  mbl (multi
       mlft
       @mdbt
  )
  mbm (multi
       mmid
       @mdbt
  )
  mbr (multi
       mrgt
       @mdbt
  )
)

;; no mappings
(deflayer qwerty
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt menu rctl
  @mhld
)

;; places mouse keys on the row above the home row.
;; pressing any other keys exits the mouse layer until mouse movement stops and restarts again.
(deflayer mouse-layer
  @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_
  @_   @_   mrgt mmid @mbl @_   @_   @mbl mmid mrgt @_   @_   @_   @_
  @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_
  @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_   @_
  @_   @_   @_             @_             @_   @_   @_
  @mhld
)


================================================
FILE: cfg_samples/automousekeys-only.kbd
================================================
(defcfg
  ;; we are only mapping the keys we want to use for mouse keys
  process-unmapped-keys yes

  ;; you may wish to only capture a trackpoint and keyboard
  ;; but not e.g. a trackpad or external mouse
  ;;linux-dev-names-include (
  ;;                         "Lenovo TrackPoint Keyboard II"
  ;;)
  ;; optional, but useful with the trackpoint
  ;;linux-use-trackpoint-property yes

  mouse-movement-key mvmt
)

(defsrc)

(defvirtualkeys
  mouse (layer-while-held mouse-layer)
)

(defalias
  mhld (hold-for-duration 750 mouse)

  moff (on-press release-vkey mouse)

  _ (multi
     @moff
     _
  )

  ;; mouse click extended time out for double tap
  mdbt (hold-for-duration 500 mouse)
  mbl (multi
       mlft
       @mdbt
  )
  mbm (multi
       mmid
       @mdbt
  )
  mbr (multi
       mrgt
       @mdbt
  )
)

;; no key mappings
(deflayermap (base)
             mvmt @mhld
)

;; places mouse keys on the row above the home row.
;; pressing any other keys exits the mouse layer until mouse movement stops and restarts again.
(deflayermap (mouse-layer)
             w mrgt
             e mmid
             r @mbl

             u @mbl
             i mmid
             o mrgt

             mvmt @mhld
             ___ @_
)


================================================
FILE: cfg_samples/chords.tsv
================================================
rus	rust
col	cool
nice	nice
you	you
th	the
 a	a
 an	an
man	man
name	name
an	and
as	as
or	or
bu	but
if	if
so	so
dn	then
bc	because

to	to
of	of
in	in
 f	for
 w	with
on	on
at	at
fm	from
by	by
abt	about
up	up
io	into
ov	over
af	after
wo	without
 i	I
 me	me
 my	my
ou	you
ur	your
he	he
hm	him
his	his
sh	she
hr	her
it	it
ts	its
we	we
us	us
our	our
dz	they
dr	their
dm	them
wc	which
wn	when
wt	what
wr	where
ho	who
hw	how
wz	why
is	is
ar	are
wa	was
er	were
be	be
hv	have
hs	has
hd	had
nt	not
cn	can
do	do
wl	will
cd	could
wd	would
sd	should
li	like
bn	been
ge	get
maz	may
mad	made
mk	make
ai	said
wk	work
uz	use
sz	say
 g	go
kn	know
tk	take
 se	see
lk	look
cm	come
thk	think
wnt	want
gi	give
ct	cannot
de	does
di	did
sem	seem
cl	call
tha	thank

 im	I'm
 id	I'd
dt	that
dis	this
des	these
tes	test
al	all
 o	one
mo	more
the	there
out	out
ao	also
tm	time
sm	some
js	just
ne	new
odr	other
pl	people
 n	no
dan	than
oz	only
 m	most
ay	any
may	many
el	well
fs	first
vy	very
much	much
now	now
ev	even
go	good
grt	great
way	way
 t	two
yr	year
bk	back
day	day
qn	question
sc	second
dg	thing
 y	yes
cn'	can't
dif	different
dgh	though
tru	through
sr	sorry
mv	move
dir	dir
stop	stop
tye	type
nx	next
sam	same
tp	top
cod	code
git	git
 to	TODO
cls	class
clus	cluster
sure	sure
lets	let's
sup	super
such	such
thig	thing
yet	yet
don	done
sem	seem
ran	ran
job	job
bot	bot
fx	effect
nce	once
rad	read
ltr	later
lot	lot
brw	brew
unst	uninstall
rmv	remove
 ad	add
poe	problem
buld	build
 tol	tool
got	got
les	less
 0	zero
 1	one
 2	two
 3	three
 4	four
 5	five
 6	six
 7	seven
 8	eight
 9	nine


================================================
FILE: cfg_samples/colemak.kbd
================================================
;;
;;  Learn Colemak, a few keys at a time.
;;
;;  The "j" key moves around the keyboard each step,
;;  until you reach the full Colemak layout.
;;
;;  To select the layout for your current step, press the
;;  letter "m" and the number of your current step, as a chord.
;;
;;  Check out:  https://dreymar.colemak.org/tarmak-intro.html
;;        and:  https://colemak.com
;;

(defsrc
  q w e r t y u i o p
  a s d f g h j k l ;
  z x c v b n m
)

(deflayer colemak_j1
  _ _ j _ _ _ _ _ _ _
  _ _ _ _ _ _ n e _ _
  _ _ _ _ _ k _
)

(deflayer colemak_j2
  _ _ f _ g _ _ _ _ _
  _ _ _ t j _ n e _ _
  _ _ _ _ _ k _
)

(deflayer colemak_j3
  _ _ f j g _ _ _ _ _
  _ r s t d _ n e _ _
  _ _ _ _ _ k _
)

(deflayer colemak_j4
  _ _ f p g j _ _ y ;
  _ r s t d _ n e _ o
  _ _ _ _ _ k _
)

(deflayer colemak
  _ _ f p g j l u y ;
  _ r s t d _ n e i o
  _ _ _ _ _ k _
)

(defcfg
  process-unmapped-keys   yes
  concurrent-tap-hold     yes
  allow-hardware-repeat   no
)

(defchordsv2
  (m 1) (layer-switch colemak_j1) 300 all-released ()
  (m 2) (layer-switch colemak_j2) 300 all-released ()
  (m 3) (layer-switch colemak_j3) 300 all-released ()
  (m 4) (layer-switch colemak_j4) 300 all-released ()
  (m 5) (layer-switch colemak) 300 all-released ()
)



================================================
FILE: cfg_samples/deflayermap.kbd
================================================
;; A configuration showcasing deflayermap.
;;
;; The process-unmapped-keys defcfg item is not used
;; and the lctl and ralt keys are unmapped
;; because mapping them can cause problems on Windows
;; with non-US layouts.

(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
       lmet lalt           spc                 rmet rctl
)

(deflayermap (base)
  caps (tap-hold 200 200 (caps-word 2000) lctl)
  spc  (tap-hold 200 200 spc (layer-while-held nav))
)

(deflayermap (nav)
  i up
  j left
  k down
  l right
)


================================================
FILE: cfg_samples/f13_f24.kbd
================================================
(defcfg
  linux-dev /dev/input/by-path/platform-i8042-serio-0-event-kbd
)

(defsrc
       f13  f14  f15  f16  f17  f18  f19  f20  f21  f22  f23  f24
)

(deflayer test
       f13  f14  f15  f16  f17  f18  f19  f20  f21  f22  f23  f24
)



================================================
FILE: cfg_samples/fancy_symbols.kbd
================================================
;; Turns   ⎇›            RightAlt into a symbol key to insert valid kanata unicode symbols for the pressed key
;; Turns ⇧›⎇› RightShift+RightAlt into a symbol key to insert extra symbols for the same keys
;; e.g., ⎇›Delete will print ␡
(defcfg)
(defalias
   🔣 (layer-while-held fancy-symbol)
  ⇧🔣 (layer-while-held ⇧fancy-symbol))
(defsrc
  ‹🖰	🖰›	🖰3	🖰4	🖰5
  ▶⏸	◀◀	▶▶	🔇 	🔉	🔊	🔅	🔆	🎛	⌨💡+	⌨💡−
  ⎋
  ˋ 	  	1 	2	3	4	5	6	7	8 	9	0	- 	=	␈	⎀	⇤	⇞	⇭ 	🔢⁄	🔢∗	🔢₋
  ⭾ 	  	q 	w	e	r	t	y	u	i 	o	p	[ 	]	\	␡	⇥	⇟	🔢₇	🔢₈	🔢₉	🔢₊
  ⇪ 	  	a 	s	d	f	g	h	j	k 	l	;	' 	⏎	 	 	 	 	🔢₄	🔢₅	🔢₆
  ‹⇧	  	z 	x	c	v	b	n	m	, 	.	/	⇧›	 	▲	 	 	 	🔢₁	🔢₂	🔢₃	🔢⏎
  ‹⎈	‹◆	‹⎇	␠	 	 	 	 	 	⎇›	 	☰	⎈›	◀	▼	▶	 	 	🔢₀	🔢⸴           )
(deflayer qwerty ;; =base with ⎇› as a fancy symbol key
  ‗	‗	‗	‗	‗
  ‗	‗	‗	‗	‗	‗	‗	‗	‗	‗	‗
  ‗
  ‗	‗	‗	‗	‗	‗	‗	‗	‗	‗ 	‗	‗	‗	‗	‗	‗	‗	‗	‗	‗	‗
  ‗	‗	‗	‗	‗	‗	‗	‗	‗	‗ 	‗	‗	‗	‗	‗	‗	‗	‗	‗	‗	‗
  ‗	‗	‗	‗	‗	‗	‗	‗	‗	‗ 	‗	‗	‗	 	 	 	 	‗	‗	‗
  ‗	‗	‗	‗	‗	‗	‗	‗	‗	‗ 	‗	‗	 	‗	 	 	 	‗	‗	‗	‗
  ‗	‗	‗	‗	 	 	 	 	 	@🔣	 	‗	‗	‗	‗	‗	 	‗	‗           )
(deflayer  fancy-symbol ;; •block all other keys
  🔣‹🖰	🔣🖰›	🔣🖰3	🔣🖰4	🔣🖰5
  🔣▶⏸	🔣◀◀	🔣▶▶	🔣🔇 	🔣🔉	🔣🔊	🔣🔅	🔣🔆	🔣🎛	🔣⌨💡+	🔣⌨💡−
  🔣⎋
  🔣ˋ	  	• 	• 	•	•	•	•	•	• 	• 	• 	🔣‐ 	🔣₌	🔣␈	🔣⎀	🔣⇤	🔣⇞	🔣⇭   	🔣🔢⁄	🔣🔢∗	🔣🔢₋
  🔣⭾	  	• 	• 	•	•	•	•	•	• 	• 	• 	🔣【 	🔣】	🔣⧵	🔣␡	🔣⇥	🔣⇟	🔣🔢₇  	🔣🔢₈	🔣🔢₉	🔣🔢₊
  🔣⇪	  	• 	• 	•	•	•	•	•	• 	• 	🔣︔	'  	🔣⏎	  	  	  	  	  🔣🔢₄	🔣🔢₅	🔣🔢₆
  🔣⇧	  	• 	• 	•	•	•	•	•	🔣⸴	🔣.	🔣⁄	@⇧🔣	  	🔣▲	  	  	  	  🔣🔢₁	🔣🔢₂	🔣🔢₃	🔣🔢⏎
  🔣⎈	🔣◆	🔣⎇	🔣␠	 	 	 	 	 	• 	  	🔣☰	•  	🔣◀	🔣▼	🔣▶	  	  	  🔣🔢₀	🔣🔢⸴  )
(deflayer ⇧fancy-symbol ;; •block all other keys
  🔣🖰1	🔣🖰2	•	•    	•
  •  	•  	•	🔣🔈⓪⓿₀	•	🔣🔈−➖₋⊖	🔣🔈+➕₊⊕	•	•	🔣⌨💡➕₊⊕	🔣⌨💡➖₋⊖
  •
  🔣˜	   	• 	• 	•	•	•	•	•	•  	•	•	-   	=   	🔣⌫	• 	🔣⤒↖	🔣🔢	•	•	•	•
  🔣↹	   	• 	• 	•	•	•	•	•	•  	•	•	🔣「〔⎡	🔣」〕⎣	🔣\	🔣⌦	🔣⤓↘	• 	•	•	•	•
  • 	   	• 	• 	•	•	•	•	•	•  	•	•	•   	🔣↩⌤␤	  	  	   	  	 	•	•	•
  • 	   	• 	• 	•	•	•	•	•	•  	•	/	•   	    	• 	  	   	  	 	•	•	•	🔣🔢↩⌤␤
  🔣⌃	🔣❖⌘	🔣⌥	🔣␣	 	 	 	 	 	🔣▤𝌆	 	•	•   	•   	• 	• 	   	  	•	•   )


================================================
FILE: cfg_samples/home-row-mod-advanced.kbd
================================================
;; Home row mods QWERTY example with more complexity.
;; Some of the changes from the basic example:
;; - when a home row mod activates tap, the home row mods are disabled
;;   while continuing to type rapidly
;; - tap-hold-release helps make the hold action more responsive
;; - pressing another key on the same half of the keyboard
;;   as the home row mod will activate an early tap action
;;
;; Suggested further reading:
;;
;; GitHub discussion on more advanced tap-hold improvements:
;;
;;    https://github.com/jtroo/kanata/discussions/1455
;;
;; Configuration guide documentation on all tap-hold options:
;;
;;    https://github.com/jtroo/kanata/blob/main/docs/config.adoc#tap-hold

(defcfg
  process-unmapped-keys yes
)
(defsrc
  a   s   d   f   j   k   l   ;
)
(defvar
  ;; Note: consider using different time values for your different fingers.
  ;; For example, your pinkies might be slower to release keys and index
  ;; fingers faster.
  tap-time 200
  hold-time 150

  left-hand-keys (
    q w e r t
    a s d f g
    z x c v b
  )
  right-hand-keys (
    y u i o p
    h j k l ;
    n m , . /
  )
)
(deflayer base
  @a  @s  @d  @f  @j  @k  @l  @;
)

(deflayer nomods
  a   s   d   f   j   k   l   ;
)
(deffakekeys
  to-base (layer-switch base)
)
(defalias
  tap (multi
    (layer-switch nomods)
    (on-idle-fakekey to-base tap 20)
  )

  a (tap-hold-release-keys $tap-time $hold-time (multi a @tap) lmet $left-hand-keys)
  s (tap-hold-release-keys $tap-time $hold-time (multi s @tap) lalt $left-hand-keys)
  d (tap-hold-release-keys $tap-time $hold-time (multi d @tap) lctl $left-hand-keys)
  f (tap-hold-release-keys $tap-time $hold-time (multi f @tap) lsft $left-hand-keys)
  j (tap-hold-release-keys $tap-time $hold-time (multi j @tap) rsft $right-hand-keys)
  k (tap-hold-release-keys $tap-time $hold-time (multi k @tap) rctl $right-hand-keys)
  l (tap-hold-release-keys $tap-time $hold-time (multi l @tap) ralt $right-hand-keys)
  ; (tap-hold-release-keys $tap-time $hold-time (multi ; @tap) rmet $right-hand-keys)
)


================================================
FILE: cfg_samples/home-row-mod-basic.kbd
================================================
;; Basic home row mods example using QWERTY
;; For a more complex but perhaps usable configuration,
;; see home-row-mod-advanced.kbd

(defcfg
  process-unmapped-keys yes
)
(defsrc
  a   s   d   f   j   k   l   ;
)
(defvar
  ;; Note: consider using different time values for your different fingers.
  ;; For example, your pinkies might be slower to release keys and index
  ;; fingers faster.
  tap-time 200
  hold-time 150
)
(defalias
  a (tap-hold $tap-time $hold-time a lmet)
  s (tap-hold $tap-time $hold-time s lalt)
  d (tap-hold $tap-time $hold-time d lctl)
  f (tap-hold $tap-time $hold-time f lsft)
  j (tap-hold $tap-time $hold-time j rsft)
  k (tap-hold $tap-time $hold-time k rctl)
  l (tap-hold $tap-time $hold-time l ralt)
  ; (tap-hold $tap-time $hold-time ; rmet)
)
(deflayer base
  @a  @s  @d  @f  @j  @k  @l  @;
)

================================================
FILE: cfg_samples/home-row-mod-prior-idle.kbd
================================================
;; Home row mods with tap-hold-require-prior-idle.
;;
;; This replaces the layer-switching workaround in home-row-mod-advanced.kbd
;; with two native features:
;;
;;   tap-hold-require-prior-idle  — during fast typing, tap-hold keys resolve as tap
;;                         immediately (no waiting state, no accidental holds)
;;
;;   tap-hold-opposite-hand — hold activates only when the next key is on
;;                            the opposite hand; same-hand rolls always tap
;;
;; The result: no nomods layer, no fakekeys, no multi wrappers.
;;
;; Configuration guide:
;;   https://github.com/jtroo/kanata/blob/main/docs/config.adoc#tap-hold-require-prior-idle
;;   https://github.com/jtroo/kanata/blob/main/docs/config.adoc#tap-hold

(defcfg
  process-unmapped-keys yes
  ;; If any key was pressed within 150ms, resolve tap-hold as tap immediately.
  ;; Prevents accidental modifier activation during fast typing.
  tap-hold-require-prior-idle 150
)

(defsrc
  a   s   d   f   j   k   l   ;
)

;; Declare which keys belong to each hand.
;; tap-hold-opposite-hand uses this to decide hold vs tap.
(defhands
  (left  q w e r t a s d f g z x c v b)
  (right y u i o p h j k l ; n m , . /)
)

(deflayer base
  @a  @s  @d  @f  @j  @k  @l  @;
)

(defalias
  ;; Note: consider using different time values for your different fingers.
  ;; For example, your pinkies might be slower to release keys and index
  ;; fingers faster.
  a (tap-hold-opposite-hand 150 a lmet)
  s (tap-hold-opposite-hand 150 s lalt)
  d (tap-hold-opposite-hand 150 d lctl)
  f (tap-hold-opposite-hand 150 f lsft)
  j (tap-hold-opposite-hand 150 j rsft)
  k (tap-hold-opposite-hand 150 k rctl)
  l (tap-hold-opposite-hand 150 l ralt)
  ; (tap-hold-opposite-hand 150 ; rmet)
)


================================================
FILE: cfg_samples/included-file.kbd
================================================
(defalias
  included-alias (macro i spc a m spc i n c l u d e d)
)


================================================
FILE: cfg_samples/japanese_mac_eisu_kana.kbd
================================================
#|
  Using meta keys as japanese eisu and kana on Mac with US keyboard.

  | Source  | Tap          | Hold |
  | ------- | ------------ | ---- |
  | lmet    | lang2 (eisu) | lmet |
  | rmet    | lang1 (kana) | rmet |

|#

(defcfg
  process-unmapped-keys yes
)

(defsrc
  lmet  rmet
)

(deflayer default
  @lmet @rmet
)

(defalias
  lmet (tap-hold-press 200 200 eisu lmet)
  rmet (tap-hold-press 200 200 kana rmet)
)



================================================
FILE: cfg_samples/jtroo.kbd
================================================
(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

(defalias
  ;; toggle layer aliases
  num (layer-toggle numbers)
  chr (layer-toggle chords)
  arr (layer-toggle arrows)
  msc (layer-toggle misc)
  lay (layer-toggle layers)
  mse (layer-toggle mouse)

  ;; change the base layer between qwerty and dvorak
  dvk (layer-switch dvorak)
  qwr (layer-switch qwerty)

  ;; tap-hold keys with letters for tap and layer change for hold
  anm (tap-hold-release 200 200 a @num)
  oar (tap-hold-release 200 200 o @arr)
  ech (tap-hold-release 200 200 e @chr)
  umc (tap-hold-release 200 200 u @msc)
  grl (tap-hold-release 200 200 grv @lay)
  .ms (tap-hold-release 200 200 . @mse)

  ;; tap for capslk, hold for lctl
  cap (tap-hold-release 200 200 caps lctl)

  ;; chords
  csv C-S-v
  csc C-S-c
)

(deflocalkeys-linux
  pho 445
)

(defalias
  ;; shifted keys
  { S-[
  } S-]
  : S-;
  ral (tap-hold-release 200 200 sldr ralt)
)

(defalias
  alp (multi a b c d e f g h i j k l m n o p q r s t u v w x y z)
  ls (macro l s spc min a l ret)
)

(deflayer dvorak
  @grl 1    2    3    4    5    6    7    8    9    0    [    ]    bspc
  tab  '    ,    @.ms p    y    f    g    c    r    l    /    =    \
  @cap @anm @oar @ech @umc i    d    h    t    n    s    -    ret
  lsft ;    q    j    k    x    b    m    w    v    z    rsft
  lctl lmet lalt           spc            @ral rmet rctl
)

(deflayer qwerty
  @grl 1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

(deflayer layers
  _    @qwr @dvk lrld _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

(deflayer numbers
  _    _    _    _    _    _    nlk  kp7  kp8  kp9  _    _    _    _
  _    _    C-S-tab C-tab _ XX  _    kp4  kp5  kp6  min  _    _    _
  _    _    C-z  C-y  M-tab XX  _    kp1  kp2  kp3  +    _    _
  _    C-z  C-x  C-c  C-v  XX   _    kp0  kp0  .    /    _
  _    _    _              _              _    _    _
)

(deflayer misc
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    ins  @{   @}    [   ]    _    _    _
  _    _    _    _    C-u  _    C-bspc bspc esc ret _    _    _
  _    C-z  C-x  C-c  C-v  _    _    del  _    _    _    _
  _    _    _              _              _    _    _
)

(deflayer chords
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    @csc _    @ls  _    _    _
  _    @alp _    _    C-u  _    C-d  _    S-;  _    C-s  _    _
  _    _    _    _    _    _    C-b  _    _    @csv _    _
  _    _    _              _              _    _    _
)

(deflayer arrows
  _    f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12  _
  _    _    _    _    _    _    C-S-tab pgup up pgdn C-tab _  _    _
  _    _    _    _    _    _    home left down rght end  _    _
  _    _    _    _    _    _    _    _    C-w  _    _    _
  _    _    _              _              _    _    _
)

(defalias
  mwu (mwheel-up 50 120)
  mwd (mwheel-down 50 120)
  mwl (mwheel-left 50 120)
  mwr (mwheel-right 50 120)
)

(deflayer mouse
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    @mwu bck  _    fwd  _    _    _    _    _    _    _    _    _
  _    @mwd mlft _    mrgt mmid _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

(defseq "git status" (g s t)
  "git commit --amend --no-edit" (g c a)
  "git rebase -i HEAD~" (g r e b)
  "git log --pretty=oneline --abbrev-commit" (g l s)
  "git diff --ignore-space-change" (g d f)
  "git diff --cached --ignore-space-change" (g d c)
  "git push -f" (g p f)
  "git commit -m 'fix_this_commit_message'" (g c m)
)

(deffakekeys
  "git status" (macro g i t spc s t a t u s)
  "git commit --amend --no-edit" (macro g i t spc c o m m i t spc min min a m e n d spc min min n o min e d i t)
  "git rebase -i HEAD~" (macro g i t spc r e b a s e spc min i spc S-h S-e S-a S-d S-grv)
  "git log --pretty=oneline --abbrev-commit" (macro
    g i t spc l o g spc
      min min p r e t t y = o n e l i n e spc
      min min a b b r e v min c o m m i t
  )
  "git diff --ignore-space-change" (macro
    g i t spc d i f f spc
      min min i g n o r e min s p a c e min c h a n g e
  )
  "git diff --cached --ignore-space-change" (macro
    g i t spc d i f f spc
      min min c a c h e d spc
      min min i g n o r e min s p a c e min c h a n g e
  )
  "git push -f" (macro g i t spc p u s h spc min f)
  "git commit -m 'fix_this_commit_message'" (macro
    g i t spc c o m m i t spc
      min m spc ' f i x S-min t h i s S-min c o m m i t S-min m e s s a g e '
  )
)


================================================
FILE: cfg_samples/kanata.kbd
================================================
#|
This is a sample configuration file that showcases every feature in kanata.
A more detailed and less terse configuration guide is found here:

    https://github.com/jtroo/kanata/blob/main/docs/config.adoc

Other configuration samples are found here:

    https://github.com/jtroo/kanata/tree/main/cfg_samples

If anything is confusing or hard to discover, please file an issue or
contribute a pull request to help improve the document.

Since it may be important for you to know, pressing and holding all of the
three following keys together at the same time will cause kanata to exit:

  Left Control, Space, Escape

This is for the physical key input rather than after any remappings
that are done by kanata.

|#

;; Single-line comments are prefixed by double-semicolon. A single semicolon
;; is parsed as the keyboard key. Comments are ignored for the configuration
;; file.

#|
A multi-line comment block begin with an octothorphe followed by a pipe: `#|`.
To end the multi-line comment block, have a pipe followed by an octothorpe,
like the following sequence with the colon removed: `|:#`. The actual two
character sequence is not used because it would end this multi-line comment
block and cause a parsing error.

This configuration language is Lisp-like and uses S-Expression syntax.
If you're unfamiliar with Lisp, don't be alarmed. The maintainer jtroo is
also unfamiliar with Lisp. You don't need to know Lisp in-depth to
be able to configure kanata.

If you follow along with the examples, you should be fine. Kanata should
also hopefully have helpful error messages in case something goes wrong.
If you need help, please feel welcome to ask in the GitHub discussions.
|#

;; One defcfg entry may be added if desired. This is used for configuration
;; key-value pairs that change kanata's behaviour at a global level.
;; All defcfg options are optional.
(defcfg
  ;; Your keyboard device will likely differ from this. I believe /dev/input/by-id/
  ;; is preferable; I recall reading that it's less likely to change names on you,
  ;; but I didn't find any keyboard device in there in my VM. If you are on Linux
  ;; and omit this entry, kanata will try to attach to every device found on your
  ;; system that seems like a keyboard.
  ;; linux-dev /dev/input/by-path/platform-i8042-serio-0-event-kbd

  ;; If you want to read from multiple devices, separate them by `:`.
  ;; linux-dev /dev/input/<dev1>:/dev/input/<dev2>
  ;;
  ;; If you have a colon in your device path, add a backslash before it so that
  ;; kanata does not parse it as multiple devices.
  ;; linux-dev /dev/input/path-to\:device

  ;; Alternatively, you can use list syntax, where both backslashes and colons
  ;; are parsed literally. List items are separated by spaces or newlines.
  ;; Using quotation marks for each item is optional, and only required if an
  ;; item contains spaces.
  ;; linux-dev (
  ;;   /dev/input/by-path/pci-0000:00:14.0-usb-0:1:1.0-event
  ;;   /dev/input/by-id/usb-Dell_Dell_USB_Keyboard-event-kbd
  ;; )

  ;; The linux-dev-names-include entry is parsed identically to linux-dev. It
  ;; defines a list of device names that should be included. This is only
  ;; used if linux-dev is omitted.
  ;; linux-dev-names-include device-1-name:device\:2\:name

  ;; The linux-dev-names-exclude entry is parsed identically to linux-dev. It
  ;; defines a list of device names that should be excluded. This is only
  ;; used if linux-dev is omitted. This and linux-dev-names-include are not
  ;; mutually exclusive but in practice it probably makes sense to only use
  ;; one of them.
  ;; linux-dev-names-exclude device-1-name:device\:2\:name

  ;; By default, kanata will crash if no input devices are found. You can change
  ;; this behaviour by setting `linux-continue-if-no-devs-found`.
  ;;
  ;; linux-continue-if-no-devs-found yes

  ;; Kanata on Linux automatically detects and grabs input devices
  ;; when none of the explicit device configurations are in use.
  ;; In case kanata is undesirably grabbing mouse-like devices,
  ;; you can use a configuration item to change detection behaviour.
  ;;
  ;; linux-device-detect-mode keyboard-only

  ;; On Linux, you can ask kanata to run `xset r rate <delay> <rate>` on startup
  ;; and on live reload via the config below. The first number is the delay in ms
  ;; and the second number is the repeat rate in repeats/second.
  ;;
  ;; linux-x11-repeat-delay-rate 400,50

  ;; On linux, you can ask kanata to label itself as a trackpoint. This has several
  ;; effects on libinput including enabling middle mouse button scrolling and using
  ;; a different acceleration curve. Otherwise, a trackpoint intercepted by kanata
  ;; may not behave as expected.
  ;;
  ;; If using this feature, it is recommended to filter out any non-trackpoint
  ;; pointing devices using linux-only-linux-dev-names-include,
  ;; linux-only-linux-dev-names-exclude or linux-only-linux-dev to avoid changing
  ;; their behavior as well.
  ;;
  ;; linux-use-trackpoint-property yes

  ;; Unicode on Linux works by pressing Ctrl+Shift+U, typing the unicode hex value,
  ;; then pressing Enter. However, if you do remapping in userspace, e.g. via
  ;; xmodmap/xkb, the keycode "U" that kanata outputs may not become a keysym "u"
  ;; after the userspace remapping. This will be likely if you use non-US,
  ;; non-European keyboards on top of kanata. For unicode to work, kanata needs to
  ;; use the keycode that outputs the keysym "u", which might not be the keycode
  ;; "U".
  ;;
  ;; You can use `evtest` or `kanata --debug`, set your userspace key remapping,
  ;; then press the key that outputs the keysym "u" to see which underlying keycode
  ;; is sent. Then you can use this configuration to change kanata's behaviour.
  ;;
  ;; Example:
  ;;
  ;;   linux-unicode-u-code v

  ;; Unicode on Linux terminates with the Enter key by default. This may not work in
  ;; some applications. The termination is configurable with the following options:
  ;;
  ;; - `enter`
  ;; - `space`
  ;; - `enter-space`
  ;; - `space-enter`
  ;;
  ;; Example:
  ;;
  ;;   linux-unicode-termination space

  ;; Kanata on Linux creates an evdev output device named "kanata".
  ;; This name can be changed with this linux-output-device-name.
  ;;
  ;; Examples:
  ;;
  ;;   linux-output-device-name kanata_laptop
  ;;   linux-output-device-name "kanata output device"

  ;; Kanata on Linux needs to declare a "bus type" for its evdev output device.
  ;; The options are USB and I8042. The default is I8042.
  ;; Using USB can break disable-touchpad-while-typing on Wayland.
  ;; But using I8042 appears to break some other scenarios. Thus it is configurable.
  ;;
  ;; Examples:
  ;;
  ;;   linux-output-device-bus-type USB
  ;;   linux-output-device-bus-type I8042

  ;; There is an optional configuration entry for Windows to help mitigate strange
  ;; behaviour of AltGr if your layout uses that. Uncomment one of the items below
  ;; to change what kanata does with the key.
  ;;
  ;; For more context, see: https://github.com/jtroo/kanata/issues/55.
  ;;
  ;; windows-altgr cancel-lctl-press ;; remove the lctl press that comes as a combo with ralt
  ;; windows-altgr add-lctl-release  ;; add an lctl release when ralt is released
  ;;
  ;; NOTE: even with these workarounds, putting lctl+ralt in your defsrc may
  ;; not work too well with other applications that use WH_KEYBOARD_LL.
  ;; Known applications with issues: GWSL/VcXsrv

  ;; Enable kanata to execute commands.
  ;;
  ;; I consider this feature a hazard so it is conditionally compiled out of
  ;; the default binary.
  ;;
  ;; This is dangerous because it allows kanata to execute arbitrary commands.
  ;; Using a binary compiled with the cmd feature enabled, uncomment below to
  ;; enable command execution:
  ;;
  ;; danger-enable-cmd yes

  ;; Enable processing of keys that are not in defsrc.
  ;; This is useful if you are only mapping a few keys in defsrc instead of
  ;; most of the keys on your keyboard. Without this, the tap-hold-release and
  ;; tap-hold-press actions will not activate for keys that are not in defsrc.
  ;;
  ;; The reason this is not enabled by default is because some keys may not
  ;; work correctly if they are intercepted. E.g. rctl/altgr on Windows; see the
  ;; windows-altgr configuration item above for context.
  ;;
  ;; process-unmapped-keys yes

  ;; We need to set it to yes in this kanata.kbd example config to allow the use of __ and ___
  ;; in the deflayer-custom-map example below in the file

  ;; This also accepts a list parameter (all-except key1 ... keyN)
  ;; which behaves like "yes" but excludes the keys within the list.
  process-unmapped-keys (all-except f19)

  ;; Disable all keys not mapped in defsrc.
  ;; Only works if process-unmapped-keys is also yes.
  ;; block-unmapped-keys yes

  ;; Intercept mouse buttons for a specific mouse device.
  ;; The intended use case for this is for laptops such as a Thinkpad, which have
  ;; mouse buttons that may be useful to activate kanata actions with. This only
  ;; works with the Interception driver.
  ;;
  ;; To know what numbers to put into the string, you can run the
  ;; kanata-wintercept variant with this defcfg item defined with random numbers.
  ;; Then when a button is first pressed on the mouse device, kanata will print
  ;; its hwid in the log; you can then copy-paste that into this configuration
  ;; entry. If this defcfg item is not defined, the log will not print.
  ;;
  ;; windows-interception-mouse-hwid "70, 0, 90, 0, 20"

  ;; There is also a list version of windows-interception-mouse-hwid:
  ;;
  ;; windows-interception-mouse-hwids (
  ;;   "70, 0, 60, 0"
  ;;   "71, 0, 62, 0"
  ;; )

  ;; List configuration for kanata-wintercept variants
  ;; that allows intercepting only some connected keyboards.
  ;; Use similarly to mouse-hwid above.
  ;;
  ;; windows-interception-keyboard-hwids (
  ;;   "90, 80, 11, 34"
  ;;   "99, 88, 77, 66"
  ;; )

  ;; There are also exclude variants of the wintercept device configurations.
  ;; These cannot be defined at the same time as the non-exclude variants.
  ;;
  ;; windows-interception-keyboard-hwids-exclude (
  ;;   "90, 80, 11, 34"
  ;;   "99, 88, 77, 66"
  ;; )
  ;;
  ;; windows-interception-mouse-hwids-exclude (
  ;;   "70, 0, 60, 0"
  ;;   "71, 0, 62, 0"
  ;; )

  ;; Transparent keys on layers will delegate to the corresponding defsrc key
  ;; when found on a layer activated by `layer-switch`. This config entry
  ;; changes the behaviour to delegate to the action of the first layer,
  ;; which is the layer active upon startup, that is in the same position.
  ;;
  ;; delegate-to-first-layer yes

  ;; This config entry alters the behavior of movemouse-accel actions.
  ;; By default, this setting is disabled - vertical and horizontal
  ;; acceleration are independent. Enabling this setting will emulate QMK mouse
  ;; move acceleration behavior, i.e. the acceleration state of new mouse
  ;; movement actions are inherited if others are already being pressed.
  ;;
  ;; movemouse-inherit-accel-state yes

  ;; This config entry alters the behavior of movemouseaccel actions.
  ;; This makes diagonal movements simultaneous to mitigate choppiness in
  ;; drawing apps, if you're using kanata mouse movements to draw for
  ;; whatever reason.
  ;;
  ;; movemouse-smooth-diagonals yes

  ;; This configuration allows you to customize the length limit on dynamic macros.
  ;; The default limit is 128 keys.
  ;;
  ;; dynamic-macro-max-presses 1000

  ;; This configuration makes multiple tap-hold actions that are activated near
  ;; in time expire their timeout quicker. Without this, the timeout for the 2nd
  ;; tap-hold onwards will start from 0ms after the previous tap-hold expires.
  ;;
  concurrent-tap-hold yes

  ;; This configuration makes the release of one-shot-press and of the tap in a tap-hold
  ;; by the defined number of milliseconds (approximate).
  ;; The default value is 5.
  ;; While the release is delayed, further processing of inputs is also paused.
  ;; This means that there will be a minor input latency impact in the mentioned scenarios.
  ;; The reason for this configuration existing is that some environments
  ;; do not process the scenarios correctly due to the rapidity of the release.
  ;; Kanata does send the events in the correct order,
  ;; so the fault is more in the environment, but kanata provides a workaround anyway.
  rapid-event-delay 5

  ;; This setting defaults to yes but can be configured to no to save on
  ;; logging. However, if --log-layer-changes is passed as a command line
  ;; argument, a "no" in the configuration file will be overridden and layer
  ;; changes will be logged.
  ;;
  ;; log-layer-changes no

  ;; This configuration will press and then immediately release the non-modifier key
  ;; as soon as the override activates, meaning you are unlikely as a human to ever
  ;; release modifiers first, which can result in unintended behaviour.
  ;;
  ;; The downside of this configuration is that the non-modifier key
  ;; does not remain held which is important to consider for your use cases.
  override-release-on-activation yes

  ;; Accepts a single key name.
  ;; When configured, whenever a mouse cursor movement is received,
  ;; the configured key name will be "tapped" by Kanata, activating
  ;; the key's action.
  ;;
  ;; This enables reporting of every relative mouse movement, which
  ;; corresponds to standard mice, trackballs, trackpads and
  ;; trackpoints. Absolute movements, which can be generated by
  ;; touchscreens, drawing tablets and some mouse replacement or
  ;; accessibility software, are ignored. Scrolling events and mouse
  ;; buttons are also ignored.
  ;;
  ;; The intended use of these events is to provide a way to
  ;; automatically enable a mouse keys layer while mousing, which can
  ;; be disabled by a timeout or typing on other keys, rather than
  ;; explicit toggling. see cfg_examples/automousekeys-*.kbd for more.
  ;;
  ;; The `mvmt` key name is specially intended for this purpose. It
  ;; has no output key mapping and cannot be supplied as an action;
  ;; however, any key may be used.
  ;;
  ;; Supports live reload on Linux, but with Windows-interception,
  ;; this option must be present on startup to enable mouse movement
  ;; event collection, so restart is required to enable it. Changing
  ;; the key name is always supported, however.
  ;;
  ;; mouse-movement-key mvmt
)

;; deflocalkeys-* enables you to define and use key names that match your locale
;; by defining OS code number mappings for that character.
;;
;; There are five variants of deflocalkeys-*:
;; - deflocalkeys-win
;; - deflocalkeys-winiov2
;; - deflocalkeys-wintercept
;; - deflocalkeys-linux
;; - deflocalkeys-macos
;;
;; Only one of each deflocalkeys-* variant is allowed. The variants that are
;; not applicable will be ignored, e.g. deflocalkeys-linux and deflocalkeys-wintercept
;; are both ignored when using the default Windows kanata binary.
;;
;; The configuration item is parsed similarly to defcfg; it is composed of
;; pairs of keys and values.
;;
;; You can check docs/locales.adoc for the mapping for your locale. If your
;; locale is not there, please ask for help if needed, and add the mapping for
;; your locale to the document.
;;
;; Web link for locales: https://github.com/jtroo/kanata/blob/main/docs/locales.adoc
;;
;; This example is for an Italian keyboard remapping in Linux. The numbers will
;; unfortunately differ between Linux, Windows-hooks, and Windows-interception.
;;
;; To see how you can discover key mappings for yourself, see the "Non-US keyboards"
;; section of docs/config.adoc.
;;
;; Web link or config: https://github.com/jtroo/kanata/blob/main/docs/config.adoc

(deflocalkeys-win
  ì 187
)

(deflocalkeys-wintercept
  ì 187
)

(deflocalkeys-winiov2
  ì 187
)

(deflocalkeys-linux
  ì 13
)

(deflocalkeys-macos
  ì 13
)

;; Only one defsrc is allowed.
;;
;; defsrc defines the keys that will be intercepted by kanata. The order of the
;; keys matches the deflayer declarations and all deflayer declarations must
;; have the same number of keys as defsrc.
;;
;; The visual/spatial positioning is *not* mandatory; it is done by convention
;; for visual ease. These items are parsed as a long list with newlines being
;; ignored.
;;
;; If you are looking for other keys, the file src/keys/mod.rs should hopefully
;; provide some insight.
(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

;; The first layer defined is the layer that will be active by default when
;; kanata starts up. This layer is the standard QWERTY layout except for the
;; backtick/grave key (@grl) which is an alias for a tap-hold key.
(deflayer qwerty
  @grl 1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

;; The dvorak layer remaps the keys to the dvorak layout. There are several
;; tap-hold aliases configured on the left side.
(deflayer dvorak
  @grl 1    2    3    4    5    6    7    8    9    0    [    ]    bspc
  tab  '    ,    @.ms p    y    f    g    c    r    l    /    =    \
  @cap @anm @oar @ech @umc @ifk d    h    t    n    s    -    ret
  lsft ;    q    j    k    x    b    m    w    v    z    rsft
  lctl lmet lalt           spc           @ralt rmet @rcl
)

;; This is an alternative to deflayer and does not rely on defsrc.
;; It has the advantage of simpler config if only remapping a few keys.
;; You might still prefer the standard deflayer for its visual printing in
;; the log as you are learning a new configuration.
(deflayermap (custom-map-example)
  caps esc
  esc  caps

  ;; You can use _ , __ or ___ instead of specifying a key name to map all
  ;; keys that are not explicitly mapped in the layer.
  ;; E.g. esc and caps above will not be overwritten.
  ;;
  ;; _    maps only keys that are in defsrc.
  ;; __   excludes mapping keys that are in defsrc.
  ;; ___  maps both, keys that are in `defsrc`, and keys that are not.
  ;;
  ;; The two- and three-underscore variants require
  ;; "process-unmapped-keys yes" in defcfg to work.

  ;; ___ XX ;; maps all keys that are not mapped explicitly in the layer
  ;;          ;; (i.e. esc and caps above) to "no-op" to disable the key.
  _ XX   ;; maps all keys that are in defsrc and are not mapped in the layer
  __ XX  ;; maps all keys that are NOT in defsrc and are not mapped in the layer
)

;; defvar can be used to declare commonly-used values
(defvar
  tap-repress-timeout   100
  hold-timeout          200
  tt $tap-repress-timeout
  ht $hold-timeout

  ;; A list value in defvar that begins with concat behaves in a special manner
  ;; where strings will be joined together.
  ;;
  ;; Below results in 100200
  a "hello"
  b "world"
  ct (concat $a " " $b)
)

(defalias
  th1 (tap-hold $tt $ht caps lctl)
  th2 (tap-hold $tt $ht spc lsft)
)

;; defalias is used to declare a shortcut for a more complicated action to keep
;; the deflayer declarations clean and aligned. The alignment in deflayers is not
;; necessary, but is strongly recommended for ease of understanding visually.
;;
;; Aliases are referred to by `@<alias_name>`. Aliases can refer to each other,
;; e.g. in the `anm` alias. However, an alias can only refer to another alias
;; that has been defined before it in the file.
(defalias
  ;; aliases to change the base layer to qwerty or dvorak
  dvk (layer-switch dvorak)
  qwr (layer-switch qwerty)

  ;; Aliases for layer "toggling". It's not quite toggling because the layer
  ;; will be active while the key is held and deactivated when the key is
  ;; released. An alternate action name you can use is layer-while-held.
  ;; However, the rest of this document will use The term "toggle" for brevity.
  num (layer-toggle numbers)
  chr (layer-toggle chords)
  arr (layer-toggle arrows)
  msc (layer-toggle misc)
  lay (layer-toggle layers)
  mse (layer-toggle mouse)
  fks (layer-while-held fakekeys)

  ;; tap-hold aliases with tap for dvorak key, and hold for toggle layers
  ;; WARNING(Linux only): key repeat with tap-hold can behave unexpectedly.
  ;; For full context, see https://github.com/jtroo/kanata/discussions/422
  ;;
  ;; tap-hold parameter order:
  ;; 1. tap repress timeout
  ;; 2. hold timeout
  ;; 3. tap action
  ;; 4. hold action
  ;;
  ;; The hold timeout is the number of milliseconds after which the hold action
  ;; will activate.
  ;;
  ;; The tap repress timeout is best explained in a roundabout way. When you press and
  ;; hold a standard key on your keyboard (e.g. 'a'), your operating system will
  ;; read that and keep sending 'a' to the active application. To be able to
  ;; replicate this behaviour with a tap-hold key, you must press-release-press
  ;; the key within the tap repress timeout window (number is milliseconds). Simply
  ;; holding the key results in the hold action activating, which is why you
  ;; need to double-press for the tap action to stay pressed.
  ;;
  ;; There are two additional versions of tap-hold available:
  ;; 1. tap-hold-press: if there is a key press, the hold action is activated
  ;; 2. tap-hold-release: if there is a press and release of another key, the
  ;; hold action is activated
  ;;
  ;; These versions are useful if you don't want to wait for the whole hold
  ;; timeout to activate, but want to activate the hold action immediately
  ;; based on the next key press or press and release of another key. These
  ;; versions might be great to implement home row mods.
  ;;
  ;; If you come from kmonad, tap-hold-press and tap-hold-release are similar
  ;; to tap-hold-next and tap-hold-next-release, respectively. If you know
  ;; the underlying keyberon crate, tap-hold-press is the HoldOnOtherKeyPress
  ;; and tap-hold-release is the PermissiveHold configuration.
  anm (tap-hold 200 200 a @num)   ;; tap: a      hold: numbers layer
  oar (tap-hold 200 200 o @arr)   ;; tap: o      hold: arrows layer
  ech (tap-hold 200 200 e @chr)   ;; tap: e      hold: chords layer
  umc (tap-hold 200 200 u @msc)   ;; tap: u      hold: misc layer
  grl (tap-hold 200 200 grv @lay) ;; tap: grave  hold: layers layer
  .ms (tap-hold 200 200 . @mse)   ;; tap: .      hold: mouse layer
  ifk (tap-hold 200 200 i @fks)   ;; tap: i      hold: fake keys layer

  ;; There are additional variants of tap-hold-press and tap-hold-release that
  ;; activate the timeout action (the 5th parameter) when the action times out
  ;; as opposed to the hold action being activated by other keys.

  ;; tap: o    hold: arrows layer    timeout: backspace
  oat (tap-hold-press-timeout   200 200 o @arr bspc)
  ;; tap: e    hold: chords layer    timeout: esc
  ect (tap-hold-release-timeout 200 200 e @chr esc)
  ;; If you add reset-timeout-on-press to tap-hold-release-timeout,
  ;; the timeout will reset on a press to give you more time to release
  ;; a key to activate the hold.
  ect2 (tap-hold-release-timeout 200 200 e @chr esc reset-timeout-on-press)

  ;; There is another variant of `tap-hold-release` that takes a 5th parameter
  ;; that is a list of keys that will trigger an early tap when pressed.

  ;; tap: u    hold: misc layer      early tap if any of: (a o e) are pressed
  umk (tap-hold-release-keys 200 200 u @msc (a o e))

  ;; A variant of tap-hold-release-keys accepts another parameter,
  ;; which is a list of keys that activates the tap
  ;; on a press->release of a listed key.
  umk2 (tap-hold-release-tap-keys-release 200 200 u @msc (a o e) (' , .))

  ;; tap: u    hold: misc layer      always tap if any of: (a o e) are pressed
  uek (tap-hold-except-keys 200 200 u @msc (a o e))

  ;; tap: u    hold: misc layer      early tap if any of: (a o e) are pressed
  ;; Unlike tap-hold-release-keys, other keys do NOT trigger early hold.
  ;; This is useful for home row mods where fast typing should not trigger modifiers.
  utk (tap-hold-tap-keys 200 200 u @msc (a o e))

  ;; tap-hold-order resolves by release order instead of timeout.
  ;; tap: a    hold: lctl    buffer: 50ms (fast typing grace period)
  aor (tap-hold-order 200 50 a lctl)

  ;; tap for capslk, hold for lctl
  cap (tap-hold 200 200 caps lctl)

  ;; Below is an alias for the `multi` action which executes multiple actions
  ;; in order but at the same time.
  ;;
  ;; It may result in some incorrect/unexpected behaviour if combining complex
  ;; actions, so be reasonable with it. One reasonable use case is this alias:
  ;; press right-alt while also toggling to the `ralted` layer. The utility of
  ;; this is better revealed if you go see `ralted` and its aliases.
  ralt (multi ralt (layer-toggle ralted))
)

;; Wrapping a top-level configuration item in a list beginning with
;; (environment (env-var-name env-var-value) ...configuration...)
;; will make the configuration only active if the environment variable matches.
(environment (LAPTOP lp1)
  (defalias met @lp1met)
)

(environment (LAPTOP lp2)
  (defalias met @lp2met)
)

;; NOTE: the configuration below is an older and less general variant
;; of the environment configuration above.
;;
;; The defaliasenvcond variant of defalias is parsed similarly, but there must
;; be a list parameter first. The list must contain two strings. In order,
;; these strings are: an environment variable name, and the environment
;; variable value. When the environment variable defined by name has the
;; corresponding value when running kanata, the aliases within will be active.
;; Otherwise, the aliases will be skipped.
(defaliasenvcond (LAPTOP lp1)
  met @lp1met
)

(defaliasenvcond (LAPTOP lp2)
  met @lp2met
)

(defalias
  ;; shifted keys
  { S-[
  } S-]
  : S-;

  ;; alias numbers as themselves for use in macro
  8 8
  0 0
)

(defalias
  ;; For the multi action, all keys are pressed for the whole sequence
  ;; but still in the listed order which may be undesirable, particularly
  ;; for modifiers like shift. You probably want to use macro instead.
  ;;
  ;; Chording can be more succinctly described by the modifier prefixes
  ;; `C-`, `A-`, `S-`, and `M-` for lctrl, lalt, lshift, lmeta, but are possible
  ;; by using `multi` as well. The lmeta key is also known by some other
  ;; names: "Windows", "GUI", "Command", "Super".
  ;;
  ;; For ralt/altgr, you can use either of: `RA-` or `AG-`. They both work the
  ;; same and only one is allowed in a single chord. This chord can be useful for
  ;; international layouts.
  ;;
  ;; A special behaviour of output chords is that if another key is pressed,
  ;; all of the chord keys will be released. For the explanation about why
  ;; this is the case, see the configuration guide.
  ;;
  ;; This use case for multi is typing an all-caps string.
  alp (multi lsft a b c d e f g h i j k l m n o p q r s t u v w x y z)

  ;; Within multi you can also include reverse-release-order to release keys
  ;; from last-to-first order instead of first-to-last which is the default.
  S-a-reversed (multi lsft a reverse-release-order)

  ;; Chords using the shortcut syntax. These ones are used for copying/pasting
  ;; from some Linux terminals.
  csv C-S-v
  csc C-S-c

  ;; Windows shortcut for displaying all windows
  win M-tab

  ;; Accented e characters for France layout using altgr sequence. Showcases
  ;; both of the shortcuts. You can just use one version of shortcut at your
  ;; preference.
  é AG-2
  è RA-7
  testmacro (macro AG-2 RA-7)
  🙃 (unicode 🙃)

  ;; macro accepts keys, chords, and numbers (a delay in ms). Note that numbers
  ;; will be parsed as delays, so they will need to be aliased to be used.
  lch (macro h t t p @: / / 100 l o c a l h o s t @: @8 @0 @8 @0)
  tbm (macro A-(tab 200 tab 200 tab) 200 S-A-(tab 200 tab 200 tab))
  hpy (macro S-i spc a m spc S-(h a p p y) spc m y S-f r S-i e S-n d @🙃)

  rls (macro-release-cancel Digit1 500 bspc S-1 500 bspc S-2)
  cop (macro-cancel-on-press Digit1 500 bspc S-1 500 bspc S-2)
  rlpr (macro-release-cancel-and-cancel-on-press Digit1 500 bspc S-1 500 bspc S-2)

  ;; repeat variants will repeat while held, once ALL macros have ended,
  ;; including the held macro.
  mr1 (macro-repeat mltp)
  mr2 (macro-repeat-release-cancel mltp)
  mr3 (macro-repeat-cancel-on-press mltp)
  mr4 (macro-repeat-release-cancel-and-cancel-on-press mltp)

  ;; Kanata also supports dynamic macros. Dynamic macros can be nested, but
  ;; cannot recurse.
  dms dynamic-macro-record-stop
  dst (dynamic-macro-record-stop-truncate 3)
  dr0 (dynamic-macro-record 0)
  dr1 (dynamic-macro-record 1)
  dr2 (dynamic-macro-record 2)
  dp0 (dynamic-macro-play 0)
  dp1 (dynamic-macro-play 1)
  dp2 (dynamic-macro-play 2)

  ;; unmod will release all modifiers temporarily and send the .
  ;; So for example holding shift and tapping a @um1 key will still output 1.
  um1 (unmod 1)
  ;; dead keys é (as opposed to using AltGr) that outputs É when shifted
  dké (macro (unmod ') e)

  ;; unshift is like unmod but only releases shifts
  ;; In ISO German QWERTZ, force unshifted symbols even if shift is held
  de{ (unshift ralt 7)
  de[ (unshift ralt 8)

  ;; unmod can optionally take a list as the first parameter,
  ;; and then will only temporarily remove
  ;; the listed modifiers instead of all modifiers.
  unalt-a (unmod (lalt ralt) a)

  ;; unicode accepts a single unicode character. The unicode character will
  ;; not be automatically repeated by holding the key down. The alias name
  ;; is the unicode character itself and is referenced by @🙁 in deflayer.
  🙁 (unicode 🙁)

  ;; You may output parentheses or double quotes using unicode
  ;; by quotes as well as special quoting syntax.
  lp1 (unicode r#"("#)
  rp1 (unicode r#")"#)
  dq (unicode r#"""#)
  lp2 (unicode "(")
  rp2 (unicode ")")

  ;; fork accepts two actions and a key list. The first (left) action will
  ;; activate by default. The second (right) action will activate if any of
  ;; the keys in the third parameter (right-trigger-keys) are currently active.
  frk (fork @🙃 @🙁 (lsft rsft))

  ;; switch accepts triples of keys check, action, and fallthrough|break.
  ;; The default usage of keys check behaves similarly to fork.
  ;; However, it also accepts boolean operators and|or to allow more
  ;; complex use cases.
  ;;
  ;; The order of cases matters. If two different cases match the
  ;; currently pressed keys, the case listed earlier in the configuration
  ;; will activate first. If the early case uses break, the second case will
  ;; not activate at all. Otherwise if fallthrough is used, the second case
  ;; will also activate sequentially after the first case.
  swt (switch

    ;; translating this keys check to some other common languages
    ;; this might look like:
    ;;
    ;;    (a && b && (c || d) && (e || f))
    ((and a b (or c d) (or e f))) a break

    ;; this case behaves like fork, i.e.
    ;;
    ;;    (or a b c)
    ;;
    ;; or for some other common languages:
    ;;
    ;;    a || b || c
    (a b c) b fallthrough

    ;; key-history evaluates to true if the n'th most recent typed key,
    ;; {n | n ∈ [1, 8]}, matches the given key.
    ((key-history a 1) (key-history b 8)) c break

    ;; key-timing evaluates to true if the n'th most recent typed key,
    ;; {n | n ∈ [1, 8]}, was typed at a time less-than/greater-than the
    ;; given number of milliseconds.
    ((key-timing 1 lt 3000)       (key-timing 2 gt 30000)        ) c break
    ((key-timing 7 less-than 200) (key-timing 8 greater-than 500)) c break

    ;; not means "not any of the list constituents".
    ;; The example below behaves like:
    ;;
    ;;    !(a || b || c)
    ;;
    ;; and is equivalent to:
    ;;
    ;;    ((not (or a b c)))
    ((not a b c)) c break

    ;; input logic
    ((input real lctl)) d break
    ((input virtual sft)) e break
    ((input-history real lsft 2)) f break
    ((input-history virtual ctl 2)) g break

    ;; layer evaluates to `true` if the active layer matches the given name
    ((layer dvorak)) x break
    ((layer qwerty)) y break

    ;; base-layer evaluates to `true` if the base layer matches the given name
    ;; The base layer is the most recent target of layer-switch.
    ;; The base layer is not always the active layer.
    ((base-layer dvorak)) x break
    ((base-layer qwerty)) y break

    ;; default case, empty list always evaluates to true.
    ;; break vs. fallthrough doesn't matter here
    () c break
  )

  ;; Having a cmd action in your configuration without explicitly enabling
  ;; `danger-enable-cmd` **and** using the cmd-enabled executable will make
  ;; kanata refuse to load your configuration. The aliases below are commented
  ;; out since commands aren't allowed by this configuration file.
  ;;
  ;; Note that the parameters to `cmd` are executed directly as opposed to
  ;; passed to a shell. So for example, `~` and `$HOME` would not refer
  ;; to your home directory on Linux.
  ;;
  ;; You can use:
  ;; `cmd bash -c "your_stuff_here"` to run your command inside of bash.
  ;;
  ;; cm1 (cmd bash -c "echo hello world")
  ;; cm2 (cmd rm -fr /tmp/testing)

  ;; One variant of `cmd` is `cmd-log`, which lets you control how
  ;; running command, stdout, stderr, and execution failure are logged.
  ;;
  ;; The command takes two extra arguments at the beginning `<log_level>`,
  ;; and `<error_log_level>`. `<log_level>` controls where the name
  ;; of the command is logged, as well as the success message and command
  ;; stdout and stderr.
  ;;
  ;; `<error_log_level>` is only used if there is a failure executing the initial
  ;; command. This can be if there is trouble spawning the command, or
  ;; the command is not found. This means if you use `bash -c "thisisntacommand"`, as
  ;; long as bash starts up correctly, nothing would be logged to this channel, but
  ;; something like `thisisntacommand` would be.
  ;;
  ;; The log level can be `debug`, `info`, `warn`, `error`, or `none`.
  ;;
  ;; cmd-log info error bash -c "echo these are the default levels"
  ;; cmd-log none none bash -c "echo nothing back in kanata logs"
  ;; cmd-log none error bash -c "only if command fails"
  ;; cmd-log debug debug bash -c "echo log, but require changing verbosity levels"
  ;; cmd-log warn warn bash -c "echo this probably isn't helpful"

  ;; Another variant of `cmd` is `cmd-output-keys`. This reads the output
  ;; of the command and treats it as an S-Expression, similarly to `macro`.
  ;; However, only delays, keys, chords, and chorded lists are supported.
  ;; Other actions are not.
  ;;
  ;; bash: type date-time as YYYY-MM-DD HH:MM
  ;; cmd-output-keys bash -c "date +'%F %R' | sed 's/./& /g' | sed 's/:/S-;/g' | sed 's/\(.\{20\}\)\(.*\)/\(\1 spc \2\)/'"
)

;; The underscore _ means transparent. The key on the base layer will be used
;; instead. XX means no-op. The key will do nothing.
;;
;; A similar concept to transparent, use-defsrc means the key will always
;; behave as the key as defined by defsrc.
(defalias src use-defsrc)
(deflayer numbers
  @src _    _    _    _    _    nlk  kp7  kp8  kp9  _    _    _    _
  _    _    _    _    _    XX   _    kp4  kp5  kp6  -    _    _    _
  _    _    C-z  _    _    XX   _    kp1  kp2  kp3  +    _    _
  _    C-z  C-x  C-c  C-v  XX   _    kp0  kp0  .    /    _
  _    _    _              _              _    _    _
)

;; The `lrld` action stands for "live reload".
;;
;; NOTE: live reload does not read changes to device-related configurations,
;; such as `linux-dev`, `macos-dev-names-include`,
;; or `windows-only-windows-interception-keyboard-hwids`.
;;
;; The variants `lrpv` and `lrnx` will cycle between multiple configuration files
;; if they are specified in the startup arguments.
;; The list action variant `lrld-num` takes a number parameter and
;; reloads the configuration file specified by the number, according to the
;; order passed into the arguments on kanata startup.
;;
;; Upon a successful reload, the kanata state will begin on the default base layer
;; in the configuration. E.g. in this example configuration, you would start on
;; the qwerty layer.
(deflayer layers
  _    @qwr @dvk lrld lrpv lrnx (lrld-num 1) _ _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

(defalias

  ;; Alias for one-shot which will activate an action until either the timeout
  ;; expires or a different key is pressed. The timeout is the first parameter
  ;; and the action is the second parameter.
  ;;
  ;; The intended use cases are pressing a modifier for exactly one key or
  ;; switching to another layer for exactly one key.
  ;;
  ;; If a one-shot key is held then it will act as a regular key. E.g. for os1
  ;; below, holding an @os1 key will keep lsft held and holding an @os3 key
  ;; will keep the layer set to misc.
  os1 (one-shot 500 lsft)
  os2 (one-shot 500 C-S-lalt)
  os3 (one-shot 500 (layer-toggle misc))

  ;; Another name for one-shot is one-shot-press, since it ends on the first
  ;; press of another key.
  ;;
  ;; There is another variant one-shot-release which ends on the first release
  ;; of another key.
  ;;
  ;; There are further variants of both of these:
  ;; - one-shot-press-pcancel
  ;; - one-shot-release-pcancel
  ;;
  ;; These will cancel the one-shot action and all other active one-shot actions
  ;; if a one-shot key is repressed while already active.
  osp (one-shot-press 500 lsft)
  osr (one-shot-release 500 lsft)
  opp (one-shot-press-pcancel 500 lsft)
  orp (one-shot-release-pcancel 500 lsft)

  ;; one-shot-pause-processing can be useful in some cases
  ;; to preserve an activated one-shot state when it otherwise
  ;; would get deactivated by some action that isn't intended
  ;; to consume the one-shot.
  ;; The unit is number of milliseconds.
  ops (one-shot-pause-processing 5)

  ;; Alias for tap-dance which will activate one of the actions in the action
  ;; list depending on how many taps were done. Tapping once will output the
  ;; first action and tapping N times will output the N'th action.
  ;;
  ;; The first parameter is a timeout. Tapping the same tap-dance key again
  ;; within the timeout will reset the timeout and advance the tap-dance to the
  ;; next key.
  ;;
  ;; The action activates either when any of the following happens:
  ;; - the timeout expires
  ;; - the tap sequence reaches the end
  ;; - a different key is pressed
  td (tap-dance 200 (a b c d spc))

  ;; There is a variant of tap-dance — tap-dance-eager — that will activate
  ;; every action tapped in the sequence rather than a single one. The example
  ;; below is rather simple and behaves similarly to the original tap-dance.
  td2 (tap-dance-eager 500 (
    (macro a) ;; use macro to prevent auto-repeat of the key
    (macro bspc b b)
    (macro bspc bspc c c c)
  ))

  ;; arbitrary-code allows sending an arbitrary number as an OS code. This is
  ;; not cross platform! This can be useful for testing keys that are not yet
  ;; named or mapped in kanata. Please contribute findings with names and/order
  ;; mappings, either in a GitHub issue or as a pull request! This is currently
  ;; not supported with Windows using the interception driver.
  ab1 (arbitrary-code 700)
)

(defalias
  ;; caps-word will add an lsft to the active key list for all alphanumeric keys
  ;; a-z, and the US layout minus key; meaning it will be converted to an
  ;; underscore.
  ;;
  ;; The caps-word state will also be cleared if any key that doesn't get auto-
  ;; capitalized and also doesn't belong in this list is pressed:
  ;; - 0-9
  ;; - kp0-kp9
  ;; - bspc, del
  ;; - up, down, left, rght
  ;;
  ;; The single parameter is a timeout in milliseconds after which the caps-word
  ;; state will be cleared and lsft will not be added anymore. The timer is reset
  ;; any time a capitalizable or extra non-terminating key is active.
  cw (caps-word 2000)

  ;; Like caps-word, but you get to choose the key lists where lsft gets added.
  ;; This example is similar to the default caps-word behaviour but it moves the
  ;; 0-9 keys to capitalized key list from the extra non-terminating key list.
  cwc (caps-word-custom
    2000
    (a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9)
    (kp0 kp1 kp2 kp3 kp4 kp5 kp6 kp7 kp8 kp9 bspc del up down left rght)
  )
)

;; -toggle variants of caps-word will terminate caps-word on repress if it is
;; currently active, otherwise caps-word will be activated.
(defalias
  cwt (caps-word-toggle 2000)
  cct (caps-word-custom-toggle
    2000
    (a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9)
    (kp0 kp1 kp2 kp3 kp4 kp5 kp6 kp7 kp8 kp9 bspc del up down left rght)
  )
)

;; Can see a new action `rpt` in this layer. This repeats the most recently
;; pressed key. Holding down the `rpt` key will not repeatedly send the key.
;; The intended use case is to be able to use a different finger to repeat a
;; double letter, as opposed to double-tapping a letter.
;;
;; The `rpt` action only repeats the last key output. For example, it won't
;; output a chord like `ctrl+c` if the previous key pressed was `C-c` - it
;; will only output `c`. There is a variant `rpt-any` which will repeat the
;; previous action and would work for that use case.
(deflayer misc
  _    _    _    _    _    _    _    _    _    @é   @è   _    ì #|random custom key for testing|#   _
  _    _    @ab1 _    _    _    ins  @{   @}   [    ]    _    _    +
  @cw  _    _    _    C-u  _    del  bspc esc  ret  _    _    _
  @cwc C-z  C-x  C-c  C-v  _    _    _    @td  @os1 @os2 @os3
  rpt rpt-any _            _              _    _    _
)


(deflayer chords      ;; you can put list actions directly in deflayer but it's ugly, so prefer aliases.
  _    _    _    _    _    _    _    _    _    _    @🙁  (unicode 😀) _    _
  _    _    _    _    _    _    _    _    @csc @hpy @lch @tbm         _    _
  _    @alp _    _    _    _    _    @ch1 @ch2 @ch4 @ch8 _            _
  _    _    _    _    _    _    _    _    _    @csv _    _
  _    _    _              _              _    _    _
)

(deflayer arrows
  _    f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12  _
  _    _    _    _    _    _    _    pgup up   pgdn _    _    _    _
  _    _    _    _    _    _    home left down rght end  _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

;; In Windows, using mouse buttons on the kanata window seems to cause it to hang.
;; Using the mouse on other windows seems to be fine though.
;;
;; The mouse buttons can be clicked using mlft, mrgt, mmid, mfwd and mbck, representing the
;; left, right, middle, forward and backward mouse buttons respectively. If the key is held, the
;; button press will also be held.
;;
;; If there are multiple mouse click actions within a single multi action, e.g.
;; (multi mrgt mlft), then all the buttons except the last will be clicked then
;; unclicked. The last button will remain held until key release. In the example
;; given, the button sequence will be:
;; press key->click right->unclick right->click left->release key->release left
;;
;; There are variants of the standard mouse buttons which "tap" the button.
;; These are mltp, mrtp, and mmtp. Rather than holding until key release, this
;; action will click and unclick the button once the key is pressed. Nothing
;; happens on key release. The action (multi lctl mltp) will result in the
;; sequence below:
;; press key->press lctl->click left->unclick left->release key->release lctl
;;
;; One can also see mouse movement actions at the lower right side, with the
;; arrow unicode characters.
(deflayer mouse
  _    @mwu @mwd @mwl @mwr _    _    _    _    _    @ma↑ _    _    _
  _    pgup bck  _    fwd  _    _    _    _    @ma← @ma↓ @ma→ _    _
  _    pgdn mlft _    mrgt mmid _    mbck mfwd _    @ms↑ _    _
  @fms _    mltp _    mrtp mmtp _    mbtp mftp @ms← @ms↓ @ms→
  _    _    _              _              _    _    _
)

(defalias
  ;; Mouse wheel actions. The first number is the interval in milliseconds
  ;; between scroll actions. The second number is the distance in some arbitrary
  ;; unit. Play with the parameters to see what feels correct. Both numbers
  ;; must be in the range 1-65535
  ;;
  ;; In both Windows and Linux, 120 distance units is equivalent to a single
  ;; notch movement on a physical wheel. In Linux, not all desktop environments
  ;; support the REL_WHEEL_HI_RES event so if you experience issues with `mwheel`
  ;; actions in Linux, using a distance value that is multiple of 120 may help.
  mwu (mwheel-up 50 120)
  mwd (mwheel-down 50 120)

  ;; Horizontal mouse wheel actions. Similar story to vertical mouse wheel.
  mwl (mwheel-left 50 120)
  mwr (mwheel-right 50 120)

  ;; There are similar wheel actions with `-accel` that have
  ;; accelerating/inertial scrolling.
  ;; The parameters are:
  ;; 1. initial velocity
  ;; 2. maximum velocity
  ;; 3. acceleration multiplier
  ;; 4. deceleration multiplier
  ;; The units are arbitrary.
  ;; The author finds the values in the example below
  ;; to be a decent-feeling starting paint.
  ;; Experiment to find your preference.
  mau (mwheel-accel-up   3 1200 1.15 0.93)
  mad (mwheel-accel-down 3 1200 1.15 0.93)

  ;; Mouse movement actions.The first number is the interval in milliseconds
  ;; between mouse actions. The second number is the distance traveled per interval
  ;; in pixels.

  ms↑ (movemouse-up 1 1)
  ms← (movemouse-left 1 1)
  ms↓ (movemouse-down 1 1)
  ms→ (movemouse-right 1 1)

  ;; Mouse movement actions with linear acceleration. The first number is the
  ;; interval in milliseconds between mouse actions. The second number is the time
  ;; in milliseconds for the distance to linearly ramp up from the minimum distance
  ;; to the maximum distance. The third number is the minimum distance traveled
  ;; per interval in pixels. The fourth number is the maximum distance traveled
  ;; per interval in pixels.

  ma↑ (movemouse-accel-up 1 1000 1 5)
  ma← (movemouse-accel-left 1 1000 1 5)
  ma↓ (movemouse-accel-down 1 1000 1 5)
  ma→ (movemouse-accel-right 1 1000 1 5)

  ;; setmouse places the cursor at a specific pixel x-y position. This
  ;; example puts it in the middle of the screen. The coordinates go from 0,0
  ;; which is the upper-left corner of the screen to 65535,65535 which is the
  ;; lower-right corner of the screen. If you have multiple monitors, they are
  ;; treated as one giant screen, which may make it a bit confusing for how to
  ;; set up the pixels. You will need to experiment.
  sm (setmouse 32228 32228)

  ;; movemouse-speed takes a percentage by which it then scales all of the
  ;; mouse movements while held. You can have as many of these active at a
  ;; given time as you would like, but be warned that some values, such as 33
  ;; may not have correct pixel distance representations.
  fms (movemouse-speed 200)
)

(defalias
  lft (multi (release-key ralt) left) ;; release ralt if held and also press left
  rgt (multi (release-key ralt) rght) ;; release ralt if held and also press rght
  rlr (release-layer ralted)          ;; release layer-toggle of ralted
)

;; It's not clear what the practical use case is for the @rlr alias, but the
;; combination of @ralt on the dvorak layer and this layer with @lft and @rgt
;; results in the physical ralt key behaving mostly as ralt, **except** for
;; holding it **then** pressing specific keys. These specific keys release the
;; ralt because it would cause them to have undesired behaviour without the
;; release.
;;
;; E.g. ralt+@lft will result in only left being pressed instead of ralt+left,
;; while ralt(hold)+tab+tab+tab still works as intended.
(deflayer ralted
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    @lft @rlr @rgt _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

;; Virtual key actions

(defvirtualkeys
  ;; Define some virtual keys that perform modifier actions
  vkctl lctl
  vksft lsft
  vkmet lmet
  vkalt lalt

  ;; A virtual key that toggles all modifier virtual keys above
  vktal (multi
        (on-press toggle-virtualkey vkctl)
        (on-press toggle-virtualkey vksft)
        (on-press toggle-virtualkey vkmet)
        (on-press toggle-virtualkey vkalt)
      )

  ;; Virtual key that activates a macro
  vkmacro (macro h e l l o spc w o r l d)
)

(defalias
  psfvk (on-press press-virtualkey   vksft)
  rsfvk (on-press release-virtualkey vksft)

  palvk (on-press tap-vkey vktal)
  macvk (on-press tap-vkey vkmacro)

  isfvk (on-idle 1000 tap-vkey vksft)
  pisfvk (on-physical-idle 1000 tap-vkey vksft)
)

;; Press and release fake keys.
;;
;; Fake keys can't be pressed by any physical keyboard buttons and can only be
;; acted upon by the actions:
;; - on-press-fakekey
;; - on-release-fakekey
;; - on-idle-fakekey
;;
;; One use case of fake keys is for holding modifier keys
;; for any number of keypresses and then releasing the modifiers when desired.
;;
;; The actions associated with fake keys in deffakekeys are parsed before
;; aliases, so you can't use aliases within deffakekeys. Other than the lack
;; of alias support, fake keys can do any action that a normal key can,
;; including doing operations on previously defined fake keys.
;;
;; Operations on fake keys can occur either on press (on-press-fakekey),
;; on release (on-release-fakekey), or on idle for a specified time
;; (on-idle-fakekey).
;;
;; Fake keys are flexible in usage but can be obscure to discover how they
;; can be useful to you.
(deflayer fakekeys
  _    @fcp @fsp @fmp @pal _    _    _    _    _    _    _    _    _
  _    @fcr @fsr @fap @ral _    _    _    _    _    _    _    _    _
  _    @fct @fst @rma _    _    _    _    _    _    _    _    _
  _    @t1  _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

(deffakekeys
  ctl lctl
  sft lsft
  lsft lsft
  met lmet
  alt lalt
  mmid mmid
  pal (multi
        (on-press-fakekey ctl press)
        (on-press-fakekey sft press)
        (on-press-fakekey met press)
        (on-press-fakekey alt press)
      )
  ral (multi
        (on-press-fakekey ctl release)
        (on-press-fakekey sft release)
        (on-press-fakekey met release)
        (on-press-fakekey alt release)
      )
)

(defalias
  fcp (on-press-fakekey ctl press)
  fcr (on-press-fakekey ctl release)
  fct (on-press-fakekey ctl tap)
  fsp (on-release-fakekey sft press)
  fsr (on-release-fakekey sft release)
  fst (on-release-fakekey sft tap)
  fsg (on-release-fakekey sft toggle)
  fmp (on-press-fakekey met press)
  fap (on-press-fakekey alt press)
  rma (multi
        (on-press-fakekey met release)
        (on-press-fakekey alt release)
      )
  pal (on-press-fakekey pal tap)
  ral (on-press-fakekey ral tap)
  rdl (on-idle-fakekey ral tap 1000)
  hfd (hold-for-duration 1000 met)

  ;; Test of on-press-fakekey and on-release-fakekey in a macro
  t1 (macro-release-cancel @fsp 5 a b c @fsr 5 c b a)

  ;; If you find that an application isn't registering keypresses correctly
  ;; with multi, you can try out:
  ;; - on-press-fakekey-delay
  ;; - on-release-fakekey-delay
  ;;
  ;; Do note that processing a fakekey-delay and even a sequence of delays will
  ;; delay any other inputs from being processed until the fakekey-delays are
  ;; all complete, so use with care.
  stm (multi ;; Shift -> middle mouse with a delay
    (on-press-fakekey lsft press)
    (on-press-fakekey-delay 200)
    (on-press-fakekey mmid press)
    (on-release-fakekey mmid release)
    (on-release-fakekey-delay 200)
    (on-release-fakekey lsft release)
  )
)

;; Vim-style leader-key sequences. Activate a fakekey-tap by pressing a "leader"
;; key and then a sequence of characters.
;; See: https://github.com/jtroo/kanata/issues/97
;;
;; You can add an entry to defcfg to change the sequence timeout (default is 1000):
;;     sequence-timeout <number(ms)>
;;
;; If you want multiple timeouts with different leaders, you can also activate the
;; sequence action:
;;     (sequence <timeout>)
;; This acts like `sldr` but uses a different timeout.
;;
;; There is also an option to customize the key sequence input mode. Its default
;; value when not configured is `hidden-suppressed`.
;;
;; The options are:
;;
;; - `visible-backspaced`: types sequence characters as they are inputted. The
;;   typed characters will be erased with backspaces for a valid sequence termination.
;; - `hidden-suppressed`: hides sequence characters as they are typed. Does not
;;   output the hidden characters for an invalid sequence termination.
;; - `hidden-delay-type`: hides sequence characters as they are typed. Outputs the
;;   hidden characters for an invalid sequence termination either after either a
;;   timeout or after a non-sequence key is typed.
;;
;; For `visible-backspaced` and `hidden-delay-type`, a sequence leader input will
;; be ignored if a sequence is already active. For historical reasons, and in case
;; it is desired behaviour, a sequence leader input using `hidden-suppressed` will
;; reset the key sequence.
;;
;; Example:
;;     sequence-input-mode visible-backspaced
(defseq git-status (g s t))
(deffakekeys git-status (macro g i t spc s t a t u s))
(defalias rcl (tap-hold-release 200 200 sldr rctl))

(defseq
    dotcom (. S-3)
    dotorg (. S-4)
)
(deffakekeys
    dotcom (macro . c o m)
    dotorg (macro . o r g)
)
;; Enter sequence mode and input .
(defalias dot-sequence (macro (sequence 250) 10 .))
(defalias dot-sequence-inputmode (macro (sequence 250 hidden-delay-type) 10 .))

;; There are special keys that you can assign in your actions which will
;; never output events to your operating system, but which you can use
;; in sequences. They are named: nop0-nop9.
(defseq
    dotcom (nop0 nop1)
    dotorg (nop8 nop9)
)

;; A key list within O-(...) signifies simultaneous presses.
(defseq
    dotcom (O-(. c m))
    dotorg (O-(. r g))
)

;; sequence-noerase
;;
;; When you have a keyboard locale that uses dead keys,
;; you may be pressing two keys that only actually output one symbol.
;; By default, when visible-backspaced does the backtracking backspace,
;; it backspaces according to input count.
;; With dead keys, this may result in too many backspaces.
;;
;; The sequence-noerase action is a no-output action
;; that tells the sequences action to have one fewer backspace
;; when backtracking with visible-backspaced.

(deflayermap (base)
  0 sldr
  u (t! maybe-noerase u)
)
(deftemplate maybe-noerase (char)
  (multi
    (switch
      ((key-history ' 1)) (sequence-noerase 1) fallthrough
      () $char break
   ))
)
(defvirtualkeys seq-output-1 (macro a b c d e f g))
(defseq seq-output-1 (' u))

;; Input chording.
;;
;; Not to be confused with output chords (like C-S-a or the chords layer
;; defined above), these allow you to perform actions when a combination of
;; input keys (a "chord") are pressed all at once (order does not matter).
;; Each combination/chord can perform a different action, allowing you to bind
;; up to `2^n - 1` different actions to just `n` keys.
;;
;; Each `defchords` defines a named group of such chord-action pairs.
;; The 500 is a timeout after which a chord triggers if it isn't triggered by a
;; key release or press of a non-chord key before the timeout expires.
;; If a chord is not defined, no action will occur when it is triggered but the
;; keys used to input it will be consumed regardless.
;;
;; Each pair consists of the keys that make up a given chord in the parenthesis
;; followed by the action that should be executed when the given chord is
;; pressed.
;; Note that these keys do not directly correspond to real keys and are merely
;; arbitrary labels that make sense within the context of the chord.
;; They are mapped to real keys in layers by configuring the key in the layer to
;; map to a `(chord name key)` action (like those in the `defalias` below) where
;; `name` is the name of the chords group (here `binary`) and `key` is one of the
;; arbitrary labels of the keys in a chord (here `1`, `2`, `4` and `8`).
;;
;; Note that it is perfectly valid to nest these `chord` actions that enter
;; "chording mode" within other actions like `tap-dance` and that will work as
;; one would expect.
;; However, this only applies to the first key used to enter "chording mode".
;; Once "chording mode" is active, all other keys will be directly handled by
;; "chording mode" with no regard for wrapper actions; e.g. if a key is pressed
;; and it maps to a tap-hold with a chord as the hold action within, that chord
;; key will immediately activate instead of the key needing to be held for the
;; timeout period.
;;
;; The action executed by a chord (the right side of the chord-action pairs) may
;; be any regular or advanced action, including aliases. They currently cannot
;; however contain a `chord` action.
(defchords binary 500
  (1      ) 1
  (  2    ) 2
  (1 2    ) 3
  (    4  ) 4
  (1   4  ) 5
  (  2 4  ) 6
  (1 2 4  ) 7
  (      8) 8
  (1     8) 9
  (  2   8) (multi 1 0)
  (1 2   8) (multi 1 1)
  (    4 8) (multi 1 2)
  (1   4 8) (multi 1 3)
  (  2 4 8) (multi 1 4)
  (1 2 4 8) (multi 1 5)
)

(defalias
  ch1 (chord binary 1)
  ch2 (chord binary 2)
  ch4 (chord binary 4)
  ch8 (chord binary 8)
)

;; The top-level action `include` will read a configuration from a new file.
;; At the time of writing, includes can only be placed at the top level. The
;; included files also cannot contain includes themselves.
;;
;; (include included-file.kbd)


;; The top-level item `deftemplate` declares a template
;; which can be expanded multiple times to reduce repetition.
;;
;; Expansion of a template is done via `expand-template`.

;; This template defines a chord group and aliases that use the chord group.
;; The purpose is to easily define the same chord position behaviour
;; for multiple layers that have different underlying keys.
(deftemplate left-hand-chords (chordgroupname k1 k2 k3 k4 alias1 alias2 alias3 alias4)
  (defalias
    $alias1 (chord $chordgroupname $k1)
    $alias2 (chord $chordgroupname $k2)
    $alias3 (chord $chordgroupname $k3)
    $alias4 (chord $chordgroupname $k4)
  )
  (defchords $chordgroupname $chord-timeout
    ($k1) $k1
    ($k2) $k2
    ($k3) $k3
    ($k4) $k4
    ($k1 $k2) lctl
    ($k3 $k4) lsft
  )
)

(defvar chord-timeout 200)

(template-expand left-hand-chords qwerty a s d f qwa qws qwd qwf)
;; You can use t! as a short form of template-expand
(t! left-hand-chords dvorak a o e u dva dvo dve dvu)

(deflayer template-example
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    @qwa @qws @qwd @qwf _    _    _    _    _    _    _    _    _
  _    @dva @dvo @dve @dvu _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

;; Within a deftemplate you can use if-equal to conditionally insert content
;; into the template.

(deftemplate home-row (version)
  a s d f g h
  (if-equal $version v1 j)
  (if-equal $version v2 (tap-hold 200 200 j lctl))
   k l ; '
)

(deftemplate common-overrides ()
  (lctl 7) (lctl lsft tab)
  (lctl 9) (lctl tab)
  (lalt 7) (lalt lsft tab)
  (lalt 9) (lalt tab)
)

;; Wrapping a top-level configuration item in a list beginning with
;; (platform (applicable-platforms...) ...configuration...)
;; will make the configuration only active on a specific platform.
(platform (macos)
  ;; Only on macos, use command arrows to jump/delete words
  ;; because command is used for so many other things
  ;; and it's weird that these cases use alt.
  (defoverrides
    (lmet bspc)  (lalt bspc)
    (lmet left)  (lalt left)
    (lmet right) (lalt right)
    (template-expand common-overrides)
  )
)
(platform (win winiov2 wintercept linux)
  (defoverrides
    (template-expand common-overrides)
  )
)

#|
There is a more recent version of defoverrides that offers more customizability.
Instead of 2 list items per override entry,
`defoverridesv2` mandates 4, though the extra 2 can be empty.

You cannot have both a v1 and v2 of `defoverrides` at the same time.

The 3rd item is an "exclude modifiers list" which is composed of modifier key names
(such as `lctl`, `lalt`) that, if held, will disable the override from activating.

The 4th item is an "exclude layers" list which is composed of layer names
that while active as the most recent `layer-switch` or `layer-while-held`,
will disable the override from activating.

(defoverridesv2
  ;; lctl+a will become lalt+9
  ;; except when lsft is held or other-layer is active.
  (lctl a) (lalt 9) (lsft) (other-layer))

  ;; lctl+b will always become lalt+0
  (lctl b) (lalt 0) () ()
)
|#

#|

Global input chords.

Syntax (5-tuples):

    (defchordsv2
      (participating-keys1) action1 timeout1 release-behaviour1 (disabled-layers1)
        ...
      (participating-keysN) actionN timeoutN release-behaviourN (disabled-layersN)
    )

|#

(defchordsv2
  (a b c)   (macro a l p h a b e t)  200 all-released  (qwerty arrows)
  (h l o)   (macro h e l l o)        250 first-release (qwerty arrows)
  (g b y e) (macro g o o d b y e)    400 first-release (qwerty arrows)
)

#|

Yet another chording implementation - zippychord:


;; This is a sample for US international layout.
(defzippy
  zippy.txt
  on-first-press-chord-deadline 500
  idle-reactivate-time          500
  smart-space-punctuation (? ! . , ; :)
  output-character-mappings (
    ! S-1
    ? S-/
    % S-5
    "(" S-9
    ")" S-0
    : S-;
    < S-,
    > S-.
    r#"""# S-'
    | S-\
    _ S--
    ® AG-r
    ;; In case you use dead keys or compose keys
    ;; where multiple keys are pressed
    ;; to produce a single backspaceable symbol,
    ;; use no-erase or single-output
    ’ (no-erase `)
    é (single-output ' e)
  )
)

Example file content of zippy.txt:
---
dy	day
dy 1	Monday
 abc	Alphabet
r df	recipient
 w  a	Washington
rq	request
rqa	request assistance
---

You can read about zippychord in more detail in the configuration guide.

|#

#|

Clipboard actions allow you to manipulate the clipboard.
To paste, you should manually output C-v,
or whatever key output is necessary to paste.
E.g. S-ins might also work.

|#

(deflayermap (clip)
 a (clipboard-set       clip)
 b (clipboard-save      0)
 c (clipboard-restore   0)
 d (clipboard-save-swap 0 65535)
 #| actions with cmd only works with the compilation flags and defcfg enablement.
 e (clipboard-cmd-set powershell.exe -c "echo 'hello world'")
 f (clipboard-save-cmd-set 0 bash -c "echo 'goodbye'")
 |#
)


================================================
FILE: cfg_samples/key-toggle_press-only_release-only.kbd
================================================
#|

This configuration showcases all of:
	- key toggle
	- press-only
	- release-only

|#

(deftemplate toggle-key (vkey-name output-key alias)
	(defvirtualkeys $vkey-name $output-key)
	(defalias $alias (on-press toggle-vkey $vkey-name))
)

(deftemplate press-only-release-only-pair
		(vkey-name output-key press-alias release-alias)
	(defvirtualkeys $vkey-name $output-key)
	(defalias $press-alias (on-press press-vkey $vkey-name))
	(defalias $release-alias (on-press release-vkey $vkey-name))
)

(template-expand toggle-key v-lctl lctl lcl)
(template-expand toggle-key v-rctl rctl rcl)

;; t! is a short form of template-expand
(t! press-only-release-only-pair v-lalt lalt p-a r-a)

(defsrc
	lctl rctl lalt ralt
)

(deflayer base
	@lcl @rcl @p-a @r-a
)


================================================
FILE: cfg_samples/minimal.kbd
================================================
#|
This minimal config changes Caps Lock to act as Caps Lock on quick tap, but
if held, it will act as Left Ctrl. It also changes the backtick/grave key to
act as backtick/grave on quick tap, but change ijkl keys to arrow keys on hold.

This text between the two pipe+octothorpe sequences is a multi-line comment.
|#

;; Text after double-semicolons are single-line comments.

#|
One defcfg entry may be added, which is used for configuration key-pairs. These
configurations change kanata's behaviour at a more global level than the other
configuration entries.
|#

(defcfg
  #|
  This configuration will process all keys pressed inside of kanata, even if
  they are not mapped in defsrc. This is so that certain actions can activate
  at the right time for certain input sequences. By default, unmapped keys are
  not processed through kanata due to a Windows issue related to AltGr. If you
  use AltGr in your keyboard, you will likely want to follow the simple.kbd
  file while unmapping lctl and ralt from defsrc.
  |#
  process-unmapped-keys yes
)

(defsrc
  caps grv         i
              j    k    l
  lsft rsft
)

(deflayer default
  @cap @grv        _
              _    _    _
  _    _
)

(deflayer arrows
  _    _           up
              left down rght
  _    _
)

(defalias
  cap (tap-hold-press 200 200 caps lctl)
  grv (tap-hold-press 200 200 grv (layer-toggle arrows))
)


================================================
FILE: cfg_samples/opposite-hand-hrm.kbd
================================================
;; Home row mods using tap-hold-opposite-hand
;;
;; Hold activates only when the next key is on the opposite hand,
;; which substantially reduces misfires during fast same-hand rolls.
;; Same-hand keys resolve as tap by default.
;;
;; Compare with home-row-mod-basic.kbd which uses plain tap-hold.

(defcfg
  process-unmapped-keys yes
)

;; Assign physical keys to hands. Keys not listed have no hand
;; assignment and are governed by (unknown-hand <value>) (default: ignore).
(defhands
  (left  q w e r t a s d f g z x c v b)
  (right y u i o p h j k l ; n m , . /))

(defsrc
  q   w   e   r   t   y   u   i   o   p
  a   s   d   f   g   h   j   k   l   ;
  z   x   c   v   b   n   m   ,   .   /
                  spc
)

(defvar
  tap-time 200
  hold-time 180
)

(defalias
  a (tap-hold-opposite-hand $hold-time a lmet)
  s (tap-hold-opposite-hand $hold-time s lalt)
  d (tap-hold-opposite-hand $hold-time d lctl)
  f (tap-hold-opposite-hand $hold-time f lsft)
  j (tap-hold-opposite-hand $hold-time j rsft)
  k (tap-hold-opposite-hand $hold-time k rctl)
  l (tap-hold-opposite-hand $hold-time l ralt)
  ; (tap-hold-opposite-hand $hold-time ; rmet)
)

(deflayer base
  q   w   e   r   t   y   u   i   o   p
  @a  @s  @d  @f  g   h   @j  @k  @l  @;
  z   x   c   v   b   n   m   ,   .   /
                  spc
)


================================================
FILE: cfg_samples/push-msg.kbd
================================================
;; push-msg Sample Configuration
;;
;; This configuration demonstrates the push-msg action for sending
;; messages to external tools via Kanata's TCP server.
;;
;; To use this config:
;;   kanata -p 7070 -c push-msg.kbd
;;
;; Then connect a TCP client to localhost:7070 to receive messages.

(defcfg
  process-unmapped-keys yes
)

(defsrc
  caps a s d f g h j k l ; '
  z x c v b n m , . /
)

;; ==========================================================================
;; Layer Definitions
;; ==========================================================================

(deflayer base
  @caps a s d f g h j k l ; '
  z x c v b n m , . /
)

(deflayer nav
  @caps left down up right g h j k l ; '
  z x c v b n m , . /
)

;; ==========================================================================
;; Aliases with push-msg
;; ==========================================================================

(defalias
  ;; Caps Lock: tap for Esc (with notification), hold for nav layer (with notification)
  caps (tap-hold 200 200
    (multi esc (push-msg "layer:base"))
    (multi (layer-toggle nav) (push-msg "layer:nav:hold"))
  )
)

;; ==========================================================================
;; Virtual Keys - Triggerable via TCP ActOnFakeKey
;; ==========================================================================
;;
;; External tools can trigger these using TCP commands:
;;   {"ActOnFakeKey":{"name":"email-sig","action":"Tap"}}
;;   {"ActOnFakeKey":{"name":"switch-nav","action":"Tap"}}

(defvirtualkeys
  ;; Text expansion macro (S-x for shift+x to get capitals)
  email-sig (macro
    S-b e s t spc r e g a r d s , ret ret
    S-j o h n spc S-d o e
  )

  ;; Layer switches that also push messages
  switch-nav (multi
    (layer-switch nav)
    (push-msg "layer:nav:activated")
  )

  switch-base (multi
    (layer-switch base)
    (push-msg "layer:base:activated")
  )

  ;; Notify external tools (no keyboard action)
  notify-ready (push-msg "status:ready")
  notify-busy (push-msg "status:busy")
)

;; ==========================================================================
;; Usage Examples for External Tools
;; ==========================================================================
;;
;; Python TCP client example:
;;
;;   import socket
;;   import json
;;
;;   sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
;;   sock.connect(('127.0.0.1', 7070))
;;   buffer = ""
;;
;;   while True:
;;       data = sock.recv(4096).decode()
;;       buffer += data
;;       while '\n' in buffer:
;;           line, buffer = buffer.split('\n', 1)
;;           if line:
;;               msg = json.loads(line)
;;               if 'MessagePush' in msg:
;;                   print(f"Received: {msg['MessagePush']['message']}")
;;               elif 'LayerChange' in msg:
;;                   print(f"Layer: {msg['LayerChange']['new']}")
;;
;; Triggering virtual keys from external tools:
;;
;;   # Send this JSON to trigger the email-sig virtual key:
;;   echo '{"ActOnFakeKey":{"name":"email-sig","action":"Tap"}}' | nc localhost 7070
;;
;;   # Or trigger layer switch:
;;   echo '{"ActOnFakeKey":{"name":"switch-nav","action":"Tap"}}' | nc localhost 7070
;;
;; ==========================================================================


================================================
FILE: cfg_samples/simple.kbd
================================================
;; Comments are prefixed by double-semicolon. A single semicolon is parsed as the
;; keyboard key. Comments are ignored for the configuration file.
;;
;; This configuration language is Lisp-like. If you're unfamiliar with Lisp,
;; don't be alarmed. The maintainer jtroo is also unfamiliar with Lisp. You
;; don't need to know Lisp in-depth to be able to configure kanata.
;;
;; If you follow along with the examples, you should be fine. Kanata should
;; also hopefully have helpful error messages in case something goes wrong.
;; If you need help, you are welcome to ask.

;; Only one defsrc is allowed.
;;
;; defsrc defines the keys that will be intercepted by kanata. The order of the
;; keys matches with deflayer declarations and all deflayer declarations must
;; have the same number of keys as defsrc. Any keys not listed in defsrc will
;; be passed straight to the operating system.
(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

;; The first layer defined is the layer that will be active by default when
;; kanata starts up. This layer is the standard QWERTY layout except for the
;; backtick/grave key (@grl) which is an alias for a tap-hold key.
(deflayer qwerty
  @grl 1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

;; The dvorak layer remaps the keys to the dvorak layout. In addition there is
;; another tap-hold key: @cap. This key retains caps lock functionality when
;; quickly tapped but is read as left-control when held.
(deflayer dvorak
  @grl 1    2    3    4    5    6    7    8    9    0    [    ]    bspc
  tab  '    ,    .    p    y    f    g    c    r    l    /    =    \
  @cap a    o    e    u    i    d    h    t    n    s    -    ret
  lsft ;    q    j    k    x    b    m    w    v    z    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

;; defalias is used to declare a shortcut for a more complicated action to keep
;; the deflayer declarations clean and aligned. The alignment in deflayers is not
;; necessary, but is strongly recommended for ease of understanding visually.
;;
;; Aliases are referred to by `@<alias_name>`.
(defalias
  ;; tap: backtick (grave), hold: toggle layer-switching layer while held
  grl (tap-hold 200 200 grv (layer-toggle layers))

  ;; layer-switch changes the base layer.
  dvk (layer-switch dvorak)
  qwr (layer-switch qwerty)

  ;; tap for capslk, hold for lctl
  cap (tap-hold 200 200 caps lctl)
)

;; The `lrld` action stands for "live reload". This will re-parse everything
;; except for linux-dev, meaning you cannot live reload and switch keyboard
;; devices.
;;
;; The keys 1 and 2 switch the base layer to qwerty and dvorak respectively.
;;
;; Apart from the layer switching and live reload, all other keys are the
;; underscore _ which means "transparent". Transparent means the base layer
;; behaviour is used when pressing that key.
(deflayer layers
  _    @qwr @dvk lrld _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)


================================================
FILE: cfg_samples/tray-icon/license_icons.txt
================================================
BSD 2-Clause License

Copyright (c) 2024, Fred Vatin

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: cfg_samples/tray-icon/tray-icon.kbd
================================================
(defcfg
  process-unmapped-keys		yes	;;|no| enable processing of keys that are not in defsrc, useful if mapping a few keys in defsrc instead of most of the keys on your keyboard. Without this, the tap-hold-release and tap-hold-press actions will not activate for keys that are not in defsrc. Disabled because some keys may not work correctly if they are intercepted. E.g. rctl/altgr on Windows; see the windows-altgr configuration item above for context.
  log-layer-changes    		yes	;;|no| overhead
  tray-icon "./_custom-icons/s.png" ;; should activate for layers without icons like '5no-icn'
  ;;opt                   	val  	  |≝|
  icon-match-layer-name   	yes  	;;|yes| match layer name to icon files even without an explicit (icon name.ico) config
  tooltip-layer-changes   	yes  	;;|false|
  tooltip-show-blank      	yes  	;;|no|
  tooltip-duration        	500  	;;|500|
  tooltip-size            	24,24	;;|24 24|
  notify-cfg-reload       	yes  	;;|yes|
  notify-cfg-reload-silent	no   	;;|no|
  notify-error            	yes  	;;|yes|
)
(defalias l1 (layer-while-held 1emoji))
(defalias l2 (layer-while-held 2icon-quote))
(defalias l3 (layer-while-held 3emoji_alt))
(defalias l4 (layer-while-held 4my-lmap))
(defalias l5 (layer-while-held 5no-icn))
(defalias l6 (layer-while-held 6name-match))

(defsrc     	            	                            	1  	2  	3  	4  	5  	6)
(deflayer   	(⌂          	icon base.png)              	@l1	@l2	@l3	@l4	@l5	@l6)	;; find in the 'icon'  subfolder
(deflayer   	(1emoji     	🖻 1symbols.png)             	q  	q  	q  	q  	q  	q)  	;; find in the 'icons' subfolder
(deflayer   	(2icon-quote	🖻 "2Nav Num.png")           	w  	w  	w  	w  	w  	w)  	;; find in the 'img'   subfolder
(deflayer   	(3emoji_alt 	🖼 3trans.parent)            	e  	e  	e  	e  	e  	e)  	;; find '.png'
(deflayermap	(4my-lmap   	🖻 "..\..\assets\kanata.ico")	1 r	2 r	3 r	4 r	5 r	6 r) ;; find in relative path
(deflayer   	5no-icn     	                            	t  	t  	t  	t  	t  	t) ;; match file name from 'tray-icon' config, whithout which would fall back to 'tray-icon.png' as it's the only valid icon matching 'tray-icon.kbd' name
(deflayer   	6name-match 	                            	y  	y  	y  	y  	y  	y) ;; uses '6name-match' with any valid extension since 'icon-match-layer-name' is set to 'yes'


================================================
FILE: docs/README.md
================================================

### Converting ".adoc" to html

To generate html from the these documentation files, use ["asciidoctor"](https://asciidoctor.org)
(they are not fully compatible with the separate "asciidoc" project)



================================================
FILE: docs/config-stylesheet.css
================================================
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details>summary::-webkit-details-marker{display:none}
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>*>tr>*{border-width:1px}
table.grid-cols>*>tr>*{border-width:0 1px}
table.grid-rows>*>tr>*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li>p:empty:only-child::before{content:"";display:inline-block}
ul.checklist>li>p:first-child{margin-left:-1em}
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}

/* DARK MODE */

@media (prefers-color-scheme: dark) {
body,
body .btn,
body table,
body th {
	background-color: #222; !important
	color: #e0e0e0; !important
}

body .btn {
	box-shadow: 0 0 5px #616161; !important
	border: 1px solid #222; !important
}

body .btn:focus {
	box-shadow: 0 0 5px #9e9e9e; !important
}

body .theme-switcher {
	background: url("../img/sun.svg") no-repeat center; !important
}

.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{
color:#ff8a80;!important
}
.quoteblock blockquote::before{
color:#ff8a80;!important
}

body h1,
body h2,
body h3,
body h4,
body h5,
body h6,
body #toctitle,
body .sidebarblock .title,
body .imageblock .title {
	color: #ff8a80 !important;
}

body blockquote::before {
	color: #d32f2f !important;
}

body code,
body pre {
	background-color: #2f2f2f !important;
	color: #e0e0e0; !important
}

body .sectlevel1 li a {
	color: #ff8a80 !important;
}

body a,
body a code,
body .sectlevel2 li a {
	color: #90caf9 !important;
}

body a:hover,
body a:hover code,
body a code:hover,
body .sectlevel2 li a:hover {
	color: #42a5f5 !important;
}

body #toc,
body .pwa-install-div {
	background-color: #222 !important;
}

body #toc {
	border-left-color: #212121; !important
	border-right-color: #212121; !important
}

body .pwa-install-div {
	box-shadow: 0 0 5px #2f2f2f; !important
}

body #pwa-install-btn {
	box-shadow: 0 0 5px #2f2f2f; !important
	background-color: #e0e0e0; !important
	border: 1px solid #e0e0e0; !important
	color: #222; !important
}

body li,
body p,
body .details,
body details,
body details summary,
body td,
body blockquote,
body .attribution cite {
	color: #e0e0e0 !important;
}

body .sidebarblock {
	background-color: #222 !important;
}

* {
	scrollbar-color: #818181 #333; !important
}
*::-webkit-scrollbar-track:hover {
	scrollbar-color: #a1a181 #333; !important
}


/* code style */
:not(pre):not([class^=L])>code{background:#2f2f2f;!important}
kbd{background:#2f2f2f;!important}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#2f2f2f;!important}
.literalblock.output pre{color:#2f2f2f;!important}
.prettyprint{background:#2f2f2f;!important}
}


================================================
FILE: docs/config.adoc
================================================
= Kanata Configuration Guide
:last-update-label!:
ifndef::env-github[]
:toc: left
endif::[]
:stylesheet: config-stylesheet.css

This document describes how to create a kanata configuration file.
The kanata configuration file will determine your keyboard behaviour upon running kanata.

== How to read the guide

ifdef::env-github[]
See the triple bullet-lines at the upper right
to open or close a Table of Contents sidebar.

You may want 
Download .txt
gitextract_lgrqbydp/

├── .devcontainer/
│   └── devcontainer.json
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   └── feature_request.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── build-everything.yml
│       ├── linux-build.yml
│       ├── macos-build.yml
│       ├── rust.yml
│       └── windows-build.yml
├── .gitignore
├── Cargo.toml
├── EnableUIAccess/
│   ├── EnableUIAccess_launch.ahk
│   ├── Lib/
│   │   └── EnableUIAccess.ahk
│   └── README.md
├── LICENSE
├── README.md
├── build.rs
├── cfg_samples/
│   ├── artsey.kbd
│   ├── automousekeys-full-map.kbd
│   ├── automousekeys-only.kbd
│   ├── chords.tsv
│   ├── colemak.kbd
│   ├── deflayermap.kbd
│   ├── f13_f24.kbd
│   ├── fancy_symbols.kbd
│   ├── home-row-mod-advanced.kbd
│   ├── home-row-mod-basic.kbd
│   ├── home-row-mod-prior-idle.kbd
│   ├── included-file.kbd
│   ├── japanese_mac_eisu_kana.kbd
│   ├── jtroo.kbd
│   ├── kanata.kbd
│   ├── key-toggle_press-only_release-only.kbd
│   ├── minimal.kbd
│   ├── opposite-hand-hrm.kbd
│   ├── push-msg.kbd
│   ├── simple.kbd
│   └── tray-icon/
│       ├── license_icons.txt
│       └── tray-icon.kbd
├── docs/
│   ├── README.md
│   ├── config-stylesheet.css
│   ├── config.adoc
│   ├── design.md
│   ├── fancy_symbols.md
│   ├── interception.md
│   ├── kmonad_comparison.md
│   ├── locales.adoc
│   ├── platform-known-issues.adoc
│   ├── release-template.md
│   ├── sequence-adding-chords-ideas.md
│   ├── setup-linux.md
│   ├── simulated_output/
│   │   ├── sim.kbd
│   │   ├── sim.txt
│   │   └── sim_out.txt
│   ├── simulated_passthru_ahk/
│   │   ├── [COPY HERE] kanata_passthru.dll _
│   │   ├── kanata_dll.kbd
│   │   └── kanata_passthru.ahk
│   └── switch-design
├── example_tcp_client/
│   ├── .gitignore
│   ├── Cargo.toml
│   └── src/
│       └── main.rs
├── interception/
│   ├── Cargo.toml
│   └── src/
│       ├── lib.rs
│       └── scancode.rs
├── justfile
├── key-sort-add/
│   ├── Cargo.toml
│   ├── README.md
│   ├── mapping.txt
│   └── src/
│       └── main.rs
├── keyberon/
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── Cargo.toml
│   ├── KEYBOARDS.md
│   ├── LICENSE
│   ├── README.md
│   ├── keyberon-macros/
│   │   ├── Cargo.toml
│   │   ├── README.md
│   │   └── src/
│   │       └── lib.rs
│   └── src/
│       ├── action/
│       │   └── switch.rs
│       ├── action.rs
│       ├── chord.rs
│       ├── key_code.rs
│       ├── layout/
│       │   └── contextual_execution.rs
│       ├── layout.rs
│       ├── lib.rs
│       ├── multikey_buffer.rs
│       └── tap_hold_tracker.rs
├── parser/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── LICENSE
│   ├── README.md
│   ├── src/
│   │   ├── cfg/
│   │   │   ├── alloc.rs
│   │   │   ├── arbitrary_code.rs
│   │   │   ├── caps_word.rs
│   │   │   ├── chord.rs
│   │   │   ├── chord_v1.rs
│   │   │   ├── clipboard.rs
│   │   │   ├── cmd.rs
│   │   │   ├── custom_tap_hold.rs
│   │   │   ├── defcfg.rs
│   │   │   ├── defhands.rs
│   │   │   ├── deflayer.rs
│   │   │   ├── deflocalkeys.rs
│   │   │   ├── defsrc.rs
│   │   │   ├── deftemplate.rs
│   │   │   ├── error.rs
│   │   │   ├── fake_key.rs
│   │   │   ├── fork.rs
│   │   │   ├── is_a_button.rs
│   │   │   ├── key_outputs.rs
│   │   │   ├── key_override.rs
│   │   │   ├── layer_opts.rs
│   │   │   ├── list_actions.rs
│   │   │   ├── live_reload.rs
│   │   │   ├── macro.rs
│   │   │   ├── mod.rs
│   │   │   ├── mouse.rs
│   │   │   ├── multi.rs
│   │   │   ├── oneshot.rs
│   │   │   ├── override.rs
│   │   │   ├── permutations.rs
│   │   │   ├── platform.rs
│   │   │   ├── push_msg.rs
│   │   │   ├── releases.rs
│   │   │   ├── sequence.rs
│   │   │   ├── sexpr.rs
│   │   │   ├── str_ext.rs
│   │   │   ├── switch.rs
│   │   │   ├── tap_dance.rs
│   │   │   ├── tap_hold.rs
│   │   │   ├── tests/
│   │   │   │   ├── ambiguous.rs
│   │   │   │   ├── defcfg.rs
│   │   │   │   ├── defhands.rs
│   │   │   │   ├── device_detect.rs
│   │   │   │   ├── environment.rs
│   │   │   │   └── macros.rs
│   │   │   ├── tests.rs
│   │   │   ├── unicode.rs
│   │   │   ├── unmod.rs
│   │   │   ├── vars.rs
│   │   │   └── zippychord.rs
│   │   ├── custom_action.rs
│   │   ├── keys/
│   │   │   ├── linux.rs
│   │   │   ├── macos.rs
│   │   │   ├── mappings.rs
│   │   │   ├── mod.rs
│   │   │   └── windows.rs
│   │   ├── layers.rs
│   │   ├── lib.rs
│   │   ├── lsp_hints.rs
│   │   ├── sequences.rs
│   │   ├── subset.rs
│   │   └── trie.rs
│   └── test_cfgs/
│       ├── all_keys_in_defsrc.kbd
│       ├── ancestor_seq.kbd
│       ├── bad_multi.kbd
│       ├── descendant_seq.kbd
│       ├── icon_bad_dupe.kbd
│       ├── icon_good.kbd
│       ├── include-bad.kbd
│       ├── include-bad2.kbd
│       ├── include-good-optional-absent.kbd
│       ├── include-good.kbd
│       ├── included-bad.kbd
│       ├── included-bad2.kbd
│       ├── included-good.kbd
│       ├── macro-chord-dont-panic.kbd
│       ├── multiline_comment.kbd
│       ├── nested_tap_hold.kbd
│       ├── test.zch
│       ├── testzch.kbd
│       ├── unknown_defcfg_opt.kbd
│       ├── utf8bom-included.kbd
│       └── utf8bom.kbd
├── rustfmt.toml
├── scripts/
│   └── test_linux_list_devices.sh
├── simulated_input/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       └── sim.rs
├── simulated_passthru/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── ReadMe.md
│   └── src/
│       ├── key_in.rs
│       ├── key_out.rs
│       ├── lib_passthru.rs
│       └── log_win.rs
├── src/
│   ├── gui/
│   │   ├── mod.rs
│   │   ├── win.rs
│   │   ├── win_dbg_logger/
│   │   │   ├── mod.rs
│   │   │   └── win_dbg_logger.toml
│   │   └── win_nwg_ext/
│   │       ├── license-MIT
│   │       ├── license-nwg-MIT
│   │       └── mod.rs
│   ├── kanata/
│   │   ├── caps_word.rs
│   │   ├── cfg_forced.rs
│   │   ├── clipboard.rs
│   │   ├── cmd.rs
│   │   ├── dynamic_macro.rs
│   │   ├── key_repeat.rs
│   │   ├── linux.rs
│   │   ├── macos.rs
│   │   ├── millisecond_counting.rs
│   │   ├── mod.rs
│   │   ├── output_logic/
│   │   │   └── zippychord.rs
│   │   ├── output_logic.rs
│   │   ├── scroll.rs
│   │   ├── sequences.rs
│   │   ├── unknown.rs
│   │   └── windows/
│   │       ├── exthook.rs
│   │       ├── interception.rs
│   │       ├── llhook.rs
│   │       └── mod.rs
│   ├── kanata.exe.manifest.rc
│   ├── lib.rs
│   ├── main.rs
│   ├── main_lib/
│   │   ├── args.rs
│   │   ├── mod.rs
│   │   └── win_gui.rs
│   ├── oskbd/
│   │   ├── linux.rs
│   │   ├── macos.rs
│   │   ├── mod.rs
│   │   ├── sim_passthru.rs
│   │   ├── simulated.rs
│   │   └── windows/
│   │       ├── exthook_os.rs
│   │       ├── interception.rs
│   │       ├── interception_convert.rs
│   │       ├── llhook/
│   │       │   └── mouse.rs
│   │       ├── llhook.rs
│   │       ├── mod.rs
│   │       └── scancode_to_usvk.rs
│   ├── tcp_server.rs
│   ├── tests/
│   │   ├── passthru_macos_tests.rs
│   │   └── sim_tests/
│   │       ├── block_keys_tests.rs
│   │       ├── capsword_sim_tests.rs
│   │       ├── chord_sim_tests.rs
│   │       ├── delay_tests.rs
│   │       ├── layer_sim_tests.rs
│   │       ├── macro_sim_tests.rs
│   │       ├── mod.rs
│   │       ├── oneshot_tests.rs
│   │       ├── output_chord_tests.rs
│   │       ├── override_tests.rs
│   │       ├── release_sim_tests.rs
│   │       ├── repeat_sim_tests.rs
│   │       ├── seq_sim_tests.rs
│   │       ├── switch_sim_tests.rs
│   │       ├── tap_dance_tests.rs
│   │       ├── tap_hold_tests.rs
│   │       ├── template_sim_tests.rs
│   │       ├── timing_tests.rs
│   │       ├── unicode_sim_tests.rs
│   │       ├── unmod_sim_tests.rs
│   │       ├── use_defsrc_sim_tests.rs
│   │       ├── vkey_sim_tests.rs
│   │       └── zippychord_sim_tests.rs
│   └── tests.rs
├── tcp_protocol/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── wasm/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       └── lib.rs
└── windows_key_tester/
    ├── .gitignore
    ├── Cargo.toml
    ├── README.md
    └── src/
        ├── main.rs
        ├── windows/
        │   ├── interception.rs
        │   └── llhook.rs
        └── windows.rs
Download .txt
Showing preview only (217K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2523 symbols across 151 files)

FILE: build.rs
  function main (line 1) | fn main() -> std::io::Result<()> {
  function build (line 21) | pub(super) fn build() -> std::io::Result<()> {

FILE: example_tcp_client/src/main.rs
  type Args (line 11) | struct Args {
  function main (line 25) | fn main() {
  function print_usage (line 50) | fn print_usage() {
  function init_logger (line 116) | fn init_logger(args: &Args) {
  function write_to_kanata (line 139) | fn write_to_kanata(mut s: TcpStream) {
  function read_from_kanata (line 221) | fn read_from_kanata(s: TcpStream) {

FILE: interception/src/lib.rs
  type Device (line 16) | pub type Device = i32;
  type Precedence (line 17) | pub type Precedence = i32;
  type Filter (line 19) | pub enum Filter {
  type Predicate (line 24) | pub type Predicate = extern "C" fn(device: Device) -> bool;
  type MouseFilter (line 51) | pub type MouseFilter = MouseState;
  type Stroke (line 96) | pub enum Stroke {
    type Error (line 114) | type Error = &'static str;
    method try_from (line 116) | fn try_from(raw_stroke: raw::InterceptionMouseStroke) -> Result<Self, ...
    type Error (line 139) | type Error = &'static str;
    method try_from (line 141) | fn try_from(raw_stroke: raw::InterceptionKeyStroke) -> Result<Self, Se...
  type Error (line 161) | type Error = &'static str;
  function try_from (line 163) | fn try_from(stroke: Stroke) -> Result<Self, Self::Error> {
  type Error (line 188) | type Error = &'static str;
  function try_from (line 190) | fn try_from(stroke: Stroke) -> Result<Self, Self::Error> {
  type Interception (line 208) | pub struct Interception {
    method new (line 213) | pub fn new() -> Option<Self> {
    method get_precedence (line 223) | pub fn get_precedence(&self, device: Device) -> Precedence {
    method set_precedence (line 227) | pub fn set_precedence(&self, device: Device, precedence: Precedence) {
    method get_filter (line 231) | pub fn get_filter(&self, device: Device) -> Filter {
    method set_filter (line 254) | pub fn set_filter(&self, predicate: Predicate, filter: Filter) {
    method wait (line 266) | pub fn wait(&self) -> Device {
    method wait_with_timeout (line 270) | pub fn wait_with_timeout(&self, duration: Duration) -> Device {
    method send (line 279) | pub fn send(&self, device: Device, strokes: &[Stroke]) -> i32 {
    method send_internal (line 289) | fn send_internal<T: TryFrom<Stroke>>(&self, device: Device, strokes: &...
    method receive (line 307) | pub fn receive(&self, device: Device, strokes: &mut [Stroke]) -> i32 {
    method receive_internal (line 317) | fn receive_internal<T: TryInto<Stroke> + Default + Copy>(
    method get_hardware_id (line 345) | pub fn get_hardware_id(&self, device: Device, buffer: &mut [u8]) -> u32 {
  method drop (line 359) | fn drop(&mut self) {
  function is_invalid (line 364) | pub extern "C" fn is_invalid(device: Device) -> bool {
  function is_keyboard (line 368) | pub extern "C" fn is_keyboard(device: Device) -> bool {
  function is_mouse (line 372) | pub extern "C" fn is_mouse(device: Device) -> bool {

FILE: interception/src/scancode.rs
  type ScanCode (line 7) | pub enum ScanCode {

FILE: key-sort-add/src/main.rs
  function main (line 21) | fn main() {
  function one (line 29) | fn one() {
  function two (line 68) | fn two() {

FILE: keyberon/keyberon-macros/src/lib.rs
  function layout (line 6) | pub fn layout(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
  function parse_layer (line 31) | fn parse_layer(input: TokenStream) -> TokenStream {
  function parse_row (line 48) | fn parse_row(input: TokenStream) -> TokenStream {
  function parse_group (line 67) | fn parse_group(g: &Group, out: &mut TokenStream) {
  function parse_keycode_group (line 97) | fn parse_keycode_group(input: TokenStream, out: &mut TokenStream) {
  function punctuation_to_keycode (line 112) | fn punctuation_to_keycode(p: &Punct, out: &mut TokenStream) {
  function literal_to_keycode (line 143) | fn literal_to_keycode(l: &Literal, out: &mut TokenStream) {

FILE: keyberon/src/action.rs
  type SequenceEvent (line 13) | pub enum SequenceEvent<'a, T: 'a> {
  method fmt (line 35) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type HoldTapConfig (line 53) | pub enum HoldTapConfig<'a> {
  method fmt (line 106) | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  method eq (line 118) | fn eq(&self, other: &Self) -> bool {
  type ReleasableState (line 132) | pub enum ReleasableState {
  type HoldTapAction (line 153) | pub struct HoldTapAction<'a, T>
  type OneShot (line 197) | pub struct OneShot<'a, T = core::convert::Infallible>
  type OneShotEndConfig (line 215) | pub enum OneShotEndConfig {
  constant ONE_SHOT_MAX_ACTIVE (line 229) | pub const ONE_SHOT_MAX_ACTIVE: usize = 16;
  type TapDance (line 233) | pub struct TapDance<'a, T = core::convert::Infallible>
  type TapDanceConfig (line 252) | pub enum TapDanceConfig {
  type ChordsGroup (line 259) | pub struct ChordsGroup<'a, T = core::convert::Infallible>
  function get_keys (line 274) | pub fn get_keys(&self, coord: (u8, u16)) -> Option<ChordKeys> {
  function get_chord (line 279) | pub fn get_chord(&self, keys: ChordKeys) -> Option<&'a Action<'a, T>> {
  function get_chord_if_unambiguous (line 287) | pub fn get_chord_if_unambiguous(&self, keys: ChordKeys) -> Option<&'a Ac...
  type ChordKeys (line 308) | pub type ChordKeys = u128;
  constant MAX_CHORD_KEYS (line 311) | pub const MAX_CHORD_KEYS: usize = ChordKeys::BITS as usize;
  type ForkConfig (line 317) | pub struct ForkConfig<'a, T> {
  type Action (line 325) | pub enum Action<'a, T = core::convert::Infallible>
  function layer (line 420) | pub fn layer(self) -> Option<usize> {
  function key_codes (line 427) | pub fn key_codes(&self) -> impl Iterator<Item = KeyCode> + '_ {
  function k (line 438) | pub const fn k<T>(kc: KeyCode) -> Action<'static, T> {
  function l (line 444) | pub const fn l<T>(layer: usize) -> Action<'static, T> {
  function d (line 450) | pub const fn d<T>(layer: usize) -> Action<'static, T> {

FILE: keyberon/src/action/switch.rs
  constant MAX_OPCODE_LEN (line 21) | pub const MAX_OPCODE_LEN: u16 = 0x0FFF;
  constant OP_MASK (line 22) | pub const OP_MASK: u16 = 0xF000;
  constant MAX_BOOL_EXPR_DEPTH (line 23) | pub const MAX_BOOL_EXPR_DEPTH: usize = 8;
  constant MAX_KEY_RECENCY (line 24) | pub const MAX_KEY_RECENCY: u8 = 7;
  type Case (line 26) | pub type Case<'a, T> = (&'a [OpCode], &'a Action<'a, T>, BreakOrFallthro...
  type Switch (line 34) | pub struct Switch<'a, T: 'a> {
  constant OR_VAL (line 44) | const OR_VAL: u16 = 0x1000;
  constant AND_VAL (line 45) | const AND_VAL: u16 = 0x2000;
  constant NOT_VAL (line 46) | const NOT_VAL: u16 = 0x3000;
  constant INPUT_VAL (line 48) | const INPUT_VAL: u16 = 851;
  constant HISTORICAL_INPUT_VAL (line 49) | const HISTORICAL_INPUT_VAL: u16 = 852;
  constant LAYER_VAL (line 50) | const LAYER_VAL: u16 = 853;
  constant BASE_LAYER_VAL (line 51) | const BASE_LAYER_VAL: u16 = 854;
  constant TICKS_SINCE_VAL_GT (line 59) | const TICKS_SINCE_VAL_GT: u16 = 0x4000;
  constant TICKS_SINCE_VAL_LT (line 60) | const TICKS_SINCE_VAL_LT: u16 = 0x6000;
  constant HISTORICAL_KEYCODE_VAL (line 64) | const HISTORICAL_KEYCODE_VAL: u16 = 0x8000;
  type BooleanOperator (line 68) | pub enum BooleanOperator {
    method to_u16 (line 219) | fn to_u16(self) -> u16 {
  type OpCode (line 76) | pub struct OpCode(u16);
    method new_key (line 245) | pub fn new_key(kc: KeyCode) -> Self {
    method new_key_history (line 252) | pub fn new_key_history(kc: KeyCode, key_recency: u8) -> Self {
    method new_ticks_since_gt (line 263) | pub fn new_ticks_since_gt(nth_key: u8, ticks_since: u16) -> Self {
    method new_ticks_since_lt (line 273) | pub fn new_ticks_since_lt(nth_key: u8, ticks_since: u16) -> Self {
    method new_bool (line 280) | pub fn new_bool(op: BooleanOperator, end_idx: u16) -> Self {
    method new_active_input (line 286) | pub fn new_active_input(input: KCoord) -> (Self, Self) {
    method new_historical_input (line 296) | pub fn new_historical_input(input: KCoord, key_recency: u8) -> (Self, ...
    method new_layer (line 307) | pub fn new_layer(layer: u16) -> (Self, Self) {
    method new_base_layer (line 313) | pub fn new_base_layer(base_layer: u16) -> (Self, Self) {
    method opcode_type (line 319) | fn opcode_type(self, next: Option<OpCode>) -> OpCodeType {
  type OpCodeType (line 80) | enum OpCodeType {
  type OperatorAndEndIndex (line 94) | struct OperatorAndEndIndex {
    method from (line 355) | fn from(value: u16) -> Self {
  type HistoricalKeyCode (line 102) | struct HistoricalKeyCode {
  type HistoricalInput (line 110) | struct HistoricalInput {
  type TicksSinceNthKey (line 116) | struct TicksSinceNthKey {
  type BreakOrFallthrough (line 124) | pub enum BreakOrFallthrough {
  function actions (line 134) | pub fn actions<A1, A2, H1, H2, L>(
  type SwitchActions (line 165) | pub struct SwitchActions<'a, T, A1, A2, H1, H2, L>
  type Item (line 191) | type Item = &'a Action<'a, T>;
  method next (line 193) | fn next(&mut self) -> Option<Self::Item> {
  function lossy_compress_ticks (line 227) | fn lossy_compress_ticks(t: u16) -> u16 {
  function lossy_decompress_ticks (line 235) | fn lossy_decompress_ticks(t: u16) -> u16 {
  function evaluate_boolean (line 369) | fn evaluate_boolean(
  function evaluate_bool_test (line 487) | fn evaluate_bool_test(opcodes: &[OpCode], keycodes: impl Iterator<Item =...
  function bool_evaluation_test_0 (line 500) | fn bool_evaluation_test_0() {
  function bool_evaluation_test_1 (line 520) | fn bool_evaluation_test_1() {
  function bool_evaluation_test_2 (line 547) | fn bool_evaluation_test_2() {
  function bool_evaluation_test_3 (line 567) | fn bool_evaluation_test_3() {
  function bool_evaluation_test_4 (line 587) | fn bool_evaluation_test_4() {
  function bool_evaluation_test_5 (line 597) | fn bool_evaluation_test_5() {
  function bool_evaluation_test_6 (line 614) | fn bool_evaluation_test_6() {
  function bool_evaluation_test_7 (line 631) | fn bool_evaluation_test_7() {
  function bool_evaluation_test_9 (line 641) | fn bool_evaluation_test_9() {
  function bool_evaluation_test_10 (line 656) | fn bool_evaluation_test_10() {
  function bool_evaluation_test_11 (line 671) | fn bool_evaluation_test_11() {
  function bool_evaluation_test_12 (line 685) | fn bool_evaluation_test_12() {
  function bool_evaluation_test_max_depth_does_not_panic (line 701) | fn bool_evaluation_test_max_depth_does_not_panic() {
  function bool_evaluation_test_more_than_max_depth_panics (line 721) | fn bool_evaluation_test_more_than_max_depth_panics() {
  function switch_fallthrough (line 741) | fn switch_fallthrough() {
  function switch_break (line 762) | fn switch_break() {
  function switch_no_actions (line 782) | fn switch_no_actions() {
  function switch_historical_1 (line 809) | fn switch_historical_1() {
  function switch_historical_bools (line 895) | fn switch_historical_bools() {
  function switch_historical_ticks_since (line 990) | fn switch_historical_ticks_since() {
  function bool_evaluation_test_not_0 (line 1111) | fn bool_evaluation_test_not_0() {
  function bool_evaluation_test_not_1 (line 1133) | fn bool_evaluation_test_not_1() {
  function bool_evaluation_test_not_2 (line 1148) | fn bool_evaluation_test_not_2() {
  function bool_evaluation_test_not_3 (line 1163) | fn bool_evaluation_test_not_3() {
  function bool_evaluation_test_not_4 (line 1177) | fn bool_evaluation_test_not_4() {
  function bool_evaluation_test_not_5 (line 1198) | fn bool_evaluation_test_not_5() {
  function bool_evaluation_test_not_6 (line 1213) | fn bool_evaluation_test_not_6() {
  function bool_evaluation_test_or_equivalency_not_6 (line 1229) | fn bool_evaluation_test_or_equivalency_not_6() {
  function bool_evaluation_test_not_7 (line 1244) | fn bool_evaluation_test_not_7() {
  function bool_evaluation_test_or_equivalency_not_7 (line 1259) | fn bool_evaluation_test_or_equivalency_not_7() {
  function bool_evaluation_test_not_8 (line 1274) | fn bool_evaluation_test_not_8() {
  function bool_evaluation_test_not_9 (line 1289) | fn bool_evaluation_test_not_9() {
  function switch_inputs (line 1304) | fn switch_inputs() {
  function switch_historical_inputs (line 1339) | fn switch_historical_inputs() {

FILE: keyberon/src/chord.rs
  constant TRIGGER_TAPHOLD_COORD (line 25) | pub(crate) const TRIGGER_TAPHOLD_COORD: (u8, u16) = (0, 0);
  type ReleaseBehaviour (line 28) | pub enum ReleaseBehaviour {
  type ChordV2 (line 34) | pub struct ChordV2<'a, T> {
  function fmt (line 51) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::E...
  type ChordsForKey (line 62) | pub struct ChordsForKey<'a, T> {
  type ChordsForKeys (line 68) | pub struct ChordsForKeys<'a, T> {
  constant SMOL_Q_LEN (line 72) | const SMOL_Q_LEN: usize = 16;
  type ActiveChord (line 74) | struct ActiveChord<'a, T> {
  function tick_ach (line 96) | fn tick_ach<T>(acc: &mut ActiveChord<T>) {
  type ActiveChordStatus (line 101) | enum ActiveChordStatus {
  type SmolQueue (line 116) | pub(crate) type SmolQueue = ArrayDeque<Queued, SMOL_Q_LEN, arraydeque::b...
  type ChordsV2 (line 119) | pub struct ChordsV2<'a, T> {
  function fmt (line 156) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  function new (line 162) | pub fn new(chords: ChordsForKeys<'a, T>, ticks_ignore_chord: u16) -> Self {
  function is_idle_chv2 (line 177) | pub fn is_idle_chv2(&self) -> bool {
  function accepts_chords_chv2 (line 181) | pub fn accepts_chords_chv2(&self) -> bool {
  function push_back_chv2 (line 185) | pub fn push_back_chv2(&mut self, item: Queued) -> Option<Queued> {
  function chords (line 189) | pub fn chords(&self) -> &ChordsForKeys<'a, T> {
  function get_action_chv2 (line 193) | pub(crate) fn get_action_chv2(&mut self) -> QueuedAction<'a, T> {
  function tick_chv2 (line 225) | pub(crate) fn tick_chv2(&mut self, active_layer: u16) -> SmolQueue {
  function next_coord (line 259) | fn next_coord(&self) -> u16 {
  function drain_inputs (line 269) | fn drain_inputs(&mut self, drainq: &mut SmolQueue, active_layer: u16) {
  function drain_without_new_activations (line 294) | fn drain_without_new_activations(&mut self, drainq: &mut SmolQueue) {
  function drain_virtual_keys (line 317) | fn drain_virtual_keys(&mut self, drainq: &mut SmolQueue) {
  function drain_releases (line 332) | fn drain_releases(&mut self, drainq: &mut SmolQueue) {
  function process_presses (line 365) | fn process_presses(&mut self, active_layer: u16) {
  function clear_released_chords (line 567) | fn clear_released_chords(&mut self, drainq: &mut SmolQueue) {
  function get_active_chord (line 583) | fn get_active_chord<'a, T>(

FILE: keyberon/src/key_code.rs
  constant KEY_MAX (line 4) | pub const KEY_MAX: u16 = 850;
  function keycode_max_test (line 7) | fn keycode_max_test() {
  type KeyCode (line 16) | pub enum KeyCode {
    method is_mod (line 788) | pub fn is_mod(self) -> bool {
    method fmt (line 799) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

FILE: keyberon/src/layout.rs
  type KCoord (line 41) | pub type KCoord = (u8, u16);
  type Layers (line 50) | pub type Layers<'a, const C: usize, const R: usize, T = core::convert::I...
  constant QUEUE_SIZE (line 53) | const QUEUE_SIZE: usize = 32;
  type QueueLen (line 54) | pub type QueueLen = u8;
  function check_queue_size (line 57) | fn check_queue_size() {
  type Queue (line 65) | pub(crate) type Queue = ArrayDeque<Queued, QUEUE_SIZE, arraydeque::behav...
  type PressedQueue (line 69) | type PressedQueue = ArrayDeque<KCoord, QUEUE_SIZE>;
  constant ACTION_QUEUE_LEN (line 73) | pub const ACTION_QUEUE_LEN: usize = 8;
  type ActionQueue (line 79) | type ActionQueue<'a, T> =
  type Delay (line 81) | type Delay = u16;
  type QueuedAction (line 82) | pub(crate) type QueuedAction<'a, T> = Option<(KCoord, Delay, &'a Action<...
  constant REAL_KEY_ROW (line 84) | pub const REAL_KEY_ROW: u8 = 0;
  constant HISTORICAL_EVENT_LEN (line 86) | const HISTORICAL_EVENT_LEN: usize = 8;
  constant EXTRA_WAITING_LEN (line 87) | const EXTRA_WAITING_LEN: usize = 8;
  function extra_waiting_size_constraint (line 89) | fn extra_waiting_size_constraint() {
  type Layout (line 95) | pub struct Layout<'a, const C: usize, const R: usize, T = core::convert:...
  type History (line 135) | pub struct History<T> {
  type HistoricalEvent (line 141) | pub struct HistoricalEvent<T> {
  function new (line 150) | fn new() -> Self {
  function tick_hist (line 157) | fn tick_hist(&mut self) {
  function push_front (line 166) | fn push_front(&mut self, event: T) {
  function iter_hevents (line 171) | pub fn iter_hevents(&self) -> impl Iterator<Item = HistoricalEvent<T>> +...
  type Event (line 185) | pub enum Event {
    method coord (line 193) | pub fn coord(self) -> KCoord {
    method transform (line 211) | pub fn transform(self, f: impl FnOnce(u8, u16) -> KCoord) -> Self {
    method is_press (line 225) | pub fn is_press(self) -> bool {
    method is_release (line 233) | pub fn is_release(self) -> bool {
  type CustomEvent (line 243) | pub enum CustomEvent<'a, T: 'a> {
  function update (line 257) | fn update(&mut self, e: Self) {
  type NormalKeyFlags (line 269) | pub struct NormalKeyFlags(pub u8);
    method nkf_clear_on_next_action (line 275) | pub fn nkf_clear_on_next_action(self) -> bool {
    method nkf_clear_on_next_release (line 278) | pub fn nkf_clear_on_next_release(self) -> bool {
  constant NORMAL_KEY_FLAG_CLEAR_ON_NEXT_ACTION (line 271) | pub const NORMAL_KEY_FLAG_CLEAR_ON_NEXT_ACTION: u8 = 0x01;
  constant NORMAL_KEY_FLAG_CLEAR_ON_NEXT_RELEASE (line 272) | pub const NORMAL_KEY_FLAG_CLEAR_ON_NEXT_RELEASE: u8 = 0x02;
  type State (line 284) | pub enum State<'a, T: 'a> {
  method clone (line 314) | fn clone(&self) -> Self {
  function keycode (line 319) | pub fn keycode(&self) -> Option<KeyCode> {
  function coord (line 326) | pub fn coord(&self) -> Option<KCoord> {
  function keycode_in_coords (line 336) | fn keycode_in_coords(&self, coords: &OneShotCoords) -> Option<KeyCode> {
  function release (line 349) | pub fn release(&self, c: KCoord, custom: &mut CustomEvent<'a, T>) -> Opt...
  function release_state (line 366) | pub fn release_state(&self, s: ReleasableState) -> Option<Self> {
  function seq_release (line 388) | fn seq_release(&self, kc: KeyCode) -> Option<Self> {
  function get_layer (line 394) | fn get_layer(&self) -> Option<usize> {
  function clear_on_next_release (line 400) | pub fn clear_on_next_release(&self) -> bool {
  type TapDanceState (line 412) | pub(crate) struct TapDanceState<'a, T: 'a> {
  type TapDanceEagerState (line 419) | pub struct TapDanceEagerState<'a, T: 'a> {
  function tick_tde (line 428) | fn tick_tde(&mut self) {
  function is_expired (line 432) | fn is_expired(&self) -> bool {
  function set_expired (line 436) | fn set_expired(&mut self) {
  function incr_taps (line 440) | fn incr_taps(&mut self) {
  type WaitingConfig (line 447) | pub(crate) enum WaitingConfig<'a, T: 'a + std::fmt::Debug> {
  type WaitingState (line 454) | pub struct WaitingState<'a, T: 'a + std::fmt::Debug> {
  type WaitingAction (line 470) | pub enum WaitingAction {
  function tick_wt (line 482) | fn tick_wt(
  function handle_hold_tap (line 526) | fn handle_hold_tap(&mut self, cfg: HoldTapConfig, queued: &Queue) -> Opt...
  function handle_tap_dance (line 610) | fn handle_tap_dance(
  function handle_chord (line 666) | fn handle_chord(
  function decompose_chord_into_action_queue (line 766) | fn decompose_chord_into_action_queue(
  function is_corresponding_release (line 909) | fn is_corresponding_release(&self, event: &Event) -> bool {
  function is_corresponding_press (line 913) | fn is_corresponding_press(&self, event: &Event) -> bool {
  type OneShotCoords (line 918) | type OneShotCoords = ArrayDeque<KCoord, ONE_SHOT_MAX_ACTIVE, arraydeque:...
  type SequenceState (line 921) | pub struct SequenceState<'a, T: 'a> {
  type ReleasedOneShotKeys (line 928) | type ReleasedOneShotKeys = Vec<KCoord, ONE_SHOT_MAX_ACTIVE>;
  constant MAX_LAYERS (line 932) | pub const MAX_LAYERS: usize = 60000;
  constant MAX_ACTIVE_LAYERS (line 939) | pub const MAX_ACTIVE_LAYERS: usize = 12;
  type LayerStack (line 944) | type LayerStack = Vec<u16, MAX_ACTIVE_LAYERS>;
  type OneShotState (line 947) | pub struct OneShotState {
    method tick_osh (line 1011) | fn tick_osh(&mut self) -> Option<ReleasedOneShotKeys> {
    method handle_press (line 1036) | fn handle_press(&mut self, key: OneShotHandlePressKey) -> OneShotCoords {
    method handle_release (line 1074) | fn handle_release(&mut self, (i, j): KCoord) -> (bool, Option<KCoord>) {
    method add_state_to_retain (line 1093) | fn add_state_to_retain(&mut self, state: OneShotRetainableState) {
  type OneShotRetainableState (line 991) | pub enum OneShotRetainableState {
    method coord (line 997) | pub fn coord(&self) -> KCoord {
  type OneShotHandlePressKey (line 1005) | enum OneShotHandlePressKey {
  type QueuedIter (line 1104) | pub struct QueuedIter<'a>(arraydeque::Iter<'a, Queued>);
  type Item (line 1107) | type Item = &'a Queued;
  method next (line 1108) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 1111) | fn size_hint(&self) -> (usize, Option<usize>) {
  type Queued (line 1118) | pub struct Queued {
    method from (line 1123) | fn from(event: Event) -> Self {
    method new_press (line 1128) | pub(crate) fn new_press(i: u8, j: u16) -> Self {
    method new_release (line 1135) | pub(crate) fn new_release(i: u8, j: u16) -> Self {
    method tick_qd (line 1142) | pub(crate) fn tick_qd(&mut self) {
    method event (line 1147) | pub fn event(&self) -> Event {
  type LastPressTracker (line 1153) | pub struct LastPressTracker {
    method tick_lpt (line 1159) | fn tick_lpt(&mut self) {
    method update_coord (line 1162) | fn update_coord(&mut self, coord: KCoord) {
  function new (line 1172) | fn new(layers: &'a [[[Action<T>; C]; R]]) -> Self {
  function new_with_trans_action_settings (line 1212) | pub fn new_with_trans_action_settings(
  function keycodes (line 1226) | pub fn keycodes(&self) -> impl Iterator<Item = KeyCode> + Clone + '_ {
  function waiting_into_hold (line 1233) | fn waiting_into_hold(&mut self, idx: i8) -> CustomEvent<'a, T> {
  function waiting_into_tap (line 1265) | fn waiting_into_tap(&mut self, pq: Option<PressedQueue>, idx: i8) -> Cus...
  function waiting_into_timeout (line 1351) | fn waiting_into_timeout(&mut self, idx: i8) -> CustomEvent<'a, T> {
  function drop_waiting (line 1385) | fn drop_waiting(&mut self) -> CustomEvent<'a, T> {
  function tick (line 1395) | pub fn tick(&mut self) -> CustomEvent<'a, T> {
  function process_sequences (line 1470) | fn process_sequences(&mut self) {
  function process_extra_waitings (line 1554) | fn process_extra_waitings(&mut self, current_custom: CustomEvent<'a, T>)...
  function process_sequence_custom (line 1585) | fn process_sequence_custom(
  function dequeue (line 1615) | fn dequeue(&mut self, queue: Queued) -> CustomEvent<'a, T> {
  function event (line 1700) | pub fn event(&mut self, event: Event) {
  function event_to_front (line 1718) | pub fn event_to_front(&mut self, event: Event) {
  function resolve_coord (line 1732) | fn resolve_coord(
  function do_action (line 1752) | fn do_action(
  function current_layer (line 2259) | pub fn current_layer(&self) -> usize {
  function active_held_layers (line 2267) | pub fn active_held_layers(&self) -> impl Iterator<Item = u16> + Clone + ...
  function trans_resolution_layer_order (line 2275) | pub fn trans_resolution_layer_order(&self) -> LayerStack {
  function set_default_layer (line 2295) | pub fn set_default_layer(&mut self, value: usize) {
  function assert_keys (line 2314) | fn assert_keys(expected: &[KeyCode], iter: impl Iterator<Item = KeyCode>) {
  function basic_hold_tap (line 2321) | fn basic_hold_tap() {
  function basic_hold_tap_repress_timeout (line 2377) | fn basic_hold_tap_repress_timeout() {
  function hold_tap_interleaved_timeout (line 2433) | fn hold_tap_interleaved_timeout() {
  function hold_on_press (line 2486) | fn hold_on_press() {
  function order_clean_tap (line 2546) | fn order_clean_tap() {
  function order_hold (line 2578) | fn order_hold() {
  function order_tap (line 2616) | fn order_tap() {
  function order_multi_key_hold (line 2648) | fn order_multi_key_hold() {
  function order_buffer_ignores_press_within_window (line 2701) | fn order_buffer_ignores_press_within_window() {
  function permissive_hold (line 2747) | fn permissive_hold() {
  function simultaneous_hold (line 2789) | fn simultaneous_hold() {
  function multiple_actions (line 2855) | fn multiple_actions() {
  function custom (line 2878) | fn custom() {
  function multiple_layers (line 2900) | fn multiple_layers() {
  function custom_handler (line 2963) | fn custom_handler() {
  function tap_hold_interval (line 3080) | fn tap_hold_interval() {
  function tap_hold_interval_interleave (line 3137) | fn tap_hold_interval_interleave() {
  function tap_hold_interval_short_hold (line 3264) | fn tap_hold_interval_short_hold() {
  function tap_hold_interval_different_hold (line 3308) | fn tap_hold_interval_different_hold() {
  function one_shot (line 3362) | fn one_shot() {
  function one_shot_end_press_or_repress (line 3474) | fn one_shot_end_press_or_repress() {
  function one_shot_end_on_release (line 3628) | fn one_shot_end_on_release() {
  function one_shot_multi (line 3773) | fn one_shot_multi() {
  function one_shot_tap_hold (line 3831) | fn one_shot_tap_hold() {
  function tap_dance_uneager (line 3894) | fn tap_dance_uneager() {
  function tap_dance_eager (line 4036) | fn tap_dance_eager() {
  function release_state (line 4123) | fn release_state() {
  function test_chord (line 4170) | fn test_chord() {
  function test_chord_normalkey_order (line 4299) | fn test_chord_normalkey_order() {
  function test_chord_multi_waiting_decomposition (line 4342) | fn test_chord_multi_waiting_decomposition() {
  function test_fork (line 4402) | fn test_fork() {
  function test_repeat (line 4435) | fn test_repeat() {
  function test_clear_multiple_keycodes (line 4540) | fn test_clear_multiple_keycodes() {
  function test_trans_in_stacked_held_layers (line 4555) | fn test_trans_in_stacked_held_layers() {
  function test_trans_in_action_on_first_layer (line 4587) | fn test_trans_in_action_on_first_layer() {
  function test_trans_in_taphold_tap (line 4607) | fn test_trans_in_taphold_tap() {
  function test_trans_in_taphold_hold (line 4656) | fn test_trans_in_taphold_hold() {
  function test_trans_in_tapdance_lazy (line 4698) | fn test_trans_in_tapdance_lazy() {
  function test_trans_in_tapdance_eager (line 4737) | fn test_trans_in_tapdance_eager() {
  function test_trans_in_multi (line 4770) | fn test_trans_in_multi() {
  function test_trans_in_chords (line 4795) | fn test_trans_in_chords() {
  function test_trans_in_fork (line 4827) | fn test_trans_in_fork() {
  function test_trans_in_switch (line 4858) | fn test_trans_in_switch() {
  function test_multiple_taphold_trans (line 4893) | fn test_multiple_taphold_trans() {
  function trans_in_multi_works_with_all_trans_settings (line 4965) | fn trans_in_multi_works_with_all_trans_settings() {
  function hold_activated_is_set_on_hold_timeout (line 5038) | fn hold_activated_is_set_on_hold_timeout() {
  function tap_activated_is_set_on_tap_release (line 5071) | fn tap_activated_is_set_on_tap_release() {
  function hold_activated_is_set_on_permissive_hold (line 5105) | fn hold_activated_is_set_on_permissive_hold() {
  function hold_activated_is_set_on_hold_on_other_key_press (line 5141) | fn hold_activated_is_set_on_hold_on_other_key_press() {
  function chord_does_not_set_tap_hold_activated (line 5174) | fn chord_does_not_set_tap_hold_activated() {
  function tap_dance_does_not_set_tap_hold_activated (line 5198) | fn tap_dance_does_not_set_tap_hold_activated() {

FILE: keyberon/src/layout/contextual_execution.rs
  type ContextualExecution (line 7) | pub(super) struct ContextualExecution {
    method new (line 14) | pub(super) fn new() -> Self {
    method push_historical_key (line 21) | pub(super) fn push_historical_key<T: Copy>(&self, h: &mut History<T>, ...

FILE: keyberon/src/multikey_buffer.rs
  constant BUFCAP (line 12) | const BUFCAP: usize = ONE_SHOT_MAX_ACTIVE + 4;
  type MultiKeyBuffer (line 15) | pub(crate) struct MultiKeyBuffer<'a, T> {
  function new (line 30) | pub(crate) unsafe fn new() -> Self {
  function clear (line 47) | pub(crate) unsafe fn clear(&mut self) {
  function push (line 56) | pub(crate) unsafe fn push(&mut self, kc: KeyCode) {
  function get_ref (line 72) | pub(crate) unsafe fn get_ref(&self) -> &'a Action<'a, T> {
  method drop (line 81) | fn drop(&mut self) {

FILE: keyberon/src/tap_hold_tracker.rs
  type HoldActivatedInfo (line 18) | pub struct HoldActivatedInfo {
  type TapActivatedInfo (line 25) | pub struct TapActivatedInfo {
  type TapHoldTracker (line 32) | pub struct TapHoldTracker {
    method set_hold_activated (line 38) | pub(crate) fn set_hold_activated<'a, T: std::fmt::Debug>(
    method set_tap_activated (line 48) | pub(crate) fn set_tap_activated<'a, T: std::fmt::Debug>(
    method take_hold_activated (line 58) | pub fn take_hold_activated(&mut self) -> Option<HoldActivatedInfo> {
    method take_tap_activated (line 62) | pub fn take_tap_activated(&mut self) -> Option<TapActivatedInfo> {
    method set_hold_activated (line 92) | pub(crate) fn set_hold_activated<'a, T: std::fmt::Debug>(
    method set_tap_activated (line 100) | pub(crate) fn set_tap_activated<'a, T: std::fmt::Debug>(
    method take_hold_activated (line 108) | pub fn take_hold_activated(&mut self) -> Option<HoldActivatedInfo> {
    method take_tap_activated (line 113) | pub fn take_tap_activated(&mut self) -> Option<TapActivatedInfo> {
  type HoldActivatedInfo (line 74) | pub struct HoldActivatedInfo {
  type TapActivatedInfo (line 81) | pub struct TapActivatedInfo {
  type TapHoldTracker (line 88) | pub struct TapHoldTracker;
    method set_hold_activated (line 38) | pub(crate) fn set_hold_activated<'a, T: std::fmt::Debug>(
    method set_tap_activated (line 48) | pub(crate) fn set_tap_activated<'a, T: std::fmt::Debug>(
    method take_hold_activated (line 58) | pub fn take_hold_activated(&mut self) -> Option<HoldActivatedInfo> {
    method take_tap_activated (line 62) | pub fn take_tap_activated(&mut self) -> Option<TapActivatedInfo> {
    method set_hold_activated (line 92) | pub(crate) fn set_hold_activated<'a, T: std::fmt::Debug>(
    method set_tap_activated (line 100) | pub(crate) fn set_tap_activated<'a, T: std::fmt::Debug>(
    method take_hold_activated (line 108) | pub fn take_hold_activated(&mut self) -> Option<HoldActivatedInfo> {
    method take_tap_activated (line 113) | pub fn take_tap_activated(&mut self) -> Option<TapActivatedInfo> {

FILE: parser/src/cfg/alloc.rs
  type Allocations (line 19) | pub(crate) struct Allocations {
    method fmt (line 30) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    method new (line 60) | pub(crate) unsafe fn new() -> Arc<Self> {
    method sref (line 67) | pub(crate) fn sref<T>(&self, v: T) -> &'static T {
    method bref_slice (line 84) | pub(crate) fn bref_slice<T>(&self, v: Box<[T]>) -> &'static [T] {
    method sref_vec (line 103) | pub(crate) fn sref_vec<T>(&self, v: Vec<T>) -> &'static [T] {
    method sref_slice (line 109) | pub(crate) fn sref_slice<T>(&self, v: T) -> &'static [&'static T] {
    method sref_str (line 115) | pub(crate) fn sref_str(&self, v: String) -> &'static str {
  type Allocation (line 24) | pub(crate) struct Allocation {
  method drop (line 36) | fn drop(&mut self) {

FILE: parser/src/cfg/arbitrary_code.rs
  function parse_arbitrary_code (line 6) | pub(crate) fn parse_arbitrary_code(

FILE: parser/src/cfg/caps_word.rs
  function parse_caps_word (line 5) | pub(crate) fn parse_caps_word(
  function parse_caps_word_custom (line 80) | pub(crate) fn parse_caps_word_custom(

FILE: parser/src/cfg/chord.rs
  function parse_defchordv2 (line 11) | pub(crate) fn parse_defchordv2(
  function parse_single_chord (line 92) | fn parse_single_chord(
  function parse_participating_keys (line 118) | fn parse_participating_keys(keys: &SExpr, s: &ParserState) -> Result<Vec...
  function parse_timeout (line 142) | fn parse_timeout(chunk: &SExpr, s: &ParserState) -> Result<u16> {
  function parse_release_behaviour (line 147) | fn parse_release_behaviour(
  function parse_disabled_layers (line 170) | fn parse_disabled_layers(disabled_layers: &SExpr, s: &ParserState) -> Re...
  function parse_chord_file (line 193) | fn parse_chord_file(file_name: &str) -> Result<Vec<ChordDefinition>> {
  function parse_input (line 200) | fn parse_input(input: &str) -> Result<Vec<ChordDefinition>> {
  type ChordDefinition (line 220) | struct ChordDefinition {
  type ChordTranslation (line 225) | struct ChordTranslation<'a> {
  function create (line 235) | fn create(
  function post_process (line 283) | fn post_process(&self, converted: &str) -> String {
  function participant_keys (line 296) | fn participant_keys(&self, keys: &str) -> Vec<String> {
  function action (line 307) | fn action(&self, action: &str) -> Vec<String> {
  function translate_chord (line 324) | fn translate_chord(&self, chord_def: &ChordDefinition) -> Vec<SExpr> {

FILE: parser/src/cfg/chord_v1.rs
  type ChordGroup (line 11) | pub(crate) struct ChordGroup {
  function parse_chord (line 20) | pub(crate) fn parse_chord(ac_params: &[SExpr], s: &ParserState) -> Resul...
  function parse_chord_groups (line 57) | pub(crate) fn parse_chord_groups(
  function resolve_chord_groups (line 134) | pub(crate) fn resolve_chord_groups(layers: &mut IntermediateLayers, s: &...
  function find_chords_coords (line 179) | pub(crate) fn find_chords_coords(
  function fill_chords (line 234) | pub(crate) fn fill_chords(

FILE: parser/src/cfg/clipboard.rs
  function parse_clipboard_set (line 7) | pub(crate) fn parse_clipboard_set(
  function parse_clipboard_save (line 28) | pub(crate) fn parse_clipboard_save(
  function parse_clipboard_restore (line 42) | pub(crate) fn parse_clipboard_restore(
  function parse_clipboard_save_swap (line 56) | pub(crate) fn parse_clipboard_save_swap(
  function parse_clipboard_save_set (line 72) | pub(crate) fn parse_clipboard_save_set(

FILE: parser/src/cfg/cmd.rs
  type CmdType (line 6) | pub(crate) enum CmdType {
  function parse_cmd_log (line 20) | pub(crate) fn parse_cmd_log(ac_params: &[SExpr], s: &ParserState) -> Res...
  function parse_cmd (line 55) | pub(crate) fn parse_cmd(
  function collect_strings (line 112) | pub(crate) fn collect_strings(params: &[SExpr], strings: &mut Vec<String...
  function test_collect_strings (line 125) | pub(crate) fn test_collect_strings() {

FILE: parser/src/cfg/custom_tap_hold.rs
  type Hand (line 8) | pub(crate) enum Hand {
  type HandMap (line 18) | pub(crate) struct HandMap {
    method get (line 24) | pub(crate) fn get(&self, key_code: u16) -> Hand {
  type DecisionBehavior (line 34) | pub(crate) enum DecisionBehavior {
  type CustomTapHoldFn (line 41) | pub(crate) type CustomTapHoldFn =
  function custom_tap_hold_release (line 47) | pub(crate) fn custom_tap_hold_release(
  function custom_tap_hold_release_trigger_tap_release (line 77) | pub(crate) fn custom_tap_hold_release_trigger_tap_release(
  function custom_tap_hold_except (line 128) | pub(crate) fn custom_tap_hold_except(keys: &[OsCode], a: &Allocations) -...
  function custom_tap_hold_tap_keys (line 152) | pub(crate) fn custom_tap_hold_tap_keys(
  function custom_tap_hold_opposite_hand (line 175) | pub(crate) fn custom_tap_hold_opposite_hand(

FILE: parser/src/cfg/defcfg.rs
  type DeviceDetectMode (line 12) | pub enum DeviceDetectMode {
    method fmt (line 19) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type CfgLinuxOptions (line 26) | pub struct CfgLinuxOptions {
  method default (line 41) | fn default() -> Self {
  type LinuxCfgOutputBusType (line 61) | pub enum LinuxCfgOutputBusType {
  type CfgMacosOptions (line 69) | pub struct CfgMacosOptions {
  type CfgWinterceptOptions (line 79) | pub struct CfgWinterceptOptions {
  type CfgWindowsOptions (line 88) | pub struct CfgWindowsOptions {
  type CfgOptionsGui (line 95) | pub struct CfgOptionsGui {
  method default (line 119) | fn default() -> Self {
  type CfgOptions (line 136) | pub struct CfgOptions {
  method default (line 182) | fn default() -> Self {
  function parse_defcfg (line 231) | pub fn parse_defcfg(expr: &[SExpr]) -> Result<CfgOptions> {
  function parse_defcfg_val_string (line 933) | fn parse_defcfg_val_string(expr: &SExpr, _label: &str) -> Result<Option<...
  constant FALSE_VALUES (line 940) | pub const FALSE_VALUES: [&str; 3] = ["no", "false", "0"];
  constant TRUE_VALUES (line 941) | pub const TRUE_VALUES: [&str; 3] = ["yes", "true", "1"];
  constant BOOLEAN_VALUES (line 942) | pub const BOOLEAN_VALUES: [&str; 6] = ["yes", "true", "1", "no", "false"...
  function parse_defcfg_val_bool (line 944) | fn parse_defcfg_val_bool(expr: &SExpr, label: &str) -> Result<bool> {
  function parse_cfg_val_u16 (line 970) | fn parse_cfg_val_u16(expr: &SExpr, label: &str, exclude_zero: bool) -> R...
  function parse_colon_separated_text (line 992) | pub fn parse_colon_separated_text(paths: &str) -> Vec<String> {
  function parse_dev (line 1017) | pub fn parse_dev(val: &SExpr) -> Result<Vec<String>> {
  function sexpr_to_str_or_err (line 1051) | fn sexpr_to_str_or_err<'a>(expr: &'a SExpr, label: &str) -> Result<&'a s...
  function sexpr_to_list_or_err (line 1062) | fn sexpr_to_list_or_err<'a>(expr: &'a SExpr, label: &str) -> Result<&'a ...
  function sexpr_to_hwids_vec (line 1073) | fn sexpr_to_hwids_vec(
  type KeyRepeatSettings (line 1108) | pub struct KeyRepeatSettings {
  type UnicodeTermination (line 1115) | pub enum UnicodeTermination {
  type AltGrBehaviour (line 1124) | pub enum AltGrBehaviour {
  constant HWID_ARR_SZ (line 1136) | pub const HWID_ARR_SZ: usize = 1024;
  type ReplayDelayBehaviour (line 1139) | pub enum ReplayDelayBehaviour {

FILE: parser/src/cfg/defhands.rs
  function parse_defhands (line 5) | pub(super) fn parse_defhands(expr: &[SExpr], s: &ParserState) -> Result<...
  function parse_tap_hold_opposite_hand (line 74) | pub(super) fn parse_tap_hold_opposite_hand(
  function parse_key_atoms (line 222) | fn parse_key_atoms(exprs: &[SExpr], s: &ParserState, label: &str) -> Res...
  function parse_decision_behavior (line 235) | fn parse_decision_behavior(
  function parse_decision_behavior_tap_hold (line 252) | fn parse_decision_behavior_tap_hold(

FILE: parser/src/cfg/deflayer.rs
  type LayerIndexes (line 9) | pub(crate) type LayerIndexes = HashMap<String, usize>;
  constant DEFLAYER (line 11) | pub(crate) const DEFLAYER: &str = "deflayer";
  constant DEFLAYER_MAPPED (line 12) | pub(crate) const DEFLAYER_MAPPED: &str = "deflayermap";
  function parse_layer_indexes (line 18) | pub(crate) fn parse_layer_indexes(
  function parse_layers (line 122) | pub(crate) fn parse_layers(
  function parse_layer_base (line 262) | pub(crate) fn parse_layer_base(
  function parse_layer_toggle (line 271) | pub(crate) fn parse_layer_toggle(

FILE: parser/src/cfg/deflocalkeys.rs
  constant DEF_LOCAL_KEYS (line 14) | pub(crate) const DEF_LOCAL_KEYS: &str = "deflocalkeys-win";
  constant DEF_LOCAL_KEYS (line 21) | pub(crate) const DEF_LOCAL_KEYS: &str = "deflocalkeys-winiov2";
  constant DEF_LOCAL_KEYS (line 23) | pub(crate) const DEF_LOCAL_KEYS: &str = "deflocalkeys-wintercept";
  constant DEF_LOCAL_KEYS (line 25) | pub(crate) const DEF_LOCAL_KEYS: &str = "deflocalkeys-macos";
  constant DEF_LOCAL_KEYS (line 27) | pub(crate) const DEF_LOCAL_KEYS: &str = "deflocalkeys-linux";
  function deflocalkeys_variant_applies_to_current_os (line 29) | pub(crate) fn deflocalkeys_variant_applies_to_current_os(variant: &str) ...
  constant DEFLOCALKEYS_VARIANTS (line 33) | pub(crate) const DEFLOCALKEYS_VARIANTS: &[&str] = &[
  function parse_deflocalkeys (line 42) | pub(crate) fn parse_deflocalkeys(

FILE: parser/src/cfg/defsrc.rs
  function parse_defsrc (line 9) | pub(crate) fn parse_defsrc(
  function create_defsrc_layer (line 95) | pub(crate) fn create_defsrc_layer() -> [KanataAction; KEYS_IN_ROW] {

FILE: parser/src/cfg/deftemplate.rs
  type Template (line 29) | struct Template {
  function expand_templates (line 46) | pub fn expand_templates(
  type Replacement (line 204) | struct Replacement {
  function expand (line 209) | fn expand(exprs: &mut Vec<SExpr>, templates: &[Template], _lsp_hints: &m...
  function visit_validate_all_atoms (line 335) | fn visit_validate_all_atoms(
  function visit_validate_all_atoms_peek_next (line 349) | fn visit_validate_all_atoms_peek_next(
  function visit_mut_all_atoms (line 362) | fn visit_mut_all_atoms(exprs: &mut [SExpr], visit: &mut dyn FnMut(&mut S...
  function visit_mut_all_lists (line 371) | fn visit_mut_all_lists(exprs: &mut [SExpr], visit: &mut dyn FnMut(&mut S...
  type ChangeOccurred (line 388) | type ChangeOccurred = bool;
  function evaluate_conditionals (line 390) | fn evaluate_conditionals(exprs: &mut Vec<SExpr>) -> Result<ChangeOccurre...
  function if_equal_replacement (line 444) | fn if_equal_replacement(expr: &SExpr) -> Result<Option<Vec<SExpr>>> {
  function if_not_equal_replacement (line 448) | fn if_not_equal_replacement(expr: &SExpr) -> Result<Option<Vec<SExpr>>> {
  function if_in_list_replacement (line 452) | fn if_in_list_replacement(expr: &SExpr) -> Result<Option<Vec<SExpr>>> {
  function if_not_in_list_replacement (line 456) | fn if_not_in_list_replacement(expr: &SExpr) -> Result<Option<Vec<SExpr>>> {
  function strings_compare_replacement (line 460) | fn strings_compare_replacement(expr: &SExpr, operation: &str) -> Result<...
  function string_list_compare_replacement (line 507) | fn string_list_compare_replacement(expr: &SExpr, operation: &str) -> Res...

FILE: parser/src/cfg/error.rs
  type MResult (line 12) | pub type MResult<T> = miette::Result<T>;
  type Result (line 13) | pub type Result<T> = std::result::Result<T, ParseError>;
  type ParseError (line 16) | pub struct ParseError {
    method new (line 22) | pub fn new(span: Span, err_msg: impl AsRef<str>) -> Self {
    method new_without_span (line 29) | pub fn new_without_span(err_msg: impl AsRef<str>) -> Self {
    method from_expr (line 36) | pub fn from_expr(expr: &sexpr::SExpr, err_msg: impl AsRef<str>) -> Self {
    method from_spanned (line 40) | pub fn from_spanned<T>(spanned: &Spanned<T>, err_msg: impl AsRef<str>)...
    method from (line 46) | fn from(value: anyhow::Error) -> Self {
  function from (line 52) | fn from(val: ParseError) -> Self {
  type CfgError (line 76) | struct CfgError {
  function help (line 85) | pub(super) fn help(err_msg: impl AsRef<str>) -> String {

FILE: parser/src/cfg/fake_key.rs
  function set_virtual_key_reference_lsp_hint (line 6) | fn set_virtual_key_reference_lsp_hint(vk_name_expr: &SExpr, s: &ParserSt...
  function parse_fake_keys (line 21) | pub(crate) fn parse_fake_keys(exprs: &[&Vec<SExpr>], s: &mut ParserState...
  function parse_virtual_keys (line 63) | pub(crate) fn parse_virtual_keys(exprs: &[&Vec<SExpr>], s: &mut ParserSt...
  function parse_on_press_fake_key_op (line 107) | pub(crate) fn parse_on_press_fake_key_op(
  function parse_on_release_fake_key_op (line 118) | pub(crate) fn parse_on_release_fake_key_op(
  function parse_on_idle_fakekey (line 129) | pub(crate) fn parse_on_idle_fakekey(
  function parse_fake_key_op_coord_action (line 182) | fn parse_fake_key_op_coord_action(
  constant NORMAL_KEY_ROW (line 226) | pub const NORMAL_KEY_ROW: u8 = 0;
  constant FAKE_KEY_ROW (line 227) | pub const FAKE_KEY_ROW: u8 = 1;
  function get_fake_key_coords (line 229) | pub(crate) fn get_fake_key_coords<T: Into<usize>>(y: T) -> (u8, u16) {
  function parse_fake_key_delay (line 234) | pub(crate) fn parse_fake_key_delay(
  function parse_on_release_fake_key_delay (line 241) | pub(crate) fn parse_on_release_fake_key_delay(
  function parse_delay (line 248) | fn parse_delay(
  function parse_vkey_coord (line 266) | pub(crate) fn parse_vkey_coord(param: &SExpr, s: &ParserState) -> Result...
  function parse_vkey_action (line 279) | fn parse_vkey_action(param: &SExpr, s: &ParserState) -> Result<FakeKeyAc...
  function parse_on_press (line 301) | pub(crate) fn parse_on_press(
  function parse_on_release (line 317) | pub(crate) fn parse_on_release(
  function parse_on_idle (line 333) | pub(crate) fn parse_on_idle(ac_params: &[SExpr], s: &ParserState) -> Res...
  function parse_on_physical_idle (line 351) | pub(crate) fn parse_on_physical_idle(
  function parse_hold_for_duration (line 373) | pub(crate) fn parse_hold_for_duration(

FILE: parser/src/cfg/fork.rs
  function parse_fork (line 5) | pub(crate) fn parse_fork(ac_params: &[SExpr], s: &ParserState) -> Result...

FILE: parser/src/cfg/is_a_button.rs
  function is_a_button (line 1) | pub(crate) fn is_a_button(osc: u16) -> bool {
  function mouse_inputs_most_care_about_are_considered_buttons (line 10) | fn mouse_inputs_most_care_about_are_considered_buttons() {
  function standard_keys_are_not_considered_buttons (line 32) | fn standard_keys_are_not_considered_buttons() {

FILE: parser/src/cfg/key_outputs.rs
  type KeyOutputs (line 6) | pub type KeyOutputs = Vec<HashMap<OsCode, Vec<OsCode>>>;
  function create_key_outputs (line 9) | pub(crate) fn create_key_outputs(
  function add_chordsv2_output_for_key_pos (line 43) | pub(crate) fn add_chordsv2_output_for_key_pos(
  function add_key_output_from_action_to_key_pos (line 64) | pub(crate) fn add_key_output_from_action_to_key_pos(
  function add_kc_output (line 144) | pub(crate) fn add_kc_output(

FILE: parser/src/cfg/key_override.rs
  type OverrideStates (line 16) | pub struct OverrideStates {
    method new (line 29) | pub fn new() -> Self {
    method cleanup (line 37) | fn cleanup(&mut self) {
    method update (line 43) | fn update(&mut self, osc: OsCode, overrides: &Overrides, active_layer:...
    method is_key_overridden (line 57) | fn is_key_overridden(&self, osc: OsCode) -> bool {
    method add_overrides (line 61) | fn add_overrides(&self, oscs: &mut Vec<KeyCode>) {
    method removed_oscs (line 65) | pub fn removed_oscs(&self) -> impl Iterator<Item = OsCode> + '_ {
  method default (line 23) | fn default() -> Self {
  type Overrides (line 72) | pub struct Overrides {
    method new (line 77) | pub fn new(overrides: &[Override]) -> Self {
    method override_keys (line 92) | pub fn override_keys(
    method output_non_mods_for_input_non_mod (line 109) | pub fn output_non_mods_for_input_non_mod(&self, in_osc: OsCode) -> Vec...
    method is_empty (line 119) | fn is_empty(&self) -> bool {
    method update_keys (line 123) | fn update_keys(
  type Override (line 156) | pub struct Override {
    method try_new (line 166) | pub fn try_new(in_oscs: &[OsCode], out_oscs: &[OsCode]) -> Result<Self> {
    method try_new_v2 (line 207) | pub fn try_new_v2(
    method get_mod_mask (line 219) | fn get_mod_mask(&self) -> u8 {
    method get_excluded_mod_mask (line 227) | fn get_excluded_mod_mask(&self) -> u8 {
    method add_override_keys (line 237) | fn add_override_keys(&self, oscs_to_add: &mut Vec<OsCode>) {
    method add_removed_keys (line 248) | fn add_removed_keys(&self, oscs_to_remove: &mut Vec<OsCode>) {
  function mask_for_key (line 260) | fn mask_for_key(osc: OsCode) -> Option<u8> {
  function mark_overridden_nonmodkeys_for_eager_erasure (line 278) | pub fn mark_overridden_nonmodkeys_for_eager_erasure<T>(

FILE: parser/src/cfg/layer_opts.rs
  constant DEFLAYER_ICON (line 4) | pub(crate) const DEFLAYER_ICON: [&str; 3] = ["icon", "🖻", "🖼"];
  type LayerIcons (line 5) | pub(crate) type LayerIcons = HashMap<String, Option<String>>;
  function parse_layer_opts (line 7) | pub fn parse_layer_opts(list: &[SExpr]) -> Result<HashMap<String, String...

FILE: parser/src/cfg/list_actions.rs
  constant LAYER_SWITCH (line 5) | pub const LAYER_SWITCH: &str = "layer-switch";
  constant LAYER_TOGGLE (line 6) | pub const LAYER_TOGGLE: &str = "layer-toggle";
  constant LAYER_WHILE_HELD (line 7) | pub const LAYER_WHILE_HELD: &str = "layer-while-held";
  constant TAP_HOLD (line 8) | pub const TAP_HOLD: &str = "tap-hold";
  constant TAP_HOLD_PRESS (line 9) | pub const TAP_HOLD_PRESS: &str = "tap-hold-press";
  constant TAP_HOLD_PRESS_A (line 10) | pub const TAP_HOLD_PRESS_A: &str = "tap⬓↓";
  constant TAP_HOLD_RELEASE (line 11) | pub const TAP_HOLD_RELEASE: &str = "tap-hold-release";
  constant TAP_HOLD_RELEASE_A (line 12) | pub const TAP_HOLD_RELEASE_A: &str = "tap⬓↑";
  constant TAP_HOLD_PRESS_TIMEOUT (line 13) | pub const TAP_HOLD_PRESS_TIMEOUT: &str = "tap-hold-press-timeout";
  constant TAP_HOLD_PRESS_TIMEOUT_A (line 14) | pub const TAP_HOLD_PRESS_TIMEOUT_A: &str = "tap⬓↓timeout";
  constant TAP_HOLD_RELEASE_TIMEOUT (line 15) | pub const TAP_HOLD_RELEASE_TIMEOUT: &str = "tap-hold-release-timeout";
  constant TAP_HOLD_RELEASE_TIMEOUT_A (line 16) | pub const TAP_HOLD_RELEASE_TIMEOUT_A: &str = "tap⬓↑timeout";
  constant TAP_HOLD_RELEASE_KEYS (line 17) | pub const TAP_HOLD_RELEASE_KEYS: &str = "tap-hold-release-keys";
  constant TAP_HOLD_RELEASE_KEYS_TAP_RELEASE (line 18) | pub const TAP_HOLD_RELEASE_KEYS_TAP_RELEASE: &str = "tap-hold-release-ta...
  constant TAP_HOLD_RELEASE_KEYS_A (line 19) | pub const TAP_HOLD_RELEASE_KEYS_A: &str = "tap⬓↑keys";
  constant TAP_HOLD_EXCEPT_KEYS (line 20) | pub const TAP_HOLD_EXCEPT_KEYS: &str = "tap-hold-except-keys";
  constant TAP_HOLD_EXCEPT_KEYS_A (line 21) | pub const TAP_HOLD_EXCEPT_KEYS_A: &str = "tap⬓⤫keys";
  constant TAP_HOLD_TAP_KEYS (line 22) | pub const TAP_HOLD_TAP_KEYS: &str = "tap-hold-tap-keys";
  constant TAP_HOLD_TAP_KEYS_A (line 23) | pub const TAP_HOLD_TAP_KEYS_A: &str = "tap⬓tapkeys";
  constant MULTI (line 24) | pub const MULTI: &str = "multi";
  constant MACRO (line 25) | pub const MACRO: &str = "macro";
  constant MACRO_REPEAT (line 26) | pub const MACRO_REPEAT: &str = "macro-repeat";
  constant MACRO_REPEAT_A (line 27) | pub const MACRO_REPEAT_A: &str = "macro⟳";
  constant MACRO_RELEASE_CANCEL (line 28) | pub const MACRO_RELEASE_CANCEL: &str = "macro-release-cancel";
  constant MACRO_RELEASE_CANCEL_A (line 29) | pub const MACRO_RELEASE_CANCEL_A: &str = "macro↑⤫";
  constant MACRO_REPEAT_RELEASE_CANCEL (line 30) | pub const MACRO_REPEAT_RELEASE_CANCEL: &str = "macro-repeat-release-canc...
  constant MACRO_REPEAT_RELEASE_CANCEL_A (line 31) | pub const MACRO_REPEAT_RELEASE_CANCEL_A: &str = "macro⟳↑⤫";
  constant MACRO_CANCEL_ON_NEXT_PRESS (line 32) | pub const MACRO_CANCEL_ON_NEXT_PRESS: &str = "macro-cancel-on-press";
  constant MACRO_REPEAT_CANCEL_ON_NEXT_PRESS (line 33) | pub const MACRO_REPEAT_CANCEL_ON_NEXT_PRESS: &str = "macro-repeat-cancel...
  constant MACRO_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE (line 34) | pub const MACRO_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE: &str =
  constant MACRO_REPEAT_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE (line 36) | pub const MACRO_REPEAT_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE: &str =
  constant UNICODE (line 38) | pub const UNICODE: &str = "unicode";
  constant SYM (line 39) | pub const SYM: &str = "🔣";
  constant ONE_SHOT (line 40) | pub const ONE_SHOT: &str = "one-shot";
  constant ONE_SHOT_PRESS (line 41) | pub const ONE_SHOT_PRESS: &str = "one-shot-press";
  constant ONE_SHOT_PRESS_A (line 42) | pub const ONE_SHOT_PRESS_A: &str = "one-shot↓";
  constant ONE_SHOT_RELEASE (line 43) | pub const ONE_SHOT_RELEASE: &str = "one-shot-release";
  constant ONE_SHOT_RELEASE_A (line 44) | pub const ONE_SHOT_RELEASE_A: &str = "one-shot↑";
  constant ONE_SHOT_PRESS_PCANCEL (line 45) | pub const ONE_SHOT_PRESS_PCANCEL: &str = "one-shot-press-pcancel";
  constant ONE_SHOT_PRESS_PCANCEL_A (line 46) | pub const ONE_SHOT_PRESS_PCANCEL_A: &str = "one-shot↓⤫";
  constant ONE_SHOT_RELEASE_PCANCEL (line 47) | pub const ONE_SHOT_RELEASE_PCANCEL: &str = "one-shot-release-pcancel";
  constant ONE_SHOT_RELEASE_PCANCEL_A (line 48) | pub const ONE_SHOT_RELEASE_PCANCEL_A: &str = "one-shot↑⤫";
  constant ONE_SHOT_PAUSE_PROCESSING (line 49) | pub const ONE_SHOT_PAUSE_PROCESSING: &str = "one-shot-pause-processing";
  constant TAP_DANCE (line 50) | pub const TAP_DANCE: &str = "tap-dance";
  constant TAP_DANCE_EAGER (line 51) | pub const TAP_DANCE_EAGER: &str = "tap-dance-eager";
  constant CHORD (line 52) | pub const CHORD: &str = "chord";
  constant RELEASE_KEY (line 53) | pub const RELEASE_KEY: &str = "release-key";
  constant RELEASE_KEY_A (line 54) | pub const RELEASE_KEY_A: &str = "key↑";
  constant RELEASE_LAYER (line 55) | pub const RELEASE_LAYER: &str = "release-layer";
  constant RELEASE_LAYER_A (line 56) | pub const RELEASE_LAYER_A: &str = "layer↑";
  constant ON_PRESS_FAKEKEY (line 57) | pub const ON_PRESS_FAKEKEY: &str = "on-press-fakekey";
  constant ON_PRESS_FAKEKEY_A (line 58) | pub const ON_PRESS_FAKEKEY_A: &str = "on↓fakekey";
  constant ON_RELEASE_FAKEKEY (line 59) | pub const ON_RELEASE_FAKEKEY: &str = "on-release-fakekey";
  constant ON_RELEASE_FAKEKEY_A (line 60) | pub const ON_RELEASE_FAKEKEY_A: &str = "on↑fakekey";
  constant ON_PRESS_DELAY (line 61) | pub const ON_PRESS_DELAY: &str = "on-press-delay";
  constant ON_RELEASE_DELAY (line 62) | pub const ON_RELEASE_DELAY: &str = "on-release-delay";
  constant ON_PRESS_FAKEKEY_DELAY (line 63) | pub const ON_PRESS_FAKEKEY_DELAY: &str = "on-press-fakekey-delay";
  constant ON_PRESS_FAKEKEY_DELAY_A (line 64) | pub const ON_PRESS_FAKEKEY_DELAY_A: &str = "on↓fakekey-delay";
  constant ON_RELEASE_FAKEKEY_DELAY (line 65) | pub const ON_RELEASE_FAKEKEY_DELAY: &str = "on-release-fakekey-delay";
  constant ON_RELEASE_FAKEKEY_DELAY_A (line 66) | pub const ON_RELEASE_FAKEKEY_DELAY_A: &str = "on↑fakekey-delay";
  constant ON_IDLE_FAKEKEY (line 67) | pub const ON_IDLE_FAKEKEY: &str = "on-idle-fakekey";
  constant MWHEEL_UP (line 68) | pub const MWHEEL_UP: &str = "mwheel-up";
  constant MWHEEL_DOWN (line 69) | pub const MWHEEL_DOWN: &str = "mwheel-down";
  constant MWHEEL_LEFT (line 70) | pub const MWHEEL_LEFT: &str = "mwheel-left";
  constant MWHEEL_RIGHT (line 71) | pub const MWHEEL_RIGHT: &str = "mwheel-right";
  constant MWHEEL_UP_A (line 72) | pub const MWHEEL_UP_A: &str = "🖱☸↑";
  constant MWHEEL_DOWN_A (line 73) | pub const MWHEEL_DOWN_A: &str = "🖱☸↓";
  constant MWHEEL_LEFT_A (line 74) | pub const MWHEEL_LEFT_A: &str = "🖱☸←";
  constant MWHEEL_RIGHT_A (line 75) | pub const MWHEEL_RIGHT_A: &str = "🖱☸→";
  constant MWHEEL_ACCEL_UP (line 76) | pub const MWHEEL_ACCEL_UP: &str = "mwheel-accel-up";
  constant MWHEEL_ACCEL_DOWN (line 77) | pub const MWHEEL_ACCEL_DOWN: &str = "mwheel-accel-down";
  constant MWHEEL_ACCEL_LEFT (line 78) | pub const MWHEEL_ACCEL_LEFT: &str = "mwheel-accel-left";
  constant MWHEEL_ACCEL_RIGHT (line 79) | pub const MWHEEL_ACCEL_RIGHT: &str = "mwheel-accel-right";
  constant MOVEMOUSE_UP (line 80) | pub const MOVEMOUSE_UP: &str = "movemouse-up";
  constant MOVEMOUSE_DOWN (line 81) | pub const MOVEMOUSE_DOWN: &str = "movemouse-down";
  constant MOVEMOUSE_LEFT (line 82) | pub const MOVEMOUSE_LEFT: &str = "movemouse-left";
  constant MOVEMOUSE_RIGHT (line 83) | pub const MOVEMOUSE_RIGHT: &str = "movemouse-right";
  constant MOVEMOUSE_ACCEL_UP (line 84) | pub const MOVEMOUSE_ACCEL_UP: &str = "movemouse-accel-up";
  constant MOVEMOUSE_ACCEL_DOWN (line 85) | pub const MOVEMOUSE_ACCEL_DOWN: &str = "movemouse-accel-down";
  constant MOVEMOUSE_ACCEL_LEFT (line 86) | pub const MOVEMOUSE_ACCEL_LEFT: &str = "movemouse-accel-left";
  constant MOVEMOUSE_ACCEL_RIGHT (line 87) | pub const MOVEMOUSE_ACCEL_RIGHT: &str = "movemouse-accel-right";
  constant MOVEMOUSE_SPEED (line 88) | pub const MOVEMOUSE_SPEED: &str = "movemouse-speed";
  constant MOVEMOUSE_UP_A (line 89) | pub const MOVEMOUSE_UP_A: &str = "🖱↑";
  constant MOVEMOUSE_DOWN_A (line 90) | pub const MOVEMOUSE_DOWN_A: &str = "🖱↓";
  constant MOVEMOUSE_LEFT_A (line 91) | pub const MOVEMOUSE_LEFT_A: &str = "🖱←";
  constant MOVEMOUSE_RIGHT_A (line 92) | pub const MOVEMOUSE_RIGHT_A: &str = "🖱→";
  constant MOVEMOUSE_ACCEL_UP_A (line 93) | pub const MOVEMOUSE_ACCEL_UP_A: &str = "🖱accel↑";
  constant MOVEMOUSE_ACCEL_DOWN_A (line 94) | pub const MOVEMOUSE_ACCEL_DOWN_A: &str = "🖱accel↓";
  constant MOVEMOUSE_ACCEL_LEFT_A (line 95) | pub const MOVEMOUSE_ACCEL_LEFT_A: &str = "🖱accel←";
  constant MOVEMOUSE_ACCEL_RIGHT_A (line 96) | pub const MOVEMOUSE_ACCEL_RIGHT_A: &str = "🖱accel→";
  constant MOVEMOUSE_SPEED_A (line 97) | pub const MOVEMOUSE_SPEED_A: &str = "🖱speed";
  constant SETMOUSE (line 98) | pub const SETMOUSE: &str = "setmouse";
  constant SETMOUSE_A (line 99) | pub const SETMOUSE_A: &str = "set🖱";
  constant DYNAMIC_MACRO_RECORD (line 100) | pub const DYNAMIC_MACRO_RECORD: &str = "dynamic-macro-record";
  constant DYNAMIC_MACRO_PLAY (line 101) | pub const DYNAMIC_MACRO_PLAY: &str = "dynamic-macro-play";
  constant ARBITRARY_CODE (line 102) | pub const ARBITRARY_CODE: &str = "arbitrary-code";
  constant CMD (line 103) | pub const CMD: &str = "cmd";
  constant CMD_LOG (line 104) | pub const CMD_LOG: &str = "cmd-log";
  constant PUSH_MESSAGE (line 105) | pub const PUSH_MESSAGE: &str = "push-msg";
  constant CMD_OUTPUT_KEYS (line 106) | pub const CMD_OUTPUT_KEYS: &str = "cmd-output-keys";
  constant FORK (line 107) | pub const FORK: &str = "fork";
  constant CAPS_WORD (line 108) | pub const CAPS_WORD: &str = "caps-word";
  constant CAPS_WORD_A (line 109) | pub const CAPS_WORD_A: &str = "word⇪";
  constant CAPS_WORD_CUSTOM (line 110) | pub const CAPS_WORD_CUSTOM: &str = "caps-word-custom";
  constant CAPS_WORD_CUSTOM_A (line 111) | pub const CAPS_WORD_CUSTOM_A: &str = "word⇪custom";
  constant CAPS_WORD_TOGGLE (line 112) | pub const CAPS_WORD_TOGGLE: &str = "caps-word-toggle";
  constant CAPS_WORD_TOGGLE_A (line 113) | pub const CAPS_WORD_TOGGLE_A: &str = "word⇪toggle";
  constant CAPS_WORD_CUSTOM_TOGGLE (line 114) | pub const CAPS_WORD_CUSTOM_TOGGLE: &str = "caps-word-custom-toggle";
  constant CAPS_WORD_CUSTOM_TOGGLE_A (line 115) | pub const CAPS_WORD_CUSTOM_TOGGLE_A: &str = "word⇪custom-toggle";
  constant DYNAMIC_MACRO_RECORD_STOP_TRUNCATE (line 116) | pub const DYNAMIC_MACRO_RECORD_STOP_TRUNCATE: &str = "dynamic-macro-reco...
  constant SWITCH (line 117) | pub const SWITCH: &str = "switch";
  constant SEQUENCE (line 118) | pub const SEQUENCE: &str = "sequence";
  constant SEQUENCE_NOERASE (line 119) | pub const SEQUENCE_NOERASE: &str = "sequence-noerase";
  constant UNMOD (line 120) | pub const UNMOD: &str = "unmod";
  constant UNSHIFT (line 121) | pub const UNSHIFT: &str = "unshift";
  constant UNSHIFT_A (line 122) | pub const UNSHIFT_A: &str = "un⇧";
  constant LIVE_RELOAD_NUM (line 123) | pub const LIVE_RELOAD_NUM: &str = "lrld-num";
  constant LIVE_RELOAD_FILE (line 124) | pub const LIVE_RELOAD_FILE: &str = "lrld-file";
  constant ON_PRESS (line 125) | pub const ON_PRESS: &str = "on-press";
  constant ON_PRESS_A (line 126) | pub const ON_PRESS_A: &str = "on↓";
  constant ON_RELEASE (line 127) | pub const ON_RELEASE: &str = "on-release";
  constant ON_RELEASE_A (line 128) | pub const ON_RELEASE_A: &str = "on↑";
  constant ON_IDLE (line 129) | pub const ON_IDLE: &str = "on-idle";
  constant ON_PHYSICAL_IDLE (line 130) | pub const ON_PHYSICAL_IDLE: &str = "on-physical-idle";
  constant HOLD_FOR_DURATION (line 131) | pub const HOLD_FOR_DURATION: &str = "hold-for-duration";
  constant CLIPBOARD_SET (line 132) | pub const CLIPBOARD_SET: &str = "clipboard-set";
  constant CLIPBOARD_CMD_SET (line 133) | pub const CLIPBOARD_CMD_SET: &str = "clipboard-cmd-set";
  constant CLIPBOARD_SAVE (line 134) | pub const CLIPBOARD_SAVE: &str = "clipboard-save";
  constant CLIPBOARD_RESTORE (line 135) | pub const CLIPBOARD_RESTORE: &str = "clipboard-restore";
  constant CLIPBOARD_SAVE_SET (line 136) | pub const CLIPBOARD_SAVE_SET: &str = "clipboard-save-set";
  constant CLIPBOARD_SAVE_CMD_SET (line 137) | pub const CLIPBOARD_SAVE_CMD_SET: &str = "clipboard-save-cmd-set";
  constant CLIPBOARD_SAVE_SWAP (line 138) | pub const CLIPBOARD_SAVE_SWAP: &str = "clipboard-save-swap";
  constant TAP_HOLD_ORDER (line 139) | pub const TAP_HOLD_ORDER: &str = "tap-hold-order";
  constant TAP_HOLD_OPPOSITE_HAND (line 140) | pub const TAP_HOLD_OPPOSITE_HAND: &str = "tap-hold-opposite-hand";
  function is_list_action (line 142) | pub fn is_list_action(ac: &str) -> bool {

FILE: parser/src/cfg/live_reload.rs
  function parse_live_reload_num (line 6) | pub(crate) fn parse_live_reload_num(
  function parse_live_reload_file (line 22) | pub(crate) fn parse_live_reload_file(

FILE: parser/src/cfg/macro.rs
  constant MACRO_ERR (line 7) | const MACRO_ERR: &str = "Action macro only accepts delays, keys, chords,...
  type RepeatMacro (line 9) | pub(crate) enum RepeatMacro {
  function parse_macro (line 14) | pub(crate) fn parse_macro(
  function parse_macro_release_cancel (line 49) | pub(crate) fn parse_macro_release_cancel(
  function parse_macro_cancel_on_next_press (line 61) | pub(crate) fn parse_macro_cancel_on_next_press(
  function parse_macro_cancel_on_next_press_cancel_on_release (line 81) | pub(crate) fn parse_macro_cancel_on_next_press_cancel_on_release(
  function macro_sequence_event_total_duration (line 102) | pub(crate) fn macro_sequence_event_total_duration<T>(events: &[SequenceE...
  function parse_macro_record_stop_truncate (line 111) | pub(crate) fn parse_macro_record_stop_truncate(
  type MacroNumberParseMode (line 127) | pub(crate) enum MacroNumberParseMode {
  function parse_macro_item (line 133) | pub(crate) fn parse_macro_item<'a>(
  function parse_macro_item_impl (line 144) | pub(crate) fn parse_macro_item_impl<'a>(
  function parse_mods_held_for_submacro (line 260) | pub(crate) fn parse_mods_held_for_submacro<'a>(
  function parse_dynamic_macro_record (line 274) | pub(crate) fn parse_dynamic_macro_record(
  function parse_dynamic_macro_play (line 288) | pub(crate) fn parse_dynamic_macro_play(

FILE: parser/src/cfg/mod.rs
  type HashSet (line 150) | type HashSet<T> = rustc_hash::FxHashSet<T>;
  type HashMap (line 151) | type HashMap<K, V> = rustc_hash::FxHashMap<K, V>;
  type FileContentProvider (line 228) | pub struct FileContentProvider<'a> {
  function new (line 236) | pub fn new(
  function get_file_content (line 243) | pub fn get_file_content(&mut self, filename: &Path) -> std::result::Resu...
  type KanataCustom (line 248) | pub type KanataCustom = &'static &'static [&'static CustomAction];
  type KanataAction (line 249) | pub type KanataAction = Action<'static, KanataCustom>;
  type KLayout (line 250) | type KLayout = Layout<'static, KEYS_IN_ROW, 2, KanataCustom>;
  type TapHoldCustomFunc (line 252) | type TapHoldCustomFunc = fn(&[OsCode], &Allocations) -> &'static custom_...
  type BorrowedKLayout (line 254) | pub type BorrowedKLayout<'a> = Layout<'a, KEYS_IN_ROW, 2, &'a &'a [&'a C...
  type KeySeqsToFKeys (line 255) | pub type KeySeqsToFKeys = Trie<(u8, u16)>;
  type KanataLayout (line 257) | pub struct KanataLayout {
    method new (line 263) | fn new(layout: KLayout, a: Arc<Allocations>) -> Self {
    method bm (line 271) | pub fn bm(&mut self) -> &mut BorrowedKLayout<'_> {
    method b (line 277) | pub fn b(&self) -> &BorrowedKLayout<'_> {
  type Cfg (line 283) | pub struct Cfg {
  function new_from_file (line 310) | pub fn new_from_file(p: &Path) -> MResult<Cfg> {
  function new_from_str (line 314) | pub fn new_from_str(cfg_text: &str, file_content: HashMap<String, String...
  type MappedKeys (line 335) | pub type MappedKeys = HashSet<OsCode>;
  type LayerInfo (line 338) | pub struct LayerInfo {
  function parse_cfg (line 345) | fn parse_cfg(p: &Path) -> MResult<Cfg> {
  function populate_cfg_with_icfg (line 352) | fn populate_cfg_with_icfg(icfg: IntermediateCfg, s: ParserState) -> Cfg {
  type IntermediateCfg (line 396) | pub struct IntermediateCfg {
  type EnvVars (line 410) | pub type EnvVars = std::result::Result<Vec<(String, String)>, String>;
  function parse_cfg_raw (line 413) | fn parse_cfg_raw(p: &Path, s: &mut ParserState) -> MResult<IntermediateC...
  function expand_includes (line 470) | fn expand_includes(
  function parse_cfg_raw_string (line 523) | pub fn parse_cfg_raw_string(
  function error_on_unknown_top_level_atoms (line 981) | fn error_on_unknown_top_level_atoms(exprs: &[Spanned<Vec<SExpr>>]) -> Re...
  function gen_first_atom_filter (line 1032) | fn gen_first_atom_filter(a: &str) -> impl Fn(&&Vec<SExpr>) -> bool {
  function gen_first_atom_start_filter_spanned (line 1049) | fn gen_first_atom_start_filter_spanned(a: &str) -> impl Fn(&&Spanned<Vec...
  function gen_first_atom_filter_spanned (line 1066) | fn gen_first_atom_filter_spanned(a: &str) -> impl Fn(&&Spanned<Vec<SExpr...
  function check_first_expr (line 1082) | fn check_first_expr<'a>(
  type MouseInDefsrc (line 1098) | enum MouseInDefsrc {
  type Aliases (line 1103) | type Aliases = HashMap<String, &'static KanataAction>;
  type LayerExprs (line 1106) | enum LayerExprs {
  type SpannedLayerExprs (line 1112) | enum SpannedLayerExprs {
  type ParserContext (line 1118) | pub struct ParserContext {
  type ParserState (line 1124) | pub struct ParserState {
    method vars (line 1148) | fn vars(&self) -> Option<&HashMap<String, SExpr>> {
  method default (line 1154) | fn default() -> Self {
  function parse_aliases (line 1183) | fn parse_aliases(
  function handle_standard_defalias (line 1195) | fn handle_standard_defalias(expr: &[SExpr], s: &mut ParserState) -> Resu...
  function handle_envcond_defalias (line 1203) | fn handle_envcond_defalias(
  function read_alias_name_action_pairs (line 1282) | fn read_alias_name_action_pairs<'a>(
  function parse_action (line 1315) | fn parse_action(expr: &SExpr, s: &ParserState) -> Result<&'static Kanata...
  function custom (line 1332) | fn custom(ca: CustomAction, a: &Allocations) -> Result<&'static KanataAc...
  function parse_action_atom (line 1337) | fn parse_action_atom(ac_span: &Spanned<String>, s: &ParserState) -> Resu...
  function parse_action_list (line 1493) | fn parse_action_list(ac: &[SExpr], s: &ParserState) -> Result<&'static K...
  function layer_idx (line 1651) | fn layer_idx(ac_params: &[SExpr], layers: &LayerIndexes, s: &ParserState...
  function parse_named_u8_param (line 1676) | fn parse_named_u8_param(name: &str, name_and_param: &SExpr, s: &ParserSt...
  function parse_u8_with_range (line 1698) | fn parse_u8_with_range(expr: &SExpr, s: &ParserState, label: &str, min: ...
  function parse_u16 (line 1709) | fn parse_u16(expr: &SExpr, s: &ParserState, label: &str) -> Result<u16> {
  function parse_f32 (line 1716) | fn parse_f32(
  function parse_non_zero_u16 (line 1742) | fn parse_non_zero_u16(expr: &SExpr, s: &ParserState, label: &str) -> Res...
  function parse_key_list (line 1752) | fn parse_key_list(expr: &SExpr, s: &ParserState, label: &str) -> Result<...
  function parse_mod_prefix (line 1810) | pub fn parse_mod_prefix(mods: &str) -> Result<(Vec<KeyCode>, &str)> {

FILE: parser/src/cfg/mouse.rs
  function parse_distance (line 6) | pub(crate) fn parse_distance(expr: &SExpr, s: &ParserState, label: &str)...
  function parse_mwheel (line 13) | pub(crate) fn parse_mwheel(
  function parse_mwheel_accel (line 34) | pub(crate) fn parse_mwheel_accel(
  function parse_move_mouse (line 66) | pub(crate) fn parse_move_mouse(
  function parse_move_mouse_accel (line 86) | pub(crate) fn parse_move_mouse_accel(
  function parse_move_mouse_speed (line 115) | pub(crate) fn parse_move_mouse_speed(
  function parse_set_mouse (line 131) | pub(crate) fn parse_set_mouse(

FILE: parser/src/cfg/multi.rs
  function parse_multi (line 5) | pub(crate) fn parse_multi(ac_params: &[SExpr], s: &ParserState) -> Resul...

FILE: parser/src/cfg/oneshot.rs
  function parse_one_shot (line 5) | pub(crate) fn parse_one_shot(
  function parse_one_shot_pause_processing (line 31) | pub(crate) fn parse_one_shot_pause_processing(

FILE: parser/src/cfg/override.rs
  function parse_overrides (line 6) | pub(crate) fn parse_overrides(exprs: &[SExpr], s: &ParserState) -> Resul...
  function parse_override_inout_keys (line 24) | pub(crate) fn parse_override_inout_keys(
  function parse_overridesv2 (line 63) | pub(crate) fn parse_overridesv2(exprs: &[SExpr], s: &ParserState) -> Res...

FILE: parser/src/cfg/permutations.rs
  function gen_permutations (line 28) | pub fn gen_permutations<T: Clone + Default>(a: &[T]) -> Vec<Vec<T>> {
  function heaps_alg (line 36) | fn heaps_alg<T: Clone>(k: usize, a: &mut [T], outs: &mut Vec<Vec<T>>) {

FILE: parser/src/cfg/platform.rs
  function filter_platform_specific_cfg (line 8) | pub(crate) fn filter_platform_specific_cfg(
  function filter_env_specific_cfg (line 79) | pub(crate) fn filter_env_specific_cfg(

FILE: parser/src/cfg/push_msg.rs
  function parse_push_message (line 5) | pub(crate) fn parse_push_message(
  function to_simple_expr (line 18) | pub(crate) fn to_simple_expr(params: &[SExpr], s: &ParserState) -> Vec<S...
  type SimpleSExpr (line 35) | pub enum SimpleSExpr {

FILE: parser/src/cfg/releases.rs
  function parse_release_key (line 6) | pub(crate) fn parse_release_key(
  function parse_release_layer (line 23) | pub(crate) fn parse_release_layer(

FILE: parser/src/cfg/sequence.rs
  constant SEQ_ERR (line 7) | const SEQ_ERR: &str = "defseq expects pairs of parameters: <virtual_key_...
  function parse_sequence_start (line 9) | pub(crate) fn parse_sequence_start(
  function parse_sequence_noerase (line 36) | pub(crate) fn parse_sequence_noerase(
  function parse_sequences (line 50) | pub(crate) fn parse_sequences(exprs: &[&Vec<SExpr>], s: &ParserState) ->...
  function parse_sequence_keys (line 160) | pub(crate) fn parse_sequence_keys(exprs: &[SExpr], s: &ParserState) -> R...

FILE: parser/src/cfg/sexpr.rs
  type HashMap (line 6) | type HashMap<K, V> = rustc_hash::FxHashMap<K, V>;
  type Position (line 11) | pub struct Position {
    method new (line 21) | pub fn new(absolute: usize, line: usize, line_beginning: usize) -> Self {
  type Span (line 33) | pub struct Span {
    method new (line 63) | pub fn new(start: Position, end: Position, file_name: Rc<str>, file_co...
    method cover (line 74) | pub fn cover(&self, other: &Span) -> Span {
    method start (line 97) | pub fn start(&self) -> usize {
    method end (line 101) | pub fn end(&self) -> usize {
    method file_name (line 105) | pub fn file_name(&self) -> String {
    method file_content (line 109) | pub fn file_content(&self) -> String {
  method fmt (line 41) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  method default (line 52) | fn default() -> Self {
  type Output (line 115) | type Output = str;
  function index (line 116) | fn index(&self, span: Span) -> &Self::Output {
  type Output (line 122) | type Output = str;
  method index (line 123) | fn index(&self, span: Span) -> &Self::Output {
  type Spanned (line 129) | pub struct Spanned<T> {
  function new (line 135) | pub fn new(t: T, span: Span) -> Spanned<T> {
  type SExpr (line 143) | pub enum SExpr {
    method atom (line 149) | pub fn atom<'a>(&'a self, vars: Option<&'a HashMap<String, SExpr>>) ->...
    method list (line 171) | pub fn list<'a>(&'a self, vars: Option<&'a HashMap<String, SExpr>>) ->...
    method span_list (line 190) | pub fn span_list<'a>(
    method span (line 212) | pub fn span(&self) -> Span {
    method fmt (line 221) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type SExprMetaData (line 241) | pub enum SExprMetaData {
    method span (line 248) | pub fn span(&self) -> Span {
  type Token (line 258) | enum Token {
  type PositionCountingBytesIterator (line 269) | struct PositionCountingBytesIterator<'a> {
  function new (line 277) | fn new(s: &'a str) -> Self {
  function pos (line 286) | fn pos(&self) -> Position {
  type Item (line 293) | type Item = u8;
  method next (line 295) | fn next(&mut self) -> Option<Self::Item> {
  type Lexer (line 305) | pub struct Lexer<'a> {
  function is_start (line 310) | fn is_start(b: u8) -> bool {
  type TokenRes (line 314) | type TokenRes = std::result::Result<Token, String>;
  function new (line 320) | fn new(
  function next_while (line 344) | fn next_while(&mut self, f: impl Fn(u8) -> bool) {
  function read_until_multiline_string_end (line 356) | fn read_until_multiline_string_end(&mut self) -> TokenRes {
  function read_until_multiline_comment_end (line 370) | fn read_until_multiline_comment_end(&mut self) -> TokenRes {
  function next_token (line 383) | fn next_token(&mut self) -> Option<(Position, TokenRes)> {
  function next_string (line 457) | fn next_string(&mut self) -> Token {
  function next_whitespace (line 463) | fn next_whitespace(&mut self) -> Token {
  type TopLevel (line 469) | pub type TopLevel = Spanned<Vec<SExpr>>;
  function parse (line 471) | pub fn parse(cfg: &str, file_name: &str) -> std::result::Result<Vec<TopL...
  function parse_ (line 476) | pub fn parse_(
  function strip_utf8_bom (line 501) | fn strip_utf8_bom(s: &str) -> &str {
  function parse_with (line 508) | fn parse_with(

FILE: parser/src/cfg/str_ext.rs
  type TrimAtomQuotes (line 1) | pub trait TrimAtomQuotes {
    method trim_atom_quotes (line 2) | fn trim_atom_quotes(&self) -> &str;
    method trim_atom_quotes (line 6) | fn trim_atom_quotes(&self) -> &str {
    method trim_atom_quotes (line 19) | fn trim_atom_quotes(&self) -> &str {

FILE: parser/src/cfg/switch.rs
  function parse_switch (line 4) | pub fn parse_switch(ac_params: &[SExpr], s: &ParserState) -> Result<&'st...
  function parse_switch_case_bool (line 53) | pub fn parse_switch_case_bool(

FILE: parser/src/cfg/tap_dance.rs
  function parse_tap_dance (line 6) | pub(crate) fn parse_tap_dance(

FILE: parser/src/cfg/tap_hold.rs
  type TapHoldOptions (line 9) | pub(crate) struct TapHoldOptions {
  function parse_require_prior_idle_option (line 15) | pub(crate) fn parse_require_prior_idle_option(
  function parse_tap_hold_options (line 32) | pub(crate) fn parse_tap_hold_options(
  constant TAP_HOLD_OPTION_KEYWORDS (line 71) | const TAP_HOLD_OPTION_KEYWORDS: &[&str] = &["require-prior-idle"];
  function count_trailing_options (line 76) | fn count_trailing_options(ac_params: &[SExpr], s: &ParserState) -> usize {
  function parse_tap_hold (line 92) | pub(crate) fn parse_tap_hold(
  function parse_tap_hold_timeout (line 127) | pub(crate) fn parse_tap_hold_timeout(
  function parse_tap_hold_order (line 191) | pub(crate) fn parse_tap_hold_order(
  function parse_tap_hold_keys (line 225) | pub(crate) fn parse_tap_hold_keys(
  function parse_tap_hold_keys_trigger_tap_release (line 263) | pub(crate) fn parse_tap_hold_keys_trigger_tap_release(

FILE: parser/src/cfg/tests.rs
  function init_log (line 17) | fn init_log() {
  function lock (line 39) | fn lock<T>(lk: &Mutex<T>) -> MutexGuard<'_, T> {
  function parse_cfg (line 46) | fn parse_cfg(cfg: &str) -> Result<IntermediateCfg> {
  function sizeof_action_is_two_usizes (line 73) | fn sizeof_action_is_two_usizes() {
  function test_span_absolute_ranges (line 81) | fn test_span_absolute_ranges() {
  function span_works_with_unicode_characters (line 95) | fn span_works_with_unicode_characters() {
  function test_multiline_error_span (line 127) | fn test_multiline_error_span() {
  function test_span_of_an_unterminated_block_comment_error (line 161) | fn test_span_of_an_unterminated_block_comment_error() {
  function parse_action_vars (line 189) | fn parse_action_vars() {
  function parse_multiline_comment (line 304) | fn parse_multiline_comment() {
  function parse_all_keys (line 313) | fn parse_all_keys() {
  function parse_file_with_utf8_bom (line 326) | fn parse_file_with_utf8_bom() {
  function parse_zippychord_file (line 333) | fn parse_zippychord_file() {
  function disallow_nested_tap_hold (line 339) | fn disallow_nested_tap_hold() {
  function disallow_ancestor_seq (line 350) | fn disallow_ancestor_seq() {
  function disallow_descendent_seq (line 361) | fn disallow_descendent_seq() {
  function disallow_multiple_waiting_actions (line 372) | fn disallow_multiple_waiting_actions() {
  function chord_in_macro_dont_panic (line 383) | fn chord_in_macro_dont_panic() {
  function unknown_defcfg_item_fails (line 393) | fn unknown_defcfg_item_fails() {
  function recursive_multi_is_flattened (line 403) | fn recursive_multi_is_flattened() {
  function test_parse_sequence_a_b (line 447) | fn test_parse_sequence_a_b() {
  function test_parse_sequence_sa_b (line 459) | fn test_parse_sequence_sa_b() {
  function test_parse_sequence_sab (line 472) | fn test_parse_sequence_sab() {
  function test_parse_sequence_bigchord (line 485) | fn test_parse_sequence_bigchord() {
  function test_parse_sequence_inner_chord (line 503) | fn test_parse_sequence_inner_chord() {
  function test_parse_sequence_earlier_inner_chord (line 519) | fn test_parse_sequence_earlier_inner_chord() {
  function test_parse_sequence_numbers (line 535) | fn test_parse_sequence_numbers() {
  function test_parse_macro_numbers (line 555) | fn test_parse_macro_numbers() {
  function test_include_good (line 579) | fn test_include_good() {
  function test_include_bad_has_filename_included (line 585) | fn test_include_bad_has_filename_included() {
  function test_include_bad2_has_original_filename (line 605) | fn test_include_bad2_has_original_filename() {
  function test_include_ignore_optional_filename (line 628) | fn test_include_ignore_optional_filename() {
  function parse_bad_submacro (line 637) | fn parse_bad_submacro() {
  function parse_bad_submacro_2 (line 666) | fn parse_bad_submacro_2() {
  function parse_nested_macro (line 695) | fn parse_nested_macro() {
  function parse_switch (line 710) | fn parse_switch() {
  function parse_switch_exceed_depth (line 863) | fn parse_switch_exceed_depth() {
  function parse_virtualkeys (line 893) | fn parse_virtualkeys() {
  function parse_on_idle_fakekey (line 979) | fn parse_on_idle_fakekey() {
  function parse_on_idle_fakekey_errors (line 1015) | fn parse_on_idle_fakekey_errors() {
  function parse_fake_keys_errors_on_too_many (line 1120) | fn parse_fake_keys_errors_on_too_many() {
  function parse_deflocalkeys_overridden (line 1154) | fn parse_deflocalkeys_overridden() {
  function use_default_overridable_mappings (line 1260) | fn use_default_overridable_mappings() {
  function list_action_not_in_list_error_message_is_good (line 1271) | fn list_action_not_in_list_error_message_is_good() {
  function parse_device_paths (line 1301) | fn parse_device_paths() {
  function test_parse_dev (line 1311) | fn test_parse_dev() {
  function parse_all_defcfg (line 1380) | fn parse_all_defcfg() {
  function parse_defcfg_linux_output_bus (line 1430) | fn parse_defcfg_linux_output_bus() {
  function parse_unmod (line 1460) | fn parse_unmod() {
  function using_parentheses_in_deflayer_directly_fails_with_custom_message (line 1477) | fn using_parentheses_in_deflayer_directly_fails_with_custom_message() {
  function using_escaped_parentheses_in_deflayer_fails_with_custom_message (line 1502) | fn using_escaped_parentheses_in_deflayer_fails_with_custom_message() {
  function parse_cmd (line 1528) | fn parse_cmd() {
  function parse_cmd_log (line 1553) | fn parse_cmd_log() {
  function parse_defvar_concat (line 1576) | fn parse_defvar_concat() {
  function parse_template_1 (line 1647) | fn parse_template_1() {
  function parse_template_2 (line 1675) | fn parse_template_2() {
  function parse_template_3 (line 1713) | fn parse_template_3() {
  function parse_template_4 (line 1744) | fn parse_template_4() {
  function parse_template_5 (line 1767) | fn parse_template_5() {
  function parse_template_6 (line 1790) | fn parse_template_6() {
  function parse_template_7 (line 1813) | fn parse_template_7() {
  function parse_template_8 (line 1836) | fn parse_template_8() {
  function test_deflayermap (line 1874) | fn test_deflayermap() {
  function test_defaliasenvcond (line 1895) | fn test_defaliasenvcond() {
  function parse_platform_specific (line 1960) | fn parse_platform_specific() {
  function parse_defseq_overlap_limits (line 2007) | fn parse_defseq_overlap_limits() {
  function parse_defseq_overlap_too_many (line 2021) | fn parse_defseq_overlap_too_many() {
  function parse_layer_opts_icon (line 2034) | fn parse_layer_opts_icon() {
  function disallow_dupe_layer_opts_icon_layernonmap (line 2040) | fn disallow_dupe_layer_opts_icon_layernonmap() {
  function disallow_dupe_layer_opts_icon_layermap (line 2048) | fn disallow_dupe_layer_opts_icon_layermap() {
  function layer_name_allows_var (line 2058) | fn layer_name_allows_var() {
  function disallow_whitespace_in_tooltip_size (line 2077) | fn disallow_whitespace_in_tooltip_size() {
  function reverse_release_order_must_be_within_multi (line 2089) | fn reverse_release_order_must_be_within_multi() {
  function parse_clipboard_actions (line 2102) | fn parse_clipboard_actions() {

FILE: parser/src/cfg/tests/ambiguous.rs
  function parse_double_dollar_var (line 4) | fn parse_double_dollar_var() {
  function parse_double_at_alias (line 20) | fn parse_double_at_alias() {

FILE: parser/src/cfg/tests/defcfg.rs
  function disallow_same_key_in_defsrc_unmapped_except (line 4) | fn disallow_same_key_in_defsrc_unmapped_except() {
  function unmapped_except_keys_cannot_have_dupes (line 17) | fn unmapped_except_keys_cannot_have_dupes() {
  function unmapped_except_keys_must_be_known (line 30) | fn unmapped_except_keys_must_be_known() {
  function unmapped_except_keys_respects_deflocalkeys (line 43) | fn unmapped_except_keys_respects_deflocalkeys() {
  function unmapped_except_keys_is_removed_from_mapping (line 77) | fn unmapped_except_keys_is_removed_from_mapping() {
  function non_applicable_os_deflocalkeys_always_succeeds_parsing (line 114) | fn non_applicable_os_deflocalkeys_always_succeeds_parsing() {
  function tap_hold_require_prior_idle_parses_valid_value (line 126) | fn tap_hold_require_prior_idle_parses_valid_value() {
  function tap_hold_require_prior_idle_allows_zero (line 139) | fn tap_hold_require_prior_idle_allows_zero() {
  function tap_hold_require_prior_idle_rejects_non_numeric (line 152) | fn tap_hold_require_prior_idle_rejects_non_numeric() {
  function per_action_require_prior_idle_parses (line 165) | fn per_action_require_prior_idle_parses() {
  function per_action_require_prior_idle_zero_parses (line 177) | fn per_action_require_prior_idle_zero_parses() {
  function per_action_require_prior_idle_rejects_non_numeric (line 189) | fn per_action_require_prior_idle_rejects_non_numeric() {
  function per_action_require_prior_idle_rejects_unknown_option (line 199) | fn per_action_require_prior_idle_rejects_unknown_option() {
  function per_action_require_prior_idle_rejects_duplicate (line 209) | fn per_action_require_prior_idle_rejects_duplicate() {
  function per_action_require_prior_idle_on_tap_hold_press (line 219) | fn per_action_require_prior_idle_on_tap_hold_press() {
  function per_action_require_prior_idle_on_tap_hold_release (line 231) | fn per_action_require_prior_idle_on_tap_hold_release() {
  function per_action_require_prior_idle_on_tap_hold_release_timeout (line 243) | fn per_action_require_prior_idle_on_tap_hold_release_timeout() {
  function per_action_require_prior_idle_on_tap_hold_press_timeout (line 255) | fn per_action_require_prior_idle_on_tap_hold_press_timeout() {
  function per_action_require_prior_idle_on_tap_hold_release_keys (line 267) | fn per_action_require_prior_idle_on_tap_hold_release_keys() {
  function per_action_require_prior_idle_on_tap_hold_except_keys (line 279) | fn per_action_require_prior_idle_on_tap_hold_except_keys() {
  function per_action_require_prior_idle_on_tap_hold_opposite_hand (line 291) | fn per_action_require_prior_idle_on_tap_hold_opposite_hand() {
  function per_action_require_prior_idle_on_tap_hold_release_tap_keys_release (line 304) | fn per_action_require_prior_idle_on_tap_hold_release_tap_keys_release() {

FILE: parser/src/cfg/tests/defhands.rs
  function opposite_hand_no_args (line 4) | fn opposite_hand_no_args() {
  function opposite_hand_one_arg (line 16) | fn opposite_hand_one_arg() {
  function opposite_hand_two_args (line 28) | fn opposite_hand_two_args() {
  function defhands_missing_for_opposite_hand (line 40) | fn defhands_missing_for_opposite_hand() {
  function defhands_duplicate_blocks (line 51) | fn defhands_duplicate_blocks() {
  function defhands_key_in_both_groups (line 64) | fn defhands_key_in_both_groups() {
  function defhands_duplicate_group_name (line 76) | fn defhands_duplicate_group_name() {
  function defhands_invalid_group_name (line 88) | fn defhands_invalid_group_name() {
  function opposite_hand_unknown_option (line 100) | fn opposite_hand_unknown_option() {
  function opposite_hand_trailing_keyword (line 112) | fn opposite_hand_trailing_keyword() {
  function opposite_hand_invalid_behavior (line 124) | fn opposite_hand_invalid_behavior() {
  function opposite_hand_duplicate_option (line 136) | fn opposite_hand_duplicate_option() {
  function defhands_valid_partial (line 148) | fn defhands_valid_partial() {

FILE: parser/src/cfg/tests/device_detect.rs
  function linux_device_parses_properly (line 6) | fn linux_device_parses_properly() {

FILE: parser/src/cfg/tests/environment.rs
  function parse_cfg_env (line 3) | fn parse_cfg_env(cfg: &str, env_vars: Vec<(String, String)>) -> Result<I...
  function parse_env (line 19) | fn parse_env() {

FILE: parser/src/cfg/tests/macros.rs
  function unsupported_action_in_macro_triggers_error (line 4) | fn unsupported_action_in_macro_triggers_error() {
  function incorrectly_configured_supported_action_in_macro_triggers_useful_error (line 16) | fn incorrectly_configured_supported_action_in_macro_triggers_useful_erro...

FILE: parser/src/cfg/unicode.rs
  function parse_unicode (line 7) | pub(crate) fn parse_unicode(ac_params: &[SExpr], s: &ParserState) -> Res...

FILE: parser/src/cfg/unmod.rs
  function parse_unmod (line 7) | pub(crate) fn parse_unmod(

FILE: parser/src/cfg/vars.rs
  function parse_vars (line 5) | pub(crate) fn parse_vars(
  function parse_list_var (line 38) | pub(crate) fn parse_list_var(expr: &Spanned<Vec<SExpr>>, vars: &HashMap<...
  function push_all_atoms (line 57) | pub(crate) fn push_all_atoms(exprs: &[SExpr], vars: &HashMap<String, SEx...

FILE: parser/src/cfg/zippychord.rs
  type ZchPossibleChords (line 38) | pub struct ZchPossibleChords();
    method is_empty (line 77) | pub fn is_empty(&self) -> bool {
  type ZchConfig (line 41) | pub struct ZchConfig();
  function parse_zippy_inner (line 43) | fn parse_zippy_inner(
  function parse_zippy (line 54) | pub(crate) fn parse_zippy(
  type ZchPossibleChords (line 75) | pub struct ZchPossibleChords(pub SubsetMap<u16, Arc<ZchChordOutput>>);
    method is_empty (line 77) | pub fn is_empty(&self) -> bool {
  type ZchInputKeys (line 87) | pub struct ZchInputKeys {
    method zchik_new (line 91) | pub fn zchik_new() -> Self {
    method zchik_contains (line 98) | pub fn zchik_contains(&self, osc: OsCode) -> bool {
    method zchik_insert (line 101) | pub fn zchik_insert(&mut self, osc: OsCode) {
    method zchik_remove (line 104) | pub fn zchik_remove(&mut self, osc: OsCode) {
    method zchik_len (line 107) | pub fn zchik_len(&self) -> usize {
    method zchik_clear (line 110) | pub fn zchik_clear(&mut self) {
    method zchik_keys (line 113) | pub fn zchik_keys(&self) -> &[u16] {
    method zchik_is_empty (line 116) | pub fn zchik_is_empty(&self) -> bool {
  type ZchSortedChord (line 124) | pub struct ZchSortedChord {
    method zch_insert (line 128) | pub fn zch_insert(&mut self, key: u16) {
  type ZchChordOutput (line 150) | pub struct ZchChordOutput {
  type ZchOutput (line 159) | pub enum ZchOutput {
    method osc (line 171) | pub fn osc(self) -> OsCode {
    method osc_and_is_noerase (line 184) | pub fn osc_and_is_noerase(self) -> (OsCode, bool) {
    method display_len (line 194) | pub fn display_len(outs: impl AsRef<[Self]>) -> i16 {
    method output_char_count (line 200) | pub fn output_char_count(self) -> i16 {
  type ZchSmartSpaceCfg (line 215) | pub enum ZchSmartSpaceCfg {
  type ZchConfig (line 222) | pub struct ZchConfig {
  method default (line 253) | fn default() -> Self {
  constant NO_ERASE (line 270) | const NO_ERASE: &str = "no-erase";
  constant SINGLE_OUTPUT_MULTI_KEY (line 271) | const SINGLE_OUTPUT_MULTI_KEY: &str = "single-output";
  type ZchIoMappingType (line 273) | enum ZchIoMappingType {
    method try_parse (line 278) | fn try_parse(expr: &SExpr, vars: Option<&HashMap<String, SExpr>>) -> R...
  function parse_zippy_inner (line 296) | pub(super) fn parse_zippy_inner(
  function parse_single_zippy_output_mapping (line 736) | fn parse_single_zippy_output_mapping(

FILE: parser/src/custom_action.rs
  type CustomAction (line 13) | pub enum CustomAction {
  type Btn (line 104) | pub enum Btn {
    method fmt (line 113) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type Coord (line 125) | pub struct Coord {
  type FakeKeyAction (line 131) | pub enum FakeKeyAction {
  type FakeKeyOnIdle (line 140) | pub struct FakeKeyOnIdle {
  type FakeKeyHoldForDuration (line 149) | pub struct FakeKeyHoldForDuration {
  type MWheelDirection (line 155) | pub enum MWheelDirection {
    method fmt (line 162) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    type Error (line 173) | type Error = ();
    method try_from (line 174) | fn try_from(value: OsCode) -> Result<Self, Self::Error> {
  type MWheelInertial (line 187) | pub struct MWheelInertial {
  type MoveDirection (line 195) | pub enum MoveDirection {
    method fmt (line 202) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type CapsWordCfg (line 213) | pub struct CapsWordCfg {
  type CapsWordRepressBehaviour (line 221) | pub enum CapsWordRepressBehaviour {
  type SequenceInputMode (line 237) | pub enum SequenceInputMode {
    method try_from_str (line 248) | pub fn try_from_str(s: &str) -> Result<Self> {
    method err_msg (line 257) | pub fn err_msg() -> String {
  constant SEQ_VISIBLE_BACKSPACED (line 243) | const SEQ_VISIBLE_BACKSPACED: &str = "visible-backspaced";
  constant SEQ_HIDDEN_SUPPRESSED (line 244) | const SEQ_HIDDEN_SUPPRESSED: &str = "hidden-suppressed";
  constant SEQ_HIDDEN_DELAY_TYPE (line 245) | const SEQ_HIDDEN_DELAY_TYPE: &str = "hidden-delay-type";
  constant LOG_LEVEL_DEBUG (line 264) | const LOG_LEVEL_DEBUG: &str = "debug";
  constant LOG_LEVEL_INFO (line 265) | const LOG_LEVEL_INFO: &str = "info";
  constant LOG_LEVEL_WARN (line 266) | const LOG_LEVEL_WARN: &str = "warn";
  constant LOG_LEVEL_ERROR (line 267) | const LOG_LEVEL_ERROR: &str = "error";
  constant LOG_LEVEL_NONE (line 268) | const LOG_LEVEL_NONE: &str = "none";
  type LogLevel (line 271) | pub enum LogLevel {
    method try_from_str (line 281) | pub fn try_from_str(s: &str) -> Result<Self> {
    method get_level (line 292) | pub fn get_level(&self) -> Option<log::Level> {
    method err_msg (line 302) | pub fn err_msg() -> String {
  type UnmodMods (line 310) | pub struct UnmodMods(u8);

FILE: parser/src/keys/linux.rs
  method as_u16_linux (line 6) | pub(super) const fn as_u16_linux(self) -> u16 {
  method from_u16_linux (line 9) | pub(super) const fn from_u16_linux(code: u16) -> Option<Self> {
  method from (line 768) | fn from(btn: Btn) -> Self {

FILE: parser/src/keys/macos.rs
  type PageCode (line 5) | pub struct PageCode {
    type Error (line 11) | type Error = &'static str;
    method try_from (line 12) | fn try_from(item: OsCode) -> Result<Self, Self::Error> {
  type Error (line 694) | type Error = &'static str;
  method try_from (line 695) | fn try_from(item: PageCode) -> Result<Self, Self::Error> {
  method as_u16_macos (line 1339) | pub(super) const fn as_u16_macos(self) -> u16 {
  method from_u16_macos (line 1342) | pub(super) const fn from_u16_macos(code: u16) -> Option<Self> {

FILE: parser/src/keys/mappings.rs
  method from (line 5) | fn from(item: KeyCode) -> Self {
  method from (line 11) | fn from(item: OsCode) -> KeyCode {
  function roundtrip_oscode_keycode (line 17) | fn roundtrip_oscode_keycode() {

FILE: parser/src/keys/mod.rs
  type Platform (line 24) | pub enum Platform {
  function replace_custom_str_oscode_mapping (line 118) | pub fn replace_custom_str_oscode_mapping(mapping: &HashMap<String, OsCod...
  function clear_custom_str_oscode_mapping (line 127) | pub fn clear_custom_str_oscode_mapping() {
  function add_default_str_osc_mappings (line 136) | fn add_default_str_osc_mappings(mapping: &mut HashMap<String, OsCode>) {
  function str_to_oscode (line 172) | pub fn str_to_oscode(s: &str) -> Option<OsCode> {
  type OsCode (line 398) | pub enum OsCode {
    method as_u16 (line 34) | pub fn as_u16(self) -> u16 {
    method from_u16 (line 52) | pub fn from_u16(code: u16) -> Option<Self> {
    method is_modifier (line 70) | pub fn is_modifier(self) -> bool {
    method is_zippy_ignored (line 85) | pub fn is_zippy_ignored(self) -> bool {
    method is_mouse_code (line 1177) | pub fn is_mouse_code(&self) -> bool {
    method fmt (line 1196) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    type Error (line 1212) | type Error = ();
    method try_from (line 1213) | fn try_from(item: usize) -> Result<Self, Self::Error> {
    method from (line 1222) | fn from(item: u32) -> Self {
    method from (line 1228) | fn from(item: u16) -> Self {
    method from (line 1263) | fn from(item: &KeyCode) -> Self {
  function parser_key_max_lt_keyberon_key_max (line 1207) | fn parser_key_max_lt_keyberon_key_max() {
  function from (line 1234) | fn from(item: OsCode) -> Self {
  function from (line 1240) | fn from(item: OsCode) -> Self {
  function from (line 1246) | fn from(item: OsCode) -> Self {
  function from (line 1252) | fn from(item: OsCode) -> Self {
  method from (line 1258) | fn from(item: &OsCode) -> KeyCode {

FILE: parser/src/keys/windows.rs
  type VirtualKey (line 15) | pub type VirtualKey = u16;
  constant VK_KPENTER_FAKE (line 16) | pub const VK_KPENTER_FAKE: VirtualKey = 232u16;
  constant VK_0 (line 17) | pub const VK_0: VirtualKey = 48u16;
  constant VK_1 (line 18) | pub const VK_1: VirtualKey = 49u16;
  constant VK_2 (line 19) | pub const VK_2: VirtualKey = 50u16;
  constant VK_3 (line 20) | pub const VK_3: VirtualKey = 51u16;
  constant VK_4 (line 21) | pub const VK_4: VirtualKey = 52u16;
  constant VK_5 (line 22) | pub const VK_5: VirtualKey = 53u16;
  constant VK_6 (line 23) | pub const VK_6: VirtualKey = 54u16;
  constant VK_7 (line 24) | pub const VK_7: VirtualKey = 55u16;
  constant VK_8 (line 25) | pub const VK_8: VirtualKey = 56u16;
  constant VK_9 (line 26) | pub const VK_9: VirtualKey = 57u16;
  constant VK_A (line 27) | pub const VK_A: VirtualKey = 65u16;
  constant VK_ABNT_C1 (line 28) | pub const VK_ABNT_C1: VirtualKey = 193u16;
  constant VK_ABNT_C2 (line 29) | pub const VK_ABNT_C2: VirtualKey = 194u16;
  constant VK_ACCEPT (line 30) | pub const VK_ACCEPT: VirtualKey = 30u16;
  constant VK_ADD (line 31) | pub const VK_ADD: VirtualKey = 107u16;
  constant VK_APPS (line 32) | pub const VK_APPS: VirtualKey = 93u16;
  constant VK_ATTN (line 33) | pub const VK_ATTN: VirtualKey = 246u16;
  constant VK_B (line 34) | pub const VK_B: VirtualKey = 66u16;
  constant VK_BACK (line 35) | pub const VK_BACK: VirtualKey = 8u16;
  constant VK_BROWSER_BACK (line 36) | pub const VK_BROWSER_BACK: VirtualKey = 166u16;
  constant VK_BROWSER_FAVORITES (line 37) | pub const VK_BROWSER_FAVORITES: VirtualKey = 171u16;
  constant VK_BROWSER_FORWARD (line 38) | pub const VK_BROWSER_FORWARD: VirtualKey = 167u16;
  constant VK_BROWSER_HOME (line 39) | pub const VK_BROWSER_HOME: VirtualKey = 172u16;
  constant VK_BROWSER_REFRESH (line 40) | pub const VK_BROWSER_REFRESH: VirtualKey = 168u16;
  constant VK_BROWSER_SEARCH (line 41) | pub const VK_BROWSER_SEARCH: VirtualKey = 170u16;
  constant VK_BROWSER_STOP (line 42) | pub const VK_BROWSER_STOP: VirtualKey = 169u16;
  constant VK_C (line 43) | pub const VK_C: VirtualKey = 67u16;
  constant VK_CANCEL (line 44) | pub const VK_CANCEL: VirtualKey = 3u16;
  constant VK_CAPITAL (line 45) | pub const VK_CAPITAL: VirtualKey = 20u16;
  constant VK_CLEAR (line 46) | pub const VK_CLEAR: VirtualKey = 12u16;
  constant VK_CONTROL (line 47) | pub const VK_CONTROL: VirtualKey = 17u16;
  constant VK_CONVERT (line 48) | pub const VK_CONVERT: VirtualKey = 28u16;
  constant VK_CRSEL (line 49) | pub const VK_CRSEL: VirtualKey = 247u16;
  constant VK_D (line 50) | pub const VK_D: VirtualKey = 68u16;
  constant VK_DBE_ALPHANUMERIC (line 51) | pub const VK_DBE_ALPHANUMERIC: VirtualKey = 240u16;
  constant VK_DBE_CODEINPUT (line 52) | pub const VK_DBE_CODEINPUT: VirtualKey = 250u16;
  constant VK_DBE_DBCSCHAR (line 53) | pub const VK_DBE_DBCSCHAR: VirtualKey = 244u16;
  constant VK_DBE_DETERMINESTRING (line 54) | pub const VK_DBE_DETERMINESTRING: VirtualKey = 252u16;
  constant VK_DBE_ENTERDLGCONVERSIONMODE (line 55) | pub const VK_DBE_ENTERDLGCONVERSIONMODE: VirtualKey = 253u16;
  constant VK_DBE_ENTERIMECONFIGMODE (line 56) | pub const VK_DBE_ENTERIMECONFIGMODE: VirtualKey = 248u16;
  constant VK_DBE_ENTERWORDREGISTERMODE (line 57) | pub const VK_DBE_ENTERWORDREGISTERMODE: VirtualKey = 247u16;
  constant VK_DBE_FLUSHSTRING (line 58) | pub const VK_DBE_FLUSHSTRING: VirtualKey = 249u16;
  constant VK_DBE_HIRAGANA (line 59) | pub const VK_DBE_HIRAGANA: VirtualKey = 242u16;
  constant VK_DBE_KATAKANA (line 60) | pub const VK_DBE_KATAKANA: VirtualKey = 241u16;
  constant VK_DBE_NOCODEINPUT (line 61) | pub const VK_DBE_NOCODEINPUT: VirtualKey = 251u16;
  constant VK_DBE_NOROMAN (line 62) | pub const VK_DBE_NOROMAN: VirtualKey = 246u16;
  constant VK_DBE_ROMAN (line 63) | pub const VK_DBE_ROMAN: VirtualKey = 245u16;
  constant VK_DBE_SBCSCHAR (line 64) | pub const VK_DBE_SBCSCHAR: VirtualKey = 243u16;
  constant VK_DECIMAL (line 65) | pub const VK_DECIMAL: VirtualKey = 110u16;
  constant VK_DELETE (line 66) | pub const VK_DELETE: VirtualKey = 46u16;
  constant VK_DIVIDE (line 67) | pub const VK_DIVIDE: VirtualKey = 111u16;
  constant VK_DOWN (line 68) | pub const VK_DOWN: VirtualKey = 40u16;
  constant VK_E (line 69) | pub const VK_E: VirtualKey = 69u16;
  constant VK_END (line 70) | pub const VK_END: VirtualKey = 35u16;
  constant VK_EREOF (line 71) | pub const VK_EREOF: VirtualKey = 249u16;
  constant VK_ESCAPE (line 72) | pub const VK_ESCAPE: VirtualKey = 27u16;
  constant VK_EXECUTE (line 73) | pub const VK_EXECUTE: VirtualKey = 43u16;
  constant VK_EXSEL (line 74) | pub const VK_EXSEL: VirtualKey = 248u16;
  constant VK_F (line 75) | pub const VK_F: VirtualKey = 70u16;
  constant VK_F1 (line 76) | pub const VK_F1: VirtualKey = 112u16;
  constant VK_F10 (line 77) | pub const VK_F10: VirtualKey = 121u16;
  constant VK_F11 (line 78) | pub const VK_F11: VirtualKey = 122u16;
  constant VK_F12 (line 79) | pub const VK_F12: VirtualKey = 123u16;
  constant VK_F13 (line 80) | pub const VK_F13: VirtualKey = 124u16;
  constant VK_F14 (line 81) | pub const VK_F14: VirtualKey = 125u16;
  constant VK_F15 (line 82) | pub const VK_F15: VirtualKey = 126u16;
  constant VK_F16 (line 83) | pub const VK_F16: VirtualKey = 127u16;
  constant VK_F17 (line 84) | pub const VK_F17: VirtualKey = 128u16;
  constant VK_F18 (line 85) | pub const VK_F18: VirtualKey = 129u16;
  constant VK_F19 (line 86) | pub const VK_F19: VirtualKey = 130u16;
  constant VK_F2 (line 87) | pub const VK_F2: VirtualKey = 113u16;
  constant VK_F20 (line 88) | pub const VK_F20: VirtualKey = 131u16;
  constant VK_F21 (line 89) | pub const VK_F21: VirtualKey = 132u16;
  constant VK_F22 (line 90) | pub const VK_F22: VirtualKey = 133u16;
  constant VK_F23 (line 91) | pub const VK_F23: VirtualKey = 134u16;
  constant VK_F24 (line 92) | pub const VK_F24: VirtualKey = 135u16;
  constant VK_F3 (line 93) | pub const VK_F3: VirtualKey = 114u16;
  constant VK_F4 (line 94) | pub const VK_F4: VirtualKey = 115u16;
  constant VK_F5 (line 95) | pub const VK_F5: VirtualKey = 116u16;
  constant VK_F6 (line 96) | pub const VK_F6: VirtualKey = 117u16;
  constant VK_F7 (line 97) | pub const VK_F7: VirtualKey = 118u16;
  constant VK_F8 (line 98) | pub const VK_F8: VirtualKey = 119u16;
  constant VK_F9 (line 99) | pub const VK_F9: VirtualKey = 120u16;
  constant VK_FINAL (line 100) | pub const VK_FINAL: VirtualKey = 24u16;
  constant VK_G (line 101) | pub const VK_G: VirtualKey = 71u16;
  constant VK_GAMEPAD_A (line 102) | pub const VK_GAMEPAD_A: VirtualKey = 195u16;
  constant VK_GAMEPAD_B (line 103) | pub const VK_GAMEPAD_B: VirtualKey = 196u16;
  constant VK_GAMEPAD_DPAD_DOWN (line 104) | pub const VK_GAMEPAD_DPAD_DOWN: VirtualKey = 204u16;
  constant VK_GAMEPAD_DPAD_LEFT (line 105) | pub const VK_GAMEPAD_DPAD_LEFT: VirtualKey = 205u16;
  constant VK_GAMEPAD_DPAD_RIGHT (line 106) | pub const VK_GAMEPAD_DPAD_RIGHT: VirtualKey = 206u16;
  constant VK_GAMEPAD_DPAD_UP (line 107) | pub const VK_GAMEPAD_DPAD_UP: VirtualKey = 203u16;
  constant VK_GAMEPAD_LEFT_SHOULDER (line 108) | pub const VK_GAMEPAD_LEFT_SHOULDER: VirtualKey = 200u16;
  constant VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON (line 109) | pub const VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON: VirtualKey = 209u16;
  constant VK_GAMEPAD_LEFT_THUMBSTICK_DOWN (line 110) | pub const VK_GAMEPAD_LEFT_THUMBSTICK_DOWN: VirtualKey = 212u16;
  constant VK_GAMEPAD_LEFT_THUMBSTICK_LEFT (line 111) | pub const VK_GAMEPAD_LEFT_THUMBSTICK_LEFT: VirtualKey = 214u16;
  constant VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT (line 112) | pub const VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT: VirtualKey = 213u16;
  constant VK_GAMEPAD_LEFT_THUMBSTICK_UP (line 113) | pub const VK_GAMEPAD_LEFT_THUMBSTICK_UP: VirtualKey = 211u16;
  constant VK_GAMEPAD_LEFT_TRIGGER (line 114) | pub const VK_GAMEPAD_LEFT_TRIGGER: VirtualKey = 201u16;
  constant VK_GAMEPAD_MENU (line 115) | pub const VK_GAMEPAD_MENU: VirtualKey = 207u16;
  constant VK_GAMEPAD_RIGHT_SHOULDER (line 116) | pub const VK_GAMEPAD_RIGHT_SHOULDER: VirtualKey = 199u16;
  constant VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON (line 117) | pub const VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON: VirtualKey = 210u16;
  constant VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN (line 118) | pub const VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN: VirtualKey = 216u16;
  constant VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT (line 119) | pub const VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT: VirtualKey = 218u16;
  constant VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT (line 120) | pub const VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT: VirtualKey = 217u16;
  constant VK_GAMEPAD_RIGHT_THUMBSTICK_UP (line 121) | pub const VK_GAMEPAD_RIGHT_THUMBSTICK_UP: VirtualKey = 215u16;
  constant VK_GAMEPAD_RIGHT_TRIGGER (line 122) | pub const VK_GAMEPAD_RIGHT_TRIGGER: VirtualKey = 202u16;
  constant VK_GAMEPAD_VIEW (line 123) | pub const VK_GAMEPAD_VIEW: VirtualKey = 208u16;
  constant VK_GAMEPAD_X (line 124) | pub const VK_GAMEPAD_X: VirtualKey = 197u16;
  constant VK_GAMEPAD_Y (line 125) | pub const VK_GAMEPAD_Y: VirtualKey = 198u16;
  constant VK_H (line 126) | pub const VK_H: VirtualKey = 72u16;
  constant VK_HANGEUL (line 127) | pub const VK_HANGEUL: VirtualKey = 21u16;
  constant VK_HANGUL (line 128) | pub const VK_HANGUL: VirtualKey = 21u16;
  constant VK_HANJA (line 129) | pub const VK_HANJA: VirtualKey = 25u16;
  constant VK_HELP (line 130) | pub const VK_HELP: VirtualKey = 47u16;
  constant VK_HOME (line 131) | pub const VK_HOME: VirtualKey = 36u16;
  constant VK_I (line 132) | pub const VK_I: VirtualKey = 73u16;
  constant VK_ICO_00 (line 133) | pub const VK_ICO_00: VirtualKey = 228u16;
  constant VK_ICO_CLEAR (line 134) | pub const VK_ICO_CLEAR: VirtualKey = 230u16;
  constant VK_ICO_HELP (line 135) | pub const VK_ICO_HELP: VirtualKey = 227u16;
  constant VK_IME_OFF (line 136) | pub const VK_IME_OFF: VirtualKey = 26u16;
  constant VK_IME_ON (line 137) | pub const VK_IME_ON: VirtualKey = 22u16;
  constant VK_INSERT (line 138) | pub const VK_INSERT: VirtualKey = 45u16;
  constant VK_J (line 139) | pub const VK_J: VirtualKey = 74u16;
  constant VK_JUNJA (line 140) | pub const VK_JUNJA: VirtualKey = 23u16;
  constant VK_K (line 141) | pub const VK_K: VirtualKey = 75u16;
  constant VK_KANA (line 142) | pub const VK_KANA: VirtualKey = 21u16;
  constant VK_KANJI (line 143) | pub const VK_KANJI: VirtualKey = 25u16;
  constant VK_L (line 144) | pub const VK_L: VirtualKey = 76u16;
  constant VK_LAUNCH_APP1 (line 145) | pub const VK_LAUNCH_APP1: VirtualKey = 182u16;
  constant VK_LAUNCH_APP2 (line 146) | pub const VK_LAUNCH_APP2: VirtualKey = 183u16;
  constant VK_LAUNCH_MAIL (line 147) | pub const VK_LAUNCH_MAIL: VirtualKey = 180u16;
  constant VK_LAUNCH_MEDIA_SELECT (line 148) | pub const VK_LAUNCH_MEDIA_SELECT: VirtualKey = 181u16;
  constant VK_LBUTTON (line 149) | pub const VK_LBUTTON: VirtualKey = 1u16;
  constant VK_LCONTROL (line 150) | pub const VK_LCONTROL: VirtualKey = 162u16;
  constant VK_LEFT (line 151) | pub const VK_LEFT: VirtualKey = 37u16;
  constant VK_LMENU (line 152) | pub const VK_LMENU: VirtualKey = 164u16;
  constant VK_LSHIFT (line 153) | pub const VK_LSHIFT: VirtualKey = 160u16;
  constant VK_LWIN (line 154) | pub const VK_LWIN: VirtualKey = 91u16;
  constant VK_M (line 155) | pub const VK_M: VirtualKey = 77u16;
  constant VK_MBUTTON (line 156) | pub const VK_MBUTTON: VirtualKey = 4u16;
  constant VK_MEDIA_NEXT_TRACK (line 157) | pub const VK_MEDIA_NEXT_TRACK: VirtualKey = 176u16;
  constant VK_MEDIA_PLAY_PAUSE (line 158) | pub const VK_MEDIA_PLAY_PAUSE: VirtualKey = 179u16;
  constant VK_MEDIA_PREV_TRACK (line 159) | pub const VK_MEDIA_PREV_TRACK: VirtualKey = 177u16;
  constant VK_MEDIA_STOP (line 160) | pub const VK_MEDIA_STOP: VirtualKey = 178u16;
  constant VK_MENU (line 161) | pub const VK_MENU: VirtualKey = 18u16;
  constant VK_MODECHANGE (line 162) | pub const VK_MODECHANGE: VirtualKey = 31u16;
  constant VK_MULTIPLY (line 163) | pub const VK_MULTIPLY: VirtualKey = 106u16;
  constant VK_N (line 164) | pub const VK_N: VirtualKey = 78u16;
  constant VK_NAVIGATION_ACCEPT (line 165) | pub const VK_NAVIGATION_ACCEPT: VirtualKey = 142u16;
  constant VK_NAVIGATION_CANCEL (line 166) | pub const VK_NAVIGATION_CANCEL: VirtualKey = 143u16;
  constant VK_NAVIGATION_DOWN (line 167) | pub const VK_NAVIGATION_DOWN: VirtualKey = 139u16;
  constant VK_NAVIGATION_LEFT (line 168) | pub const VK_NAVIGATION_LEFT: VirtualKey = 140u16;
  constant VK_NAVIGATION_MENU (line 169) | pub const VK_NAVIGATION_MENU: VirtualKey = 137u16;
  constant VK_NAVIGATION_RIGHT (line 170) | pub const VK_NAVIGATION_RIGHT: VirtualKey = 141u16;
  constant VK_NAVIGATION_UP (line 171) | pub const VK_NAVIGATION_UP: VirtualKey = 138u16;
  constant VK_NAVIGATION_VIEW (line 172) | pub const VK_NAVIGATION_VIEW: VirtualKey = 136u16;
  constant VK_NEXT (line 173) | pub const VK_NEXT: VirtualKey = 34u16;
  constant VK_NONAME (line 174) | pub const VK_NONAME: VirtualKey = 252u16;
  constant VK_NONCONVERT (line 175) | pub const VK_NONCONVERT: VirtualKey = 29u16;
  constant VK_NUMLOCK (line 176) | pub const VK_NUMLOCK: VirtualKey = 144u16;
  constant VK_NUMPAD0 (line 177) | pub const VK_NUMPAD0: VirtualKey = 96u16;
  constant VK_NUMPAD1 (line 178) | pub const VK_NUMPAD1: VirtualKey = 97u16;
  constant VK_NUMPAD2 (line 179) | pub const VK_NUMPAD2: VirtualKey = 98u16;
  constant VK_NUMPAD3 (line 180) | pub const VK_NUMPAD3: VirtualKey = 99u16;
  constant VK_NUMPAD4 (line 181) | pub const VK_NUMPAD4: VirtualKey = 100u16;
  constant VK_NUMPAD5 (line 182) | pub const VK_NUMPAD5: VirtualKey = 101u16;
  constant VK_NUMPAD6 (line 183) | pub const VK_NUMPAD6: VirtualKey = 102u16;
  constant VK_NUMPAD7 (line 184) | pub const VK_NUMPAD7: VirtualKey = 103u16;
  constant VK_NUMPAD8 (line 185) | pub const VK_NUMPAD8: VirtualKey = 104u16;
  constant VK_NUMPAD9 (line 186) | pub const VK_NUMPAD9: VirtualKey = 105u16;
  constant VK_O (line 187) | pub const VK_O: VirtualKey = 79u16;
  constant VK_OEM_1 (line 188) | pub const VK_OEM_1: VirtualKey = 186u16;
  constant VK_OEM_102 (line 189) | pub const VK_OEM_102: VirtualKey = 226u16;
  constant VK_OEM_2 (line 190) | pub const VK_OEM_2: VirtualKey = 191u16;
  constant VK_OEM_3 (line 191) | pub const VK_OEM_3: VirtualKey = 192u16;
  constant VK_OEM_4 (line 192) | pub const VK_OEM_4: VirtualKey = 219u16;
  constant VK_OEM_5 (line 193) | pub const VK_OEM_5: VirtualKey = 220u16;
  constant VK_OEM_6 (line 194) | pub const VK_OEM_6: VirtualKey = 221u16;
  constant VK_OEM_7 (line 195) | pub const VK_OEM_7: VirtualKey = 222u16;
  constant VK_OEM_8 (line 196) | pub const VK_OEM_8: VirtualKey = 223u16;
  constant VK_OEM_ATTN (line 197) | pub const VK_OEM_ATTN: VirtualKey = 240u16;
  constant VK_OEM_AUTO (line 198) | pub const VK_OEM_AUTO: VirtualKey = 243u16;
  constant VK_OEM_AX (line 199) | pub const VK_OEM_AX: VirtualKey = 225u16;
  constant VK_OEM_BACKTAB (line 200) | pub const VK_OEM_BACKTAB: VirtualKey = 245u16;
  constant VK_OEM_CLEAR (line 201) | pub const VK_OEM_CLEAR: VirtualKey = 254u16;
  constant VK_OEM_COMMA (line 202) | pub const VK_OEM_COMMA: VirtualKey = 188u16;
  constant VK_OEM_COPY (line 203) | pub const VK_OEM_COPY: VirtualKey = 242u16;
  constant VK_OEM_CUSEL (line 204) | pub const VK_OEM_CUSEL: VirtualKey = 239u16;
  constant VK_OEM_ENLW (line 205) | pub const VK_OEM_ENLW: VirtualKey = 244u16;
  constant VK_OEM_FINISH (line 206) | pub const VK_OEM_FINISH: VirtualKey = 241u16;
  constant VK_OEM_FJ_JISHO (line 207) | pub const VK_OEM_FJ_JISHO: VirtualKey = 146u16;
  constant VK_OEM_FJ_LOYA (line 208) | pub const VK_OEM_FJ_LOYA: VirtualKey = 149u16;
  constant VK_OEM_FJ_MASSHOU (line 209) | pub const VK_OEM_FJ_MASSHOU: VirtualKey = 147u16;
  constant VK_OEM_FJ_ROYA (line 210) | pub const VK_OEM_FJ_ROYA: VirtualKey = 150u16;
  constant VK_OEM_FJ_TOUROKU (line 211) | pub const VK_OEM_FJ_TOUROKU: VirtualKey = 148u16;
  constant VK_OEM_JUMP (line 212) | pub const VK_OEM_JUMP: VirtualKey = 234u16;
  constant VK_OEM_MINUS (line 213) | pub const VK_OEM_MINUS: VirtualKey = 189u16;
  constant VK_OEM_NEC_EQUAL (line 214) | pub const VK_OEM_NEC_EQUAL: VirtualKey = 146u16;
  constant VK_OEM_PA1 (line 215) | pub const VK_OEM_PA1: VirtualKey = 235u16;
  constant VK_OEM_PA2 (line 216) | pub const VK_OEM_PA2: VirtualKey = 236u16;
  constant VK_OEM_PA3 (line 217) | pub const VK_OEM_PA3: VirtualKey = 237u16;
  constant VK_OEM_PERIOD (line 218) | pub const VK_OEM_PERIOD: VirtualKey = 190u16;
  constant VK_OEM_PLUS (line 219) | pub const VK_OEM_PLUS: VirtualKey = 187u16;
  constant VK_OEM_RESET (line 220) | pub const VK_OEM_RESET: VirtualKey = 233u16;
  constant VK_OEM_WSCTRL (line 221) | pub const VK_OEM_WSCTRL: VirtualKey = 238u16;
  constant VK_P (line 222) | pub const VK_P: VirtualKey = 80u16;
  constant VK_PA1 (line 223) | pub const VK_PA1: VirtualKey = 253u16;
  constant VK_PACKET (line 224) | pub const VK_PACKET: VirtualKey = 231u16;
  constant VK_PAUSE (line 225) | pub const VK_PAUSE: VirtualKey = 19u16;
  constant VK_PLAY (line 226) | pub const VK_PLAY: VirtualKey = 250u16;
  constant VK_PRINT (line 227) | pub const VK_PRINT: VirtualKey = 42u16;
  constant VK_PRIOR (line 228) | pub const VK_PRIOR: VirtualKey = 33u16;
  constant VK_PROCESSKEY (line 229) | pub const VK_PROCESSKEY: VirtualKey = 229u16;
  constant VK_Q (line 230) | pub const VK_Q: VirtualKey = 81u16;
  constant VK_R (line 231) | pub const VK_R: VirtualKey = 82u16;
  constant VK_RBUTTON (line 232) | pub const VK_RBUTTON: VirtualKey = 2u16;
  constant VK_RCONTROL (line 233) | pub const VK_RCONTROL: VirtualKey = 163u16;
  constant VK_RETURN (line 234) | pub const VK_RETURN: VirtualKey = 13u16;
  constant VK_RIGHT (line 235) | pub const VK_RIGHT: VirtualKey = 39u16;
  constant VK_RMENU (line 236) | pub const VK_RMENU: VirtualKey = 165u16;
  constant VK_RSHIFT (line 237) | pub const VK_RSHIFT: VirtualKey = 161u16;
  constant VK_RWIN (line 238) | pub const VK_RWIN: VirtualKey = 92u16;
  constant VK_S (line 239) | pub const VK_S: VirtualKey = 83u16;
  constant VK_SCROLL (line 240) | pub const VK_SCROLL: VirtualKey = 145u16;
  constant VK_SELECT (line 241) | pub const VK_SELECT: VirtualKey = 41u16;
  constant VK_SEPARATOR (line 242) | pub const VK_SEPARATOR: VirtualKey = 108u16;
  constant VK_SHIFT (line 243) | pub const VK_SHIFT: VirtualKey = 16u16;
  constant VK_SLEEP (line 244) | pub const VK_SLEEP: VirtualKey = 95u16;
  constant VK_SNAPSHOT (line 245) | pub const VK_SNAPSHOT: VirtualKey = 44u16;
  constant VK_SPACE (line 246) | pub const VK_SPACE: VirtualKey = 32u16;
  constant VK_SUBTRACT (line 247) | pub const VK_SUBTRACT: VirtualKey = 109u16;
  constant VK_T (line 248) | pub const VK_T: VirtualKey = 84u16;
  constant VK_TAB (line 249) | pub const VK_TAB: VirtualKey = 9u16;
  constant VK_U (line 250) | pub const VK_U: VirtualKey = 85u16;
  constant VK_UP (line 251) | pub const VK_UP: VirtualKey = 38u16;
  constant VK_V (line 252) | pub const VK_V: VirtualKey = 86u16;
  constant VK_VOLUME_DOWN (line 253) | pub const VK_VOLUME_DOWN: VirtualKey = 174u16;
  constant VK_VOLUME_MUTE (line 254) | pub const VK_VOLUME_MUTE: VirtualKey = 173u16;
  constant VK_VOLUME_UP (line 255) | pub const VK_VOLUME_UP: VirtualKey = 175u16;
  constant VK_W (line 256) | pub const VK_W: VirtualKey = 87u16;
  constant VK_X (line 257) | pub const VK_X: VirtualKey = 88u16;
  constant VK_XBUTTON1 (line 258) | pub const VK_XBUTTON1: VirtualKey = 5u16;
  constant VK_XBUTTON2 (line 259) | pub const VK_XBUTTON2: VirtualKey = 6u16;
  constant VK_Y (line 260) | pub const VK_Y: VirtualKey = 89u16;
  constant VK_Z (line 261) | pub const VK_Z: VirtualKey = 90u16;
  constant VK_ZOOM (line 262) | pub const VK_ZOOM: VirtualKey = 251u16;
  constant VK_NONE (line 263) | pub const VK_NONE: VirtualKey = 255u16;
  method from_u16_windows (line 268) | pub(super) const fn from_u16_windows(code: u16) -> Option<Self> {
  method as_u16_windows (line 912) | pub(super) const fn as_u16_windows(self) -> u16 {

FILE: parser/src/layers.rs
  constant KEYS_IN_ROW (line 12) | pub const KEYS_IN_ROW: usize = OsCode::KEY_MAX as usize;
  constant LAYER_ROWS (line 13) | pub const LAYER_ROWS: usize = 2;
  constant DEFAULT_ACTION (line 14) | pub const DEFAULT_ACTION: KanataAction = KanataAction::KeyCode(KeyCode::...
  type IntermediateLayers (line 16) | pub type IntermediateLayers = Box<[[Row; LAYER_ROWS]]>;
  type KLayers (line 18) | pub type KLayers =
  type KanataLayers (line 21) | pub struct KanataLayers {
    method fmt (line 28) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    method new (line 52) | pub(crate) unsafe fn new(layers: KLayers, allocations: Arc<Allocations...
    method get (line 59) | pub(crate) fn get(&self) -> (KLayers, Arc<Allocations>) {
  type Row (line 33) | pub type Row = [kanata_keyberon::action::Action<'static, &'static &'stat...
  function new_layers (line 36) | pub fn new_layers(layers: usize) -> IntermediateLayers {

FILE: parser/src/lsp_hints.rs
  type LspHints (line 8) | pub struct LspHints {}
  type HashMap (line 14) | type HashMap<K, V> = rustc_hash::FxHashMap<K, V>;
  type LspHints (line 17) | pub struct LspHints {
  type InactiveCode (line 24) | pub struct InactiveCode {
  type DefinitionLocations (line 30) | pub struct DefinitionLocations {
  type ReferenceLocations (line 39) | pub struct ReferenceLocations {
  type ReferencesMap (line 49) | pub struct ReferencesMap(pub HashMap<String, Vec<Span>>);
    method push_from_atom (line 53) | pub(crate) fn push_from_atom(&mut self, atom: &Spanned<String>) {
    method push (line 62) | pub(crate) fn push(&mut self, name: &str, span: Span) {
  function set_layer_change_lsp_hint (line 74) | pub(crate) fn set_layer_change_lsp_hint(layer_name_expr: &SExpr, lsp_hin...

FILE: parser/src/sequences.rs
  constant MASK_KEYCODES (line 3) | pub const MASK_KEYCODES: u16 = 0x03FF;
  constant MASK_MODDED (line 4) | pub const MASK_MODDED: u16 = 0xFC00;
  constant KEY_OVERLAP (line 5) | pub const KEY_OVERLAP: KeyCode = KeyCode::ErrorRollOver;
  constant KEY_OVERLAP_MARKER (line 6) | pub const KEY_OVERLAP_MARKER: u16 = 0x0400;
  function mod_mask_for_keycode (line 8) | pub fn mod_mask_for_keycode(kc: KeyCode) -> u16 {
  function keys_fit_within_mask (line 26) | fn keys_fit_within_mask() {

FILE: parser/src/subset.rs
  type SubsetMap (line 50) | pub struct SubsetMap<K, V> {
  type SsmKeyValue (line 55) | struct SsmKeyValue<K, V> {
  function ssmkv_new (line 64) | fn ssmkv_new(key: impl AsRef<[K]>, value: V) -> Self {
  type GetOrIsSubsetOfKnownKey (line 73) | pub enum GetOrIsSubsetOfKnownKey<T> {
  type SsmKeyExistedBeforeInsert (line 80) | pub enum SsmKeyExistedBeforeInsert {
  method default (line 92) | fn default() -> Self {
  function ssm_new (line 102) | pub fn ssm_new() -> Self {
  function ssm_insert (line 109) | pub fn ssm_insert(&mut self, mut key: impl AsMut<[K]>, val: V) -> SsmKey...
  function ssm_insert_ksorted (line 116) | pub fn ssm_insert_ksorted(
  function ssm_get_or_is_subset (line 142) | pub fn ssm_get_or_is_subset(&self, mut key: impl AsMut<[K]>) -> GetOrIsS...
  function ssm_get_or_is_subset_ksorted (line 149) | pub fn ssm_get_or_is_subset_ksorted(
  function is_empty (line 180) | pub fn is_empty(&self) -> bool {

FILE: parser/src/trie.rs
  type TrieKeyElement (line 6) | pub type TrieKeyElement = u16;
  type Trie (line 9) | pub struct Trie<T> {
  type GetOrDescendentExistsResult (line 14) | pub enum GetOrDescendentExistsResult<T> {
  method default (line 23) | fn default() -> Self {
  function key_len (line 28) | fn key_len(k: impl AsRef<[u16]>) -> usize {
  function new (line 34) | pub fn new() -> Self {
  function ancestor_exists (line 40) | pub fn ancestor_exists(&self, key: impl AsRef<[u16]>) -> bool {
  function descendant_exists (line 46) | pub fn descendant_exists(&self, key: impl AsRef<[u16]>) -> bool {
  function insert (line 53) | pub fn insert(&mut self, key: impl AsRef<[u16]>, val: T) {
  function get_or_descendant_exists (line 57) | pub fn get_or_descendant_exists(&self, key: impl AsRef<[u16]>) -> GetOrD...
  function is_empty (line 74) | pub fn is_empty(&self) -> bool {

FILE: simulated_input/src/sim.rs
  function default_sim (line 9) | pub fn default_sim() -> Vec<PathBuf> {
  type Args (line 35) | struct Args {
  function log_init (line 85) | fn log_init() {
  function cli_init_fsim (line 104) | fn cli_init_fsim() -> Result<(ValidatedArgs, Vec<PathBuf>, Option<String...
  function split_at_1 (line 150) | fn split_at_1(s: &str) -> (&str, &str) {
  function parse_fakekey_spec (line 157) | fn parse_fakekey_spec(spec: &str) -> Result<(&str, FakeKeyAction)> {
  function apply_fakekey_action (line 181) | fn apply_fakekey_action(k: &mut Kanata, name: &str, action: FakeKeyActio...
  function apply_layer_switch (line 191) | fn apply_layer_switch(k: &mut Kanata, layer_name: &str) -> Result<()> {
  type LogFmtT (line 202) | pub enum LogFmtT {
  function kbd_out_log (line 209) | fn kbd_out_log(
  function main_impl (line 249) | fn main_impl() -> Result<()> {
  function main (line 396) | fn main() -> Result<()> {

FILE: simulated_passthru/src/key_in.rs
  function input_ev_listener (line 13) | pub extern "win64" fn input_ev_listener(vk: c_uint, sc: c_uint, up: c_in...

FILE: simulated_passthru/src/key_out.rs
  type CbOutEvFn (line 11) | type CbOutEvFn = dyn Fn(i64, i64, i64) -> i64 + 'static;
  function set_cb_out_ev (line 27) | pub fn set_cb_out_ev(cb_addr: c_longlong) -> Result<()> {
  function set_cb_out_ev (line 42) | fn set_cb_out_ev(cb_addr: c_longlong) -> Result<()> {
  function send_out_ev (line 48) | pub fn send_out_ev(in_ev: InputEvent) -> Result<()> {
  function output_ev_check (line 86) | pub extern "win64" fn output_ev_check() -> LRESULT {

FILE: simulated_passthru/src/lib_passthru.rs
  function log_init (line 8) | fn log_init(max_lvl: &c_longlong) {
  function reset_kanata_state (line 30) | pub extern "win64" fn reset_kanata_state(tick: c_longlong) -> LRESULT {
  function cli_init (line 46) | fn cli_init(cfg_path: &str) -> Result<ValidatedArgs> {
  function lib_impl (line 63) | fn lib_impl(cfg_path: &str) -> Result<()> {
  function lib_kanata_passthru (line 112) | pub extern "win64" fn lib_kanata_passthru(

FILE: simulated_passthru/src/log_win.rs
  type WinDebugLogger (line 6) | pub struct WinDebugLogger;
    method enabled (line 58) | fn enabled(&self, _metadata: &Metadata) -> bool {
    method enabled (line 62) | fn enabled(&self, metadata: &Metadata) -> bool {
    method log (line 65) | fn log(&self, record: &Record) {
    method flush (line 86) | fn flush(&self) {}
  function iconify (line 19) | pub fn iconify(lvl: log::Level) -> char {
  function is_thread_state (line 30) | pub fn is_thread_state() -> &'static bool {
  function set_thread_state (line 33) | pub fn set_thread_state(is: bool) -> &'static bool {
  function clean_name (line 46) | fn clean_name(path: Option<&str>) -> String {
  function dbg_win (line 89) | pub fn dbg_win(s: &str) {
  function OutputDebugStringW (line 106) | fn OutputDebugStringW(chars: *const u16);
  function init (line 109) | pub fn init() {

FILE: src/gui/win.rs
  type PathExt (line 39) | trait PathExt {
    method add_ext (line 40) | fn add_ext(&mut self, ext_o: impl AsRef<std::path::Path>);
    method add_ext (line 43) | fn add_ext(&mut self, ext_o: impl AsRef<std::path::Path>) {
  type SystemTrayData (line 57) | pub struct SystemTrayData {
  type Icn (line 68) | pub struct Icn {
  type SystemTray (line 74) | pub struct SystemTray {
    method get_icon_from_file (line 442) | fn get_icon_from_file<P>(&self, ico_p: P) -> Result<Icn>
    method get_icon_from_file_impl (line 448) | fn get_icon_from_file_impl(&self, ico_p: &str) -> Result<Icn> {
    method set_menu_item_cfg_icon (line 482) | fn set_menu_item_cfg_icon(
    method update_tooltip_pos (line 503) | fn update_tooltip_pos(&self) {
    method update_mouse_watcher (line 579) | fn update_mouse_watcher(&self, tt2m_sndr: ASender<bool>, ticks: u16, p...
    method show_tooltip (line 614) | fn show_tooltip(&self, img: Option<&nwg::Bitmap>) {
    method hide_tooltip (line 689) | fn hide_tooltip(&self) {
    method show_menu (line 692) | fn show_menu(&self) {
    method update_tray_icon_cfg (line 699) | fn update_tray_icon_cfg(
    method update_tray_icon_cfg_group (line 735) | fn update_tray_icon_cfg_group(&self, force: bool) {
    method check_active (line 767) | fn check_active(&self) {
    method update_tooltip_data (line 800) | fn update_tooltip_data(&self, k: &Kanata) -> bool {
    method reload_cfg (line 844) | fn reload_cfg(&self, i: Option<usize>) -> Result<()> {
    method reload_layer_icon (line 986) | fn reload_layer_icon(&self) {
    method notify_error (line 990) | fn notify_error(&self) {
    method reload_cfg_icon (line 1032) | fn reload_cfg_icon(&self) {
    method reload_cfg_or_layer_icon (line 1036) | fn reload_cfg_or_layer_icon(&self, is_cfg: bool) -> Result<()> {
    method update_tray_icon (line 1118) | fn update_tray_icon(
    method exit (line 1278) | fn exit(&self) {
    method build_win_tt (line 1286) | fn build_win_tt(&self) -> Result<nwg::Window, nwg::NwgError> {
    method build_ui (line 1334) | fn build_ui(mut d: SystemTray) -> Result<SystemTrayUi, nwg::NwgError> {
  function get_appdata (line 118) | pub fn get_appdata() -> Option<PathBuf> {
  function get_user_home (line 121) | pub fn get_user_home() -> Option<PathBuf> {
  function get_xdg_home (line 124) | pub fn get_xdg_home() -> Option<PathBuf> {
  constant CFG_FD (line 128) | const CFG_FD: [&str; 3] = ["", "kanata", "kanata-tray"];
  constant ASSET_FD (line 130) | const ASSET_FD: [&str; 4] = ["", "icon", "img", "icons"];
  constant IMG_EXT (line 131) | const IMG_EXT: [&str; 7] = ["ico", "jpg", "jpeg", "png", "bmp", "dds", "...
  constant PRE_LAYER (line 132) | const PRE_LAYER: &str = "\n🗍: ";
  constant TTTIMER_L (line 133) | const TTTIMER_L: u16 = 9;
  function send_gui_notice (line 136) | pub fn send_gui_notice() {
  function send_gui_cfg_notice (line 143) | pub fn send_gui_cfg_notice() {
  function send_gui_err_notice (line 150) | pub fn send_gui_err_notice() {
  function send_gui_exit_notice (line 157) | pub fn send_gui_exit_notice() {
  function show_err_msg_nofail (line 164) | pub fn show_err_msg_nofail(title: String, msg: String) {
  function get_icon_p (line 182) | fn get_icon_p<S1, S2, S3, P>(
  function get_icon_p_impl (line 204) | fn get_icon_p_impl(
  constant ICN_SZ_MENU (line 346) | pub const ICN_SZ_MENU: [u32; 2] = [24, 24];
  constant ICN_SZ_TT (line 347) | pub const ICN_SZ_TT: [u32; 2] = [36, 36];
  constant ICN_SZ_MENU_I (line 348) | pub const ICN_SZ_MENU_I: [i32; 2] = [24, 24];
  constant ICN_SZ_TT_I (line 349) | pub const ICN_SZ_TT_I: [i32; 2] = [36, 36];
  function to_wide_str (line 377) | pub fn to_wide_str(s: &str) -> Vec<u16> {
  function get_mouse_ptr_size (line 426) | pub fn get_mouse_ptr_size(dpi_scale: bool) -> (u32, u32) {
  type SystemTrayUi (line 1328) | pub struct SystemTrayUi {
  method drop (line 1634) | fn drop(&mut self) {
  type Target (line 1642) | type Target = SystemTray;
  method deref (line 1643) | fn deref(&self) -> &Self::Target {
  constant WS_CLICK_THRU (line 1652) | pub const WS_CLICK_THRU: u32 = WS_EX_LAYERED | WS_EX_TRANSPARENT;
  function show_layered_win (line 1656) | fn show_layered_win(win_id: HWND) {
  function update_app_data (line 1667) | pub fn update_app_data(k: &MutexGuard<Kanata>) -> Result<SystemTrayData> {
  function build_tray (line 1684) | pub fn build_tray(cfg: &Arc<Mutex<Kanata>>) -> Result<system_tray_ui::Sy...

FILE: src/gui/win_dbg_logger/mod.rs
  type WinDbgLogger (line 50) | pub struct WinDbgLogger {
    method level (line 114) | fn level(&self) -> LevelFilter {
    method config (line 117) | fn config(&self) -> Option<&simplelog::Config> {
    method as_log (line 120) | fn as_log(self: Box<Self>) -> Box<dyn log::Log> {
    method enabled (line 175) | fn enabled(&self, metadata: &Metadata) -> bool {
    method log (line 179) | fn log(&self, record: &Record) {
    method flush (line 215) | fn flush(&self) {}
  function windbg_simple_combo (line 97) | pub fn windbg_simple_combo(
  function iconify (line 126) | pub fn iconify(lvl: log::Level) -> char {
  function is_thread_state (line 137) | pub fn is_thread_state() -> &'static bool {
  function set_thread_state (line 140) | pub fn set_thread_state(is: bool) -> &'static bool {
  function get_noti_lvl (line 146) | pub fn get_noti_lvl() -> &'static LevelFilter {
  function set_noti_lvl (line 149) | pub fn set_noti_lvl(lvl: LevelFilter) -> &'static LevelFilter {
  function clean_name (line 161) | fn clean_name(path: Option<&str>) -> String {
  function output_debug_string (line 223) | pub fn output_debug_string(s: &str) {
  function OutputDebugStringW (line 242) | fn OutputDebugStringW(chars: *const u16);
  function IsDebuggerPresent (line 243) | fn IsDebuggerPresent() -> i32;
  function is_debugger_present (line 251) | pub fn is_debugger_present() -> bool {
  function init (line 269) | pub fn init() {

FILE: src/gui/win_nwg_ext/mod.rs
  type BitmapEx (line 19) | pub trait BitmapEx {
    method from_system_icon (line 20) | fn from_system_icon(icon: SHSTOCKICONID) -> nwg::Bitmap;
    method from_system_icon (line 25) | fn from_system_icon(icon: SHSTOCKICONID) -> nwg::Bitmap {
  type MenuEx (line 100) | pub trait MenuEx {
    method set_bitmap (line 101) | fn set_bitmap(&self, bitmap: Option<&nwg::Bitmap>);
    method set_bitmap (line 105) | fn set_bitmap(&self, bitmap: Option<&nwg::Bitmap>) {
  type MenuItemEx (line 138) | pub trait MenuItemEx {
    method set_bitmap (line 139) | fn set_bitmap(&self, bitmap: Option<&nwg::Bitmap>);
    method set_bitmap (line 144) | fn set_bitmap(&self, bitmap: Option<&nwg::Bitmap>) {
  type WindowEx (line 177) | pub trait WindowEx {
    method set_position_ex (line 178) | fn set_position_ex(&self, x: i32, y: i32);
    method set_position_ex (line 242) | fn set_position_ex(&self, x: i32, y: i32) {
  function dpi (line 180) | pub fn dpi() -> i32 {
  function logical_to_physical (line 190) | pub fn logical_to_physical(x: i32, y: i32) -> (i32, i32) {
  function set_window_position (line 202) | pub unsafe fn set_window_position(handle: HWND, x: i32, y: i32) {
  constant NOT_BOUND (line 218) | const NOT_BOUND: &str = "Window is not yet bound to a winapi object";
  constant BAD_HANDLE (line 219) | const BAD_HANDLE: &str = "INTERNAL ERROR: Window handle is not HWND!";
  function check_hwnd (line 220) | pub fn check_hwnd(handle: &ControlHandle, not_bound: &str, bad_handle: &...

FILE: src/kanata/caps_word.rs
  type CapsWordState (line 7) | pub struct CapsWordState {
    method new (line 33) | pub(crate) fn new(cfg: &CapsWordCfg) -> Self {
    method tick_maybe_add_lsft (line 42) | pub(crate) fn tick_maybe_add_lsft(
  type CapsWordNextState (line 25) | pub enum CapsWordNextState {

FILE: src/kanata/cfg_forced.rs
  function force_log_layer_changes (line 10) | pub fn force_log_layer_changes(v: bool) {
  function get_forced_log_layer_changes (line 17) | pub fn get_forced_log_layer_changes() -> Option<bool> {

FILE: src/kanata/clipboard.rs
  type SavedClipboardData (line 12) | pub type SavedClipboardData = HashMap<u16, ClipboardData>;
  type ClipboardData (line 14) | pub enum ClipboardData {
  function clpb_set (line 32) | pub(crate) fn clpb_set(clipboard_string: &str) {
  function clpb_cmd_set (line 47) | pub(crate) fn clpb_cmd_set(cmd_and_args: &[&str]) {
  function run_cmd_get_stdout (line 70) | fn run_cmd_get_stdout(cmd_and_args: &[&str], stdin: &str) -> String {
  function clpb_save (line 105) | pub(crate) fn clpb_save(id: u16, save_data: &mut SavedClipboardData) {
  function clpb_restore (line 140) | pub(crate) fn clpb_restore(id: u16, save_data: &SavedClipboardData) {
  function clpb_save_set (line 167) | pub(crate) fn clpb_save_set(id: u16, content: &str, save_data: &mut Save...
  function test_set (line 173) | fn test_set() {
  function clpb_save_cmd_set (line 184) | pub(crate) fn clpb_save_cmd_set(
  function test_save_cmd_set (line 203) | fn test_save_cmd_set() {
  function clpb_save_swap (line 239) | pub(crate) fn clpb_save_swap(id1: u16, id2: u16, save_data: &mut SavedCl...
  function test_swap (line 251) | fn test_swap() {
  type SavedClipboardData (line 297) | pub type SavedClipboardData = HashMap<u16, ClipboardData>;
  type ClipboardData (line 299) | pub enum ClipboardData {
  function clpb_set (line 304) | pub(crate) fn clpb_set(clipboard_string: &str) {}
  function clpb_cmd_set (line 306) | pub(crate) fn clpb_cmd_set(cmd_and_args: &[&str]) {}
  function clpb_save (line 308) | pub(crate) fn clpb_save(id: u16, save_data: &mut SavedClipboardData) {}
  function clpb_restore (line 310) | pub(crate) fn clpb_restore(id: u16, save_data: &SavedClipboardData) {}
  function clpb_save_set (line 312) | pub(crate) fn clpb_save_set(id: u16, content: &str, save_data: &mut Save...
  function clpb_save_cmd_set (line 314) | pub(crate) fn clpb_save_cmd_set(
  function clpb_save_swap (line 321) | pub(crate) fn clpb_save_swap(id1: u16, id2: u16, save_data: &mut SavedCl...

FILE: src/kanata/cmd.rs
  constant LP (line 10) | const LP: &str = "cmd-out:";
  function run_cmd_in_thread (line 13) | pub(super) fn run_cmd_in_thread(
  type Item (line 65) | pub(super) type Item = KeyAction;
  type KeyAction (line 68) | pub(super) enum KeyAction {
  function empty (line 76) | fn empty() -> std::vec::IntoIter<Item> {
  function from_sexpr (line 80) | fn from_sexpr(sexpr: Vec<SExpr>) -> std::vec::IntoIter<Item> {
  function parse_items (line 89) | fn parse_items<'a>(exprs: &'a [SExpr], items: &mut Vec<Item>) -> &'a [SE...
  function try_parse_chord (line 118) | fn try_parse_chord<'a>(chord: &str, exprs: &'a [SExpr], items: &mut Vec<...
  function try_parse_chorded_key (line 134) | fn try_parse_chorded_key(mods: &[KeyCode], osc: &str, chord: &str, items...
  function try_parse_chorded_list (line 156) | fn try_parse_chorded_list<'a>(
  function keys_for_cmd_output (line 190) | pub(super) fn keys_for_cmd_output(cmd_and_args: &[&str]) -> impl Iterato...
  function keys_for_cmd_output (line 233) | pub(super) fn keys_for_cmd_output(cmd_and_args: &[&str]) -> impl Iterato...
  function run_cmd_in_thread (line 239) | pub(super) fn run_cmd_in_thread(

FILE: src/kanata/dynamic_macro.rs
  type DynamicMacroItem (line 10) | pub enum DynamicMacroItem {
  type DynamicMacroReplayState (line 16) | pub struct DynamicMacroReplayState {
  type DynamicMacroRecordState (line 22) | pub struct DynamicMacroRecordState {
    method new (line 35) | fn new(macro_id: u16) -> Self {
    method add_release_for_all_unreleased_presses (line 44) | fn add_release_for_all_unreleased_presses(&mut self) {
    method add_event (line 63) | fn add_event(&mut self, osc: OsCode, evtype: WaitingEventType) {
  type WaitingEventType (line 29) | enum WaitingEventType {
  type ReplayEvent (line 86) | pub struct ReplayEvent(Event, u16);
    method key_event (line 89) | pub fn key_event(self) -> Event {
    method delay (line 92) | pub fn delay(self) -> u16 {
  function tick_record_state (line 97) | pub fn tick_record_state(record_state: &mut Option<DynamicMacroRecordSta...
  type ReplayBehaviour (line 104) | pub struct ReplayBehaviour {
  function tick_replay_state (line 108) | pub fn tick_replay_state(
  function begin_record_macro (line 159) | pub fn begin_record_macro(
  function record_press (line 204) | pub fn record_press(
  function record_release (line 235) | pub fn record_release(record_state: &mut Option<DynamicMacroRecordState>...
  function stop_macro (line 242) | pub fn stop_macro(
  function play_macro (line 280) | pub fn play_macro(

FILE: src/kanata/key_repeat.rs
  method handle_repeat (line 7) | pub(super) fn handle_repeat(&mut self, event: &KeyEvent) -> Result<()> {
  method handle_repeat_actual (line 17) | pub(super) fn handle_repeat_actual(&mut self, event: &KeyEvent) -> Resul...

FILE: src/kanata/linux.rs
  method event_loop (line 19) | pub fn event_loop(kanata: Arc<Mutex<Self>>, tx: Sender<KeyEvent>) -> Res...
  method check_release_non_physical_shift (line 115) | pub fn check_release_non_physical_shift(&mut self) -> Result<()> {
  method set_repeat_rate (line 119) | pub fn set_repeat_rate(s: Option<KeyRepeatSettings>) -> Result<()> {
  function handle_scroll (line 153) | fn handle_scroll(

FILE: src/kanata/macos.rs
  method event_loop (line 22) | pub fn event_loop(kanata: Arc<Mutex<Self>>, tx: Sender<KeyEvent>) -> Res...
  method check_release_non_physical_shift (line 175) | pub fn check_release_non_physical_shift(&mut self) -> Result<()> {

FILE: src/kanata/millisecond_counting.rs
  type MillisecondCountResult (line 3) | pub struct MillisecondCountResult {
  function count_ms_elapsed (line 9) | pub fn count_ms_elapsed(
  function ms_counts_0_elapsed_correctly (line 32) | fn ms_counts_0_elapsed_correctly() {
  function ms_counts_1_elapsed_correctly (line 43) | fn ms_counts_1_elapsed_correctly() {
  function ms_counts_1_then_2_elapsed_correctly (line 54) | fn ms_counts_1_then_2_elapsed_correctly() {

FILE: src/kanata/mod.rs
  function collect_and_sort_events (line 12) | fn collect_and_sort_events(
  type HashSet (line 131) | type HashSet<T> = rustc_hash::FxHashSet<T>;
  type HashMap (line 132) | type HashMap<K, V> = rustc_hash::FxHashMap<K, V>;
  type Kanata (line 148) | pub struct Kanata {
    method new (line 389) | pub fn new(args: &ValidatedArgs) -> Result<Self> {
    method new_arc (line 558) | pub fn new_arc(args: &ValidatedArgs) -> Result<Arc<Mutex<Self>>> {
    method new_from_str (line 562) | pub fn new_from_str(cfg: &str, file_content: HashMap<String, String>) ...
    method new_with_output_channel (line 712) | pub fn new_with_output_channel(
    method do_live_reload (line 721) | fn do_live_reload(&mut self, _tx: &Option<Sender<ServerMessage>>) -> R...
    method handle_input_event (line 850) | pub fn handle_input_event(&mut self, event: &KeyEvent) -> Result<()> {
    method get_ms_elapsed (line 897) | pub fn get_ms_elapsed(&mut self) -> u128 {
    method handle_time_ticks (line 919) | fn handle_time_ticks(&mut self, tx: &Option<Sender<ServerMessage>>) ->...
    method tick_ms (line 950) | pub fn tick_ms(&mut self, ms_elapsed: u128, _tx: &Option<Sender<Server...
    method tick_held_vkeys (line 978) | fn tick_held_vkeys(&mut self) {
    method tick_states (line 995) | fn tick_states(&mut self, _tx: &Option<Sender<ServerMessage>>) -> Resu...
    method handle_scrolling (line 1015) | fn handle_scrolling(&mut self) -> Result<()> {
    method handle_move_mouse (line 1040) | fn handle_move_mouse(&mut self) -> Result<()> {
    method tick_sequence_state (line 1142) | fn tick_sequence_state(&mut self) -> Result<()> {
    method tick_idle_timeout (line 1153) | fn tick_idle_timeout(&mut self) {
    method tick_physical_idle_timeout (line 1170) | fn tick_physical_idle_timeout(&mut self) {
    method handle_keystate_changes (line 1193) | fn handle_keystate_changes(&mut self, _tx: &Option<Sender<ServerMessag...
    method change_layer (line 2012) | pub fn change_layer(&mut self, layer_name: String) {
    method request_live_reload (line 2022) | pub fn request_live_reload(&mut self) {
    method handle_client_command (line 2033) | pub fn handle_client_command(
    method request_live_reload_next (line 2062) | pub fn request_live_reload_next(&mut self) {
    method request_live_reload_prev (line 2076) | pub fn request_live_reload_prev(&mut self) {
    method request_live_reload_num (line 2090) | pub fn request_live_reload_num(&mut self, index: usize) -> Result<()> {
    method request_live_reload_file (line 2109) | pub fn request_live_reload_file(&mut self, path: String) -> Result<()> {
    method check_handle_layer_change (line 2127) | fn check_handle_layer_change(&mut self, tx: &Option<Sender<ServerMessa...
    method print_layer (line 2148) | fn print_layer(&self, layer: usize) {
    method get_uptime_s (line 2156) | pub fn get_uptime_s(&self) -> u64 {
    method is_reload_complete (line 2162) | pub fn is_reload_complete(&self) -> bool {
    method last_reload_succeeded (line 2168) | pub fn last_reload_succeeded(&self) -> bool {
    method start_notification_loop (line 2173) | pub fn start_notification_loop(
    method start_notification_loop (line 2215) | pub fn start_notification_loop(
    method start_processing_loop (line 2222) | pub fn start_processing_loop(
    method can_block_update_idle_waiting (line 2468) | pub fn can_block_update_idle_waiting(&mut self, ms_elapsed: u16) -> bo...
    method is_idle (line 2521) | pub fn is_idle(&self) -> bool {
  type Axis (line 335) | pub enum Axis {
    method from (line 341) | fn from(val: MoveDirection) -> Axis {
  type ReloadAction (line 350) | enum ReloadAction {
  type CalculatedMouseMove (line 359) | pub struct CalculatedMouseMove {
  type MoveMouseState (line 364) | pub struct MoveMouseState {
  type MoveMouseAccelState (line 373) | pub struct MoveMouseAccelState {
  constant LINUX_PERMISSIONS_ERROR (line 386) | const LINUX_PERMISSIONS_ERROR: &str = "Failed to open the output uinput ...
  function test_unmodmods_bits (line 2556) | fn test_unmodmods_bits() {
  function run_multi_cmd (line 2562) | fn run_multi_cmd(cmds: Vec<(Option<log::Level>, Option<log::Level>, Vec<...
  function apply_mouse_distance_modifiers (line 2572) | fn apply_mouse_distance_modifiers(initial_distance: u16, mods: &Vec<u16>...
  function apply_speed_modifiers (line 2588) | fn apply_speed_modifiers() {
  function clean_state (line 2618) | pub fn clean_state(kanata: &Arc<Mutex<Kanata>>, tick: u128) -> Result<()> {
  function check_for_exit (line 2641) | fn check_for_exit(_event: &KeyEvent) {
  function update_kbd_out (line 2704) | fn update_kbd_out(_cfg: &CfgOptions, _kbd_out: &KbdOut) -> Result<()> {
  function handle_fakekey_action (line 2716) | pub fn handle_fakekey_action<'a, const C: usize, const R: usize, T>(
  function states_has_coord (line 2740) | fn states_has_coord<T>(states: &[State<T>], x: u8, y: u16) -> bool {
  function release_normalkey_states (line 2755) | fn release_normalkey_states<'a, const C: usize, const R: usize, T>(layou...
  function make_event (line 2794) | fn make_event(code: OsCode, value: KeyValue) -> KeyEvent {
  function single_event_unchanged (line 2799) | fn single_event_unchanged() {
  function modifiers_first_on_press (line 2811) | fn modifiers_first_on_press() {
  function modifiers_last_on_release (line 2828) | fn modifiers_last_on_release() {
  function multiple_modifiers_on_press (line 2846) | fn multiple_modifiers_on_press() {
  function multiple_modifiers_on_release (line 2866) | fn multiple_modifiers_on_release() {
  function repeat_treated_like_press (line 2887) | fn repeat_treated_like_press() {
  function all_modifiers_no_reorder_needed (line 2902) | fn all_modifiers_no_reorder_needed() {
  function all_non_modifiers_no_reorder_needed (line 2920) | fn all_non_modifiers_no_reorder_needed() {
  function mixed_press_release_preserves_interleaving (line 2936) | fn mixed_press_release_preserves_interleaving() {
  function collect_layer_changes (line 2963) | fn collect_layer_changes(rx: &Receiver<ServerMessage>) -> Vec<String> {
  function direct_held_layer_press_and_release_emit_layer_changes (line 2977) | fn direct_held_layer_press_and_release_emit_layer_changes() {
  function oneshot_held_layer_timeout_emits_both_transitions_within_one_tick_batch (line 3015) | fn oneshot_held_layer_timeout_emits_both_transitions_within_one_tick_bat...
  function oneshot_held_layer_consumed_by_keypress_emits_both_transitions_within_one_tick_batch (line 3048) | fn oneshot_held_layer_consumed_by_keypress_emits_both_transitions_within...

FILE: src/kanata/output_logic.rs
  constant KEY_IGNORE_MIN (line 33) | pub(super) const KEY_IGNORE_MIN: u16 = 0x2a4;
  constant KEY_IGNORE_MAX (line 34) | pub(super) const KEY_IGNORE_MAX: u16 = 0x2ad;
  function write_key (line 35) | pub(super) fn write_key(kb: &mut KbdOut, osc: OsCode, val: KeyValue) -> ...
  function press_key (line 41) | pub(super) fn press_key(kb: &mut KbdOut, osc: OsCode) -> Result<(), std:...
  function release_key (line 58) | pub(super) fn release_key(kb: &mut KbdOut, osc: OsCode) -> Result<(), st...
  function osc_to_btn (line 76) | fn osc_to_btn(osc: OsCode) -> Btn {
  function osc_to_wheel_direction (line 88) | fn osc_to_wheel_direction(osc: OsCode) -> MWheelDirection {
  function post_filter_press (line 100) | fn post_filter_press(kb: &mut KbdOut, osc: OsCode) -> Result<(), std::io...
  function post_filter_release (line 111) | fn post_filter_release(kb: &mut KbdOut, osc: OsCode) -> Result<(), std::...
  function zippy_is_idle (line 122) | pub(super) fn zippy_is_idle() -> bool {
  function zippy_tick (line 133) | pub(super) fn zippy_tick(_caps_word_is_active: bool) {

FILE: src/kanata/output_logic/zippychord.rs
  function zch (line 18) | pub(crate) fn zch() -> MutexGuard<'static, ZchState> {
  type ZchEnabledState (line 30) | enum ZchEnabledState {
  type ZchLastPressClassification (line 38) | enum ZchLastPressClassification {
  type ZchSmartSpaceState (line 45) | enum ZchSmartSpaceState {
  type ZchDynamicState (line 52) | struct ZchDynamicState {
    method zchd_tick (line 114) | fn zchd_tick(&mut self, is_caps_word_active: bool) {
    method zchd_state_change (line 145) | fn zchd_state_change(&mut self, cfg: &ZchConfig) {
    method zchd_activate_chord_deadline (line 150) | fn zchd_activate_chord_deadline(&mut self, deadline_ticks: u16) {
    method zchd_restart_deadline (line 156) | fn zchd_restart_deadline(&mut self, deadline_ticks: u16) {
    method zchd_reset (line 162) | fn zchd_reset(&mut self) {
    method zchd_soft_reset (line 173) | fn zchd_soft_reset(&mut self) {
    method zchd_clear_history (line 185) | fn zchd_clear_history(&mut self) {
    method zchd_is_idle (line 194) | fn zchd_is_idle(&self) -> bool {
    method zchd_press_key (line 201) | fn zchd_press_key(&mut self, osc: OsCode) {
    method zchd_release_key (line 205) | fn zchd_release_key(&mut self, osc: OsCode) {
  type ZchState (line 237) | pub(crate) struct ZchState {
    method zch_configure (line 250) | pub(crate) fn zch_configure(&mut self, cfg: (ZchPossibleChords, ZchCon...
    method zch_press_key (line 257) | pub(crate) fn zch_press_key(
    method zch_release_key (line 553) | pub(crate) fn zch_release_key(
    method zch_tick (line 582) | pub(crate) fn zch_tick(&mut self, is_caps_word_active: bool) {
    method zch_is_idle (line 588) | pub(crate) fn zch_is_idle(&self) -> bool {
  function type_osc (line 593) | fn type_osc(osc: OsCode, kb: &mut KbdOut, zchd: &ZchDynamicState) -> Res...
  function maybe_press_sft_during_activation (line 604) | fn maybe_press_sft_during_activation(
  function maybe_release_sft_during_activation (line 617) | fn maybe_release_sft_during_activation(

FILE: src/kanata/scroll.rs
  type ScrollState (line 3) | pub struct ScrollState {
  type ScrollAccelState (line 11) | pub struct ScrollAccelState {
  function update_scrollstate_get_result (line 19) | pub(crate) fn update_scrollstate_get_result(

FILE: src/kanata/sequences.rs
  type SequenceActivity (line 4) | pub enum SequenceActivity {
  type SequenceState (line 11) | pub struct SequenceState {
    method new (line 36) | pub fn new() -> Self {
    method activate (line 50) | pub fn activate(&mut self, input_mode: SequenceInputMode, timeout: u16) {
    method is_active (line 61) | pub fn is_active(&self) -> bool {
    method get_active (line 65) | pub fn get_active(&mut self) -> Option<&mut Self> {
    method is_inactive (line 72) | pub fn is_inactive(&self) -> bool {
  method default (line 78) | fn default() -> Self {
  function get_mod_mask_for_cur_keys (line 83) | pub(super) fn get_mod_mask_for_cur_keys(cur_keys: &[KeyCode]) -> u16 {
  type EndSequenceType (line 90) | pub(super) enum EndSequenceType {
  function do_sequence_press_logic (line 95) | pub(super) fn do_sequence_press_logic(
  function do_successful_sequence_termination (line 274) | pub(super) fn do_successful_sequence_termination(
  function cancel_sequence (line 353) | pub(super) fn cancel_sequence(state: &mut SequenceState, kbd_out: &mut K...
  function add_noerase (line 369) | pub(super) fn add_noerase(state: &mut SequenceState, noerase_count: u16) {

FILE: src/kanata/unknown.rs
  method check_release_non_physical_shift (line 4) | pub fn check_release_non_physical_shift(&mut self) -> Result<()> {

FILE: src/kanata/windows/exthook.rs
  method event_loop (line 12) | pub fn event_loop(_cfg: Arc<Mutex<Self>>, tx: Sender<KeyEvent>) -> Resul...
  function try_send_panic (line 57) | fn try_send_panic(tx: &Sender<KeyEvent>, kev: KeyEvent) {
  function start_event_preprocessor (line 63) | fn start_event_preprocessor(preprocess_rx: Receiver<KeyEvent>, process_t...

FILE: src/kanata/windows/interception.rs
  method event_loop_inner (line 13) | pub fn event_loop_inner(kanata: Arc<Mutex<Self>>, tx: Sender<KeyEvent>) ...
  method event_loop (line 133) | pub fn event_loop(
  function is_device_interceptable (line 152) | fn is_device_interceptable(
  function mouse_state_to_event (line 192) | fn mouse_state_to_event(state: ic::MouseState, rolling: i16) -> Option<K...

FILE: src/kanata/windows/llhook.rs
  method event_loop (line 13) | pub fn event_loop(
  method win_synchronize_keystates (line 187) | pub(crate) fn win_synchronize_keystates(&mut self) {
  function try_send_panic (line 285) | fn try_send_panic(tx: &Sender<KeyEvent>, kev: KeyEvent) {
  type LctlState (line 292) | enum LctlState {
  type RecvValue (line 301) | enum RecvValue {
  type CanBlock (line 307) | enum CanBlock {
  function preprocessor_recv (line 312) | fn preprocessor_recv(preprocess_rx: &Receiver<KeyEvent>, can_block: CanB...
  function start_event_preprocessor (line 326) | fn start_event_preprocessor(preprocess_rx: Receiver<KeyEvent>, process_t...

FILE: src/kanata/windows/mod.rs
  function set_win_altgr_behaviour (line 17) | pub fn set_win_altgr_behaviour(b: AltGrBehaviour) {
  method check_release_non_physical_shift (line 27) | pub fn check_release_non_physical_shift(&mut self) -> Result<()> {
  method check_release_non_physical_shift (line 133) | pub fn check_release_non_physical_shift(&mut self) -> Result<()> {
  method live_reload (line 138) | pub fn live_reload(&mut self) -> Result<()> {
  method live_reload_n (line 144) | pub fn live_reload_n(&mut self, n: usize) -> Result<()> {
  function clear_states_from_inactivity (line 185) | pub fn clear_states_from_inactivity(

FILE: src/lib.rs
  type CfgPath (line 19) | type CfgPath = PathBuf;
  type ValidatedArgs (line 21) | pub struct ValidatedArgs {
  function default_cfg (line 30) | pub fn default_cfg() -> Vec<PathBuf> {
  type SocketAddrWrapper (line 49) | pub struct SocketAddrWrapper(SocketAddr);
    method into_inner (line 67) | pub fn into_inner(self) -> SocketAddr {
    method get_ref (line 70) | pub fn get_ref(&self) -> &SocketAddr {
  type Err (line 52) | type Err = Error;
  method from_str (line 54) | fn from_str(s: &str) -> Result<Self, Self::Err> {

FILE: src/main.rs
  function cli_init (line 23) | fn cli_init() -> Result<(ValidatedArgs, Option<String>)> {
  function main_impl (line 158) | pub(crate) fn main_impl() -> Result<()> {
  function main (line 217) | pub fn main() -> Result<()> {
  function main (line 232) | fn main() {
  function main (line 237) | fn main() {

FILE: src/main_lib/args.rs
  type Args (line 16) | pub struct Args {
  function no_wait_flag_default_false (line 127) | fn no_wait_flag_default_false() {
  function no_wait_flag_enabled (line 133) | fn no_wait_flag_enabled() {
  function no_wait_with_other_flags (line 139) | fn no_wait_with_other_flags() {
  function emergency_exit_code_default (line 147) | fn emergency_exit_code_default() {
  function emergency_exit_code_custom (line 153) | fn emergency_exit_code_custom() {
  function emergency_exit_code_with_other_flags (line 159) | fn emergency_exit_code_with_other_flags() {

FILE: src/main_lib/mod.rs
  function list_devices_macos (line 7) | pub(crate) fn list_devices_macos() {
  function list_devices_linux (line 69) | pub(crate) fn list_devices_linux() {
  type WindowsDeviceInfo (line 119) | struct WindowsDeviceInfo {
  function get_device_info (line 130) | fn get_device_info(device_handle: winapi::um::winnt::HANDLE) -> Option<W...
  function list_devices_windows (line 195) | pub(crate) fn list_devices_windows() {
  function extract_hardware_id (line 300) | fn extract_hardware_id(device_name: &str) -> Option<String> {

FILE: src/main_lib/win_gui.rs
  function cli_init (line 14) | fn cli_init() -> Result<ValidatedArgs> {
  function main_impl (line 140) | fn main_impl() -> Result<()> {
  function lib_main_gui (line 211) | pub fn lib_main_gui() {

FILE: src/oskbd/linux.rs
  type KbdIn (line 31) | pub struct KbdIn {
    method new (line 51) | pub fn new(
    method register_device (line 122) | fn register_device(&mut self, mut dev: Device, path: String) -> Result...
    method read (line 141) | pub fn read(&mut self) -> Result<Vec<InputEvent>, io::Error> {
    method rediscover_devices (line 197) | fn rediscover_devices(&mut self) -> Result<(), io::Error> {
  constant INOTIFY_TOKEN_VALUE (line 45) | const INOTIFY_TOKEN_VALUE: usize = 0;
  constant INOTIFY_TOKEN (line 46) | const INOTIFY_TOKEN: Token = Token(INOTIFY_TOKEN_VALUE);
  type DeviceType (line 257) | enum DeviceType {
  function is_input_device (line 264) | pub fn is_input_device(device: &Device, detect_mode: DeviceDetectMode) -...
  function has_keyboard_keys (line 312) | fn has_keyboard_keys(keys: &evdev::AttributeSetRef<KeyCode>) -> bool {
  type Error (line 324) | type Error = ();
  method try_from (line 325) | fn try_from(item: InputEvent) -> Result<Self, Self::Error> {
  method from (line 362) | fn from(item: KeyEvent) -> Self {
  type KbdOut (line 370) | pub struct KbdOut {
    method new (line 381) | pub fn new(
    method update_unicode_termination (line 448) | pub fn update_unicode_termination(&self, t: UnicodeTermination) {
    method update_unicode_u_code (line 452) | pub fn update_unicode_u_code(&self, u: OsCode) {
    method write_raw (line 456) | pub fn write_raw(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method write (line 476) | pub fn write(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method write_many (line 485) | pub fn write_many(&mut self, events: &[InputEvent]) -> Result<(), io::...
    method write_key (line 494) | pub fn write_key(&mut self, key: OsCode, value: KeyValue) -> Result<()...
    method write_code (line 502) | pub fn write_code(&mut self, code: u32, value: KeyValue) -> Result<(),...
    method press_key (line 508) | pub fn press_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_key (line 512) | pub fn release_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method send_unicode (line 517) | pub fn send_unicode(&mut self, c: char) -> Result<(), io::Error> {
    method click_btn (line 559) | pub fn click_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method release_btn (line 563) | pub fn release_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method scroll (line 567) | pub fn scroll(
    method move_mouse (line 630) | pub fn move_mouse(&mut self, mv: CalculatedMouseMove) -> Result<(), io...
    method move_mouse_many (line 640) | pub fn move_mouse_many(&mut self, moves: &[CalculatedMouseMove]) -> Re...
    method set_mouse (line 654) | pub fn set_mouse(&mut self, _x: u16, _y: u16) -> Result<(), io::Error> {
  function devices_from_input_paths (line 662) | fn devices_from_input_paths(
  function discover_devices (line 680) | pub fn discover_devices(
  function watch_devinput (line 726) | fn watch_devinput() -> Result<Inotify, io::Error> {
  type Symlink (line 733) | struct Symlink {
    method new (line 738) | fn new(source: PathBuf, dest: PathBuf) -> Result<Self, io::Error> {
  function handle_signals (line 758) | fn handle_signals(symlink: Option<Symlink>) {
  function wait_for_all_keys_unpressed (line 784) | fn wait_for_all_keys_unpressed(dev: &Device) -> Result<(), io::Error> {
  method drop (line 835) | fn drop(&mut self) {

FILE: src/oskbd/macos.rs
  type InputEvent (line 31) | pub struct InputEvent {
    method new (line 38) | pub fn new(event: DKEvent) -> Self {
    method fmt (line 202) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    type Error (line 240) | type Error = ();
    method try_from (line 242) | fn try_from(item: KeyEvent) -> Result<Self, Self::Error> {
  method from (line 48) | fn from(event: InputEvent) -> Self {
  type KbdIn (line 57) | pub struct KbdIn {
    method new (line 70) | pub fn new(
    method read (line 121) | pub fn read(&mut self) -> Result<InputEvent, io::Error> {
    method release_input (line 142) | pub fn release_input(&mut self) {
    method regrab_input (line 151) | pub fn regrab_input(&mut self) -> bool {
    method is_grabbed (line 161) | pub fn is_grabbed(&self) -> bool {
  method drop (line 62) | fn drop(&mut self) {
  function validate_and_register_devices (line 166) | fn validate_and_register_devices(include_names: Vec<String>) -> Vec<Stri...
  type Error (line 218) | type Error = ();
  method try_from (line 220) | fn try_from(item: InputEvent) -> Result<Self, Self::Error> {
  type KbdOut (line 260) | pub struct KbdOut {
    method new (line 266) | pub fn new() -> Result<Self, io::Error> {
    method write (line 272) | pub fn write(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method output_ready (line 285) | pub fn output_ready(&self) -> bool {
    method wait_until_ready (line 289) | pub fn wait_until_ready(&self, timeout: Option<Duration>) -> bool {
    method write_key (line 324) | pub fn write_key(&mut self, key: OsCode, value: KeyValue) -> Result<()...
    method write_code (line 337) | pub fn write_code(&mut self, code: u32, value: KeyValue) -> Result<(),...
    method press_key (line 349) | pub fn press_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_key (line 353) | pub fn release_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_tracked_output_keys (line 357) | pub fn release_tracked_output_keys(&mut self, reason: &str) {
    method send_unicode (line 375) | pub fn send_unicode(&mut self, c: char) -> Result<(), io::Error> {
    method scroll (line 388) | pub fn scroll(&mut self, _direction: MWheelDirection, _distance: u16) ...
    method button_action (line 413) | fn button_action(&mut self, _btn: Btn, is_click: bool) -> Result<(), i...
    method click_btn (line 460) | pub fn click_btn(&mut self, _btn: Btn) -> Result<(), io::Error> {
    method release_btn (line 464) | pub fn release_btn(&mut self, _btn: Btn) -> Result<(), io::Error> {
    method move_mouse (line 468) | pub fn move_mouse(&mut self, _mv: CalculatedMouseMove) -> Result<(), i...
    method pressed_buttons (line 493) | fn pressed_buttons() -> usize {
    method move_mouse_many (line 501) | pub fn move_mouse_many(&mut self, _moves: &[CalculatedMouseMove]) -> R...
    method set_mouse (line 514) | pub fn set_mouse(&mut self, _x: u16, _y: u16) -> Result<(), io::Error> {
    method make_event_source (line 523) | fn make_event_source() -> Result<CGEventSource, Error> {
    method make_event (line 532) | fn make_event() -> Result<CGEvent, Error> {
    method record_output_transition_after_write (line 539) | fn record_output_transition_after_write(&mut self, key: OsCode, value:...
    method apply_calculated_move (line 556) | fn apply_calculated_move(_mv: &CalculatedMouseMove, mouse_position: &m...

FILE: src/oskbd/mod.rs
  constant HI_RES_SCROLL_UNITS_IN_LO_RES (line 63) | pub const HI_RES_SCROLL_UNITS_IN_LO_RES: u16 = 120;
  type KeyValue (line 68) | pub enum KeyValue {
    method from (line 77) | fn from(item: i32) -> Self {
    method from (line 88) | fn from(up: bool) -> Self {
  function from (line 97) | fn from(val: KeyValue) -> Self {
  type KeyEvent (line 105) | pub struct KeyEvent {
    method new (line 112) | pub fn new(code: OsCode, value: KeyValue) -> Self {
    method fmt (line 119) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    method fmt (line 134) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

FILE: src/oskbd/sim_passthru.rs
  type CbOutEvFn (line 18) | type CbOutEvFn = dyn Fn(i64, i64, i64) -> i64 + Send + Sync + 'static;
  type FnOutEvWrapper (line 19) | pub struct FnOutEvWrapper {
  type KbdOut (line 26) | pub struct KbdOut {
    method new (line 33) | pub fn new() -> Result<Self, io::Error> {
    method new (line 37) | pub fn new(
    method write_raw (line 46) | pub fn write_raw(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method write (line 50) | pub fn write(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method output_ready (line 77) | pub fn output_ready(&self) -> bool {
    method wait_until_ready (line 80) | pub fn wait_until_ready(&self, _timeout: Option<std::time::Duration>) ...
    method write_key (line 83) | pub fn write_key(&mut self, key: OsCode, value: KeyValue) -> Result<()...
    method write_code (line 97) | pub fn write_code(&mut self, code: u32, value: KeyValue) -> Result<(),...
    method press_key (line 101) | pub fn press_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_key (line 104) | pub fn release_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_tracked_output_keys (line 107) | pub fn release_tracked_output_keys(&mut self, _reason: &str) {}
    method send_unicode (line 108) | pub fn send_unicode(&mut self, c: char) -> Result<(), io::Error> {
    method click_btn (line 112) | pub fn click_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method release_btn (line 116) | pub fn release_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method scroll (line 120) | pub fn scroll(&mut self, direction: MWheelDirection, distance: u16) ->...
    method move_mouse (line 124) | pub fn move_mouse(&mut self, mv: CalculatedMouseMove) -> Result<(), io...
    method move_mouse_many (line 129) | pub fn move_mouse_many(&mut self, moves: &[CalculatedMouseMove]) -> Re...
    method set_mouse (line 136) | pub fn set_mouse(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
    method tick (line 140) | pub fn tick(&mut self) {}
  type InputEvent (line 145) | pub struct InputEvent {
    method fmt (line 153) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    method from_oscode (line 163) | pub fn from_oscode(code: OsCode, val: KeyValue) -> Self {
    method from (line 187) | fn from(item: KeyEvent) -> Self {
  type Error (line 173) | type Error = ();
  method try_from (line 174) | fn try_from(item: InputEvent) -> Result<Self, Self::Error> {

FILE: src/oskbd/simulated.rs
  function concat_os_str2 (line 9) | pub fn concat_os_str2(a: &OsStr, b: &OsStr) -> OsString {
  function append_file_name (line 15) | fn append_file_name(path: impl AsRef<Path>, appendix: impl AsRef<OsStr>)...
  type LogFmtT (line 28) | pub enum LogFmtT {
  type LogFmt (line 45) | pub struct LogFmt {
    method new (line 72) | pub fn new() -> Self {
    method fmt (line 95) | pub fn fmt(&mut self, key: LogFmtT, value: String) {
    method write_raw (line 201) | pub fn write_raw(&mut self, event: InputEvent) {
    method in_tick (line 209) | pub fn in_tick(&mut self, t: u128) {
    method in_press_key (line 212) | pub fn in_press_key(&mut self, key: OsCode) {
    method in_release_key (line 215) | pub fn in_release_key(&mut self, key: OsCode) {
    method in_repeat_key (line 218) | pub fn in_repeat_key(&mut self, key: OsCode) {
    method press_key (line 221) | pub fn press_key(&mut self, key: OsCode) {
    method release_key (line 224) | pub fn release_key(&mut self, key: OsCode) {
    method send_unicode (line 227) | pub fn send_unicode(&mut self, c: char) {
    method click_btn (line 230) | pub fn click_btn(&mut self, btn: Btn) {
    method release_btn (line 233) | pub fn release_btn(&mut self, btn: Btn) {
    method set_mouse (line 236) | pub fn set_mouse(&mut self, x: u16, y: u16) {
    method scroll (line 239) | pub fn scroll(&mut self, dir: MWheelDirection, dist: u16) {
    method move_mouse (line 242) | pub fn move_mouse(&mut self, dir: MoveDirection, dist: u16) {
    method write_code (line 245) | pub fn write_code(&mut self, code: u32, value: KeyValue) {
    method end (line 249) | pub fn end(&self, in_path: &PathBuf, appendix: Option<String>) {
  method default (line 67) | fn default() -> Self {
  type Outputs (line 315) | pub struct Outputs {
    method new (line 321) | fn new() -> Self {
    method push (line 328) | fn push(&mut self, event: impl AsRef<str>) {
  type KbdOut (line 338) | pub struct KbdOut {
    method new_actual (line 344) | fn new_actual() -> Result<Self, io::Error> {
    method new (line 352) | pub fn new() -> Result<Self, io::Error> {
    method new (line 356) | pub fn new(
    method write_raw (line 365) | pub fn write_raw(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method write (line 370) | pub fn write(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method output_ready (line 374) | pub fn output_ready(&self) -> bool {
    method wait_until_ready (line 377) | pub fn wait_until_ready(&self, _timeout: Option<std::time::Duration>) ...
    method write_key (line 380) | pub fn write_key(&mut self, key: OsCode, value: KeyValue) -> Result<()...
    method write_code (line 394) | pub fn write_code(&mut self, code: u32, value: KeyValue) -> Result<(),...
    method press_key (line 399) | pub fn press_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_key (line 403) | pub fn release_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_tracked_output_keys (line 407) | pub fn release_tracked_output_keys(&mut self, _reason: &str) {}
    method send_unicode (line 408) | pub fn send_unicode(&mut self, c: char) -> Result<(), io::Error> {
    method click_btn (line 413) | pub fn click_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method release_btn (line 418) | pub fn release_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method scroll (line 423) | pub fn scroll(&mut self, direction: MWheelDirection, distance: u16) ->...
    method move_mouse (line 429) | pub fn move_mouse(&mut self, mv: CalculatedMouseMove) -> Result<(), io...
    method move_mouse_many (line 436) | pub fn move_mouse_many(&mut self, moves: &[CalculatedMouseMove]) -> Re...
    method set_mouse (line 445) | pub fn set_mouse(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
    method tick (line 450) | pub fn tick(&mut self) {
  type InputEvent (line 458) | pub struct InputEvent {
    method fmt (line 466) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    method from_oscode (line 475) | pub fn from_oscode(code: OsCode, val: KeyValue) -> Self {
    method from (line 499) | fn from(item: KeyEvent) -> Self {
    method from (line 509) | fn from(_item: KeyEvent) -> Self {
  type Error (line 485) | type Error = ();
  method try_from (line 486) | fn try_from(item: InputEvent) -> Result<Self, Self::Error> {

FILE: src/oskbd/windows/exthook_os.rs
  constant LLHOOK_IDLE_TIME_SECS_CLEAR_INPUTS (line 15) | pub const LLHOOK_IDLE_TIME_SECS_CLEAR_INPUTS: u64 = 60;
  type HookFn (line 17) | type HookFn = dyn FnMut(InputEvent) -> bool + Send + Sync + 'static;
  type KeyboardHook (line 21) | pub struct KeyboardHook {}
    method set_input_cb (line 24) | pub fn set_input_cb(
  method drop (line 38) | fn drop(&mut self) {
  type InputEvent (line 45) | pub struct InputEvent {
    method fmt (line 51) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    method from_vk_sc (line 58) | pub fn from_vk_sc(vk: c_uint, sc: c_uint, up: c_int) -> Self {
    method from_oscode (line 73) | pub fn from_oscode(code: OsCode, val: KeyValue) -> Self {
    method from (line 93) | fn from(item: KeyEvent) -> Self {
  type Error (line 81) | type Error = ();
  method try_from (line 82) | fn try_from(item: InputEvent) -> Result<Self, Self::Error> {

FILE: src/oskbd/windows/interception.rs
  type InputEvent (line 15) | pub struct InputEvent(pub Stroke);
    method fmt (line 19) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    method from_oscode (line 25) | fn from_oscode(code: OsCode, val: KeyValue) -> Self {
    method from_mouse_btn (line 51) | fn from_mouse_btn(btn: Btn, is_up: bool) -> Self {
    method from_mouse_scroll (line 73) | fn from_mouse_scroll(direction: MWheelDirection, distance: u16) -> Self {
    method from_mouse_move (line 94) | fn from_mouse_move(direction: MoveDirection, distance: u16) -> Self {
    method from_mouse_move_many (line 113) | fn from_mouse_move_many(moves: &[CalculatedMouseMove]) -> Self {
    method from_mouse_set (line 136) | fn from_mouse_set(x: u16, y: u16) -> Self {
  type KbdOut (line 154) | pub struct KbdOut {}
    method new (line 176) | pub fn new() -> Result<Self, io::Error> {
    method write (line 180) | pub fn write(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method write_code_raw (line 185) | pub fn write_code_raw(&mut self, code: u16, value: KeyValue) -> Result...
    method write_code (line 189) | pub fn write_code(&mut self, code: u32, value: KeyValue) -> Result<(),...
    method write_key (line 193) | pub fn write_key(&mut self, key: OsCode, value: KeyValue) -> Result<()...
    method press_key (line 197) | pub fn press_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_key (line 201) | pub fn release_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method click_btn (line 205) | pub fn click_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method release_btn (line 211) | pub fn release_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method scroll (line 218) | pub fn scroll(&mut self, direction: MWheelDirection, distance: u16) ->...
    method send_unicode (line 225) | pub fn send_unicode(&mut self, c: char) -> Result<(), io::Error> {
    method move_mouse (line 231) | pub fn move_mouse(&mut self, mv: CalculatedMouseMove) -> Result<(), io...
    method move_mouse_many (line 236) | pub fn move_mouse_many(&mut self, moves: &[CalculatedMouseMove]) -> Re...
    method set_mouse (line 241) | pub fn set_mouse(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
  function write_interception (line 156) | fn write_interception(event: InputEvent) {

FILE: src/oskbd/windows/interception_convert.rs
  type OsCodeWrapper (line 191) | pub struct OsCodeWrapper(pub OsCode);
    type Error (line 194) | type Error = ();
    method try_from (line 196) | fn try_from(item: Stroke) -> Result<Self, Self::Error> {
  type Error (line 212) | type Error = ();
  method try_from (line 214) | fn try_from(item: OsCodeWrapper) -> Result<Self, Self::Error> {

FILE: src/oskbd/windows/llhook.rs
  constant LLHOOK_IDLE_TIME_SECS_CLEAR_INPUTS (line 30) | pub const LLHOOK_IDLE_TIME_SECS_CLEAR_INPUTS: u64 = 60;
  type HookFn (line 32) | type HookFn = dyn FnMut(InputEvent) -> bool;
  type KeyboardHook (line 41) | pub struct KeyboardHook {
    method set_input_cb (line 50) | pub fn set_input_cb(callback: impl FnMut(InputEvent) -> bool + 'static...
  method drop (line 71) | fn drop(&mut self) {
  type InputEvent (line 79) | pub struct InputEvent {
    method fmt (line 87) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    method from_hook_lparam (line 96) | fn from_hook_lparam(lparam: &KBDLLHOOKSTRUCT) -> Self {
    method from_oscode (line 127) | pub fn from_oscode(code: OsCode, val: KeyValue) -> Self {
    method from (line 149) | fn from(item: KeyEvent) -> Self {
  type Error (line 136) | type Error = ();
  method try_from (line 137) | fn try_from(item: InputEvent) -> Result<Self, Self::Error> {
  function hook_proc (line 185) | unsafe extern "system" fn hook_proc(code: c_int, wparam: WPARAM, lparam:...
  type KbdOut (line 236) | pub struct KbdOut {}
    method new (line 240) | pub fn new() -> Result<Self, io::Error> {
    method write (line 244) | pub fn write(&mut self, event: InputEvent) -> Result<(), io::Error> {
    method write_key (line 249) | pub fn write_key(&mut self, key: OsCode, value: KeyValue) -> Result<()...
    method write_code (line 254) | pub fn write_code(&mut self, code: u32, value: KeyValue) -> Result<(),...
    method write_code_raw (line 258) | pub fn write_code_raw(&mut self, code: u16, value: KeyValue) -> Result...
    method press_key (line 262) | pub fn press_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method release_key (line 266) | pub fn release_key(&mut self, key: OsCode) -> Result<(), io::Error> {
    method send_unicode (line 271) | pub fn send_unicode(&mut self, c: char) -> Result<(), io::Error> {
    method click_btn (line 277) | pub fn click_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method release_btn (line 289) | pub fn release_btn(&mut self, btn: Btn) -> Result<(), io::Error> {
    method scroll (line 301) | pub fn scroll(&mut self, direction: MWheelDirection, distance: u16) ->...
    method move_mouse (line 310) | pub fn move_mouse(&mut self, mv: CalculatedMouseMove) -> Result<(), io...
    method move_mouse_many (line 315) | pub fn move_mouse_many(&mut self, moves: &[CalculatedMouseMove]) -> Re...
    method set_mouse (line 320) | pub fn set_mouse(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
  function send_btn (line 327) | fn send_btn(flag: u32) {
  function send_xbtn (line 341) | fn send_xbtn(flag: u32, xbtn: u16) {
  function scroll (line 356) | fn scroll(direction: MWheelDirection, distance: u16) {
  function hscroll (line 374) | fn hscroll(direction: MWheelDirection, distance: u16) {
  function move_mouse (line 392) | fn move_mouse(direction: MoveDirection, distance: u16) {
  function move_mouse_many (line 402) | fn move_mouse_many(moves: &[CalculatedMouseMove]) {
  function move_mouse_xy (line 418) | fn move_mouse_xy(x: i32, y: i32) {
  function set_mouse_xy (line 422) | fn set_mouse_xy(x: i32, y: i32) {
  function mouse_event (line 432) | fn mouse_event(flags: u32, data: u32, dx: i32, dy: i32) {

FILE: src/oskbd/windows/llhook/mouse.rs
  type MHookFn (line 11) | type MHookFn = dyn FnMut(MouseEventType) -> bool;
  type MouseHook (line 19) | pub struct MouseHook {
    method set_input_cb (line 24) | pub fn set_input_cb(callback: impl FnMut(MouseEventType) -> bool + 'st...
  method drop (line 45) | fn drop(&mut self) {
  function mhook_proc (line 51) | unsafe extern "system" fn mhook_proc(code: c_int, wparam: WPARAM, lparam...
  type MouseEventType (line 86) | pub enum MouseEventType {
  type MousePressEvent (line 101) | pub struct MousePressEvent {
    method new (line 211) | pub unsafe fn new(
  type MouseWheel (line 108) | pub enum MouseWheel {
    method new (line 232) | pub fn new(wm_mouse_param: WPARAM) -> MouseWheel {
  type MouseWheelDirection (line 116) | pub enum MouseWheelDirection {
    method optionally_from (line 262) | pub unsafe fn optionally_from(
    method new (line 272) | fn new(ms_ll_hook_struct: &MSLLHOOKSTRUCT) -> MouseWheelDirection {
  type MouseWheelEvent (line 124) | pub struct MouseWheelEvent {
    method new (line 248) | pub unsafe fn new(
  type Point (line 132) | pub struct Point {
    method from (line 223) | fn from(value: POINT) -> Self {
  type MouseMoveEvent (line 139) | pub struct MouseMoveEvent {
    method new (line 286) | pub unsafe fn new(ms_ll_hook_struct: *const MSLLHOOKSTRUCT) -> MouseMo...
  type MouseButtonPress (line 145) | pub enum MouseButtonPress {
    method from (line 300) | fn from(value: WPARAM) -> Self {
  type MouseClick (line 153) | pub enum MouseClick {
    method from (line 314) | fn from(value: WPARAM) -> Self {
  type MouseButton (line 161) | pub enum MouseButton {
    method from (line 333) | pub unsafe fn from(wm_mouse_param: WPARAM, ms_ll_hook_struct: *const M...
    method into_extra (line 359) | fn into_extra(click: MouseClick, ms_ll_hook_struct: &MSLLHOOKSTRUCT) -...
  function classify_mouse_event (line 177) | pub unsafe fn classify_mouse_event(
  type Error (line 370) | type Error = ();
  method try_from (line 371) | fn try_from(mevt: MouseEventType) -> Result<Self, ()> {

FILE: src/oskbd/windows/mod.rs
  function send_uc (line 42) | fn send_uc(c: char, up: bool) {
  function write_code_raw (line 71) | fn write_code_raw(code: u16, value: KeyValue) -> Result<(), std::io::Err...
  function write_code (line 93) | fn write_code(code: u16, value: KeyValue) -> Result<(), std::io::Error> {
  function send_key_sendinput (line 107) | fn send_key_sendinput(code: u16, is_key_up: bool) {

FILE: src/oskbd/windows/scancode_to_usvk.rs
  function u16_to_osc (line 5) | pub fn u16_to_osc(input: u16) -> Option<OsCode> {
  function osc_to_u16 (line 174) | pub(crate) fn osc_to_u16(osc: OsCode) -> Option<u16> {

FILE: src/tcp_server.rs
  type HashMap (line 12) | type HashMap<K, V> = rustc_hash::FxHashMap<K, V>;
  type Connections (line 21) | pub type Connections = Arc<Mutex<HashMap<String, TcpStream>>>;
  type Connections (line 24) | pub type Connections = ();
  function send_response (line 30) | fn send_response(
  function to_action (line 45) | fn to_action(val: FakeKeyActionMessage) -> FakeKeyAction {
  function handle_reload_with_wait (line 57) | fn handle_reload_with_wait(
  type TcpServer (line 109) | pub struct TcpServer {
    method new (line 122) | pub fn new(address: SocketAddr, wakeup_channel: Sender<KeyEvent>) -> S...
    method new (line 131) | pub fn new(_address: SocketAddr, _wakeup_channel: Sender<KeyEvent>) ->...
    method start (line 136) | pub fn start(&mut self, kanata: Arc<Mutex<Kanata>>) {
    method start (line 467) | pub fn start(&mut self, _kanata: Arc<Mutex<Kanata>>) {}
  type TcpServer (line 116) | pub struct TcpServer {
    method new (line 122) | pub fn new(address: SocketAddr, wakeup_channel: Sender<KeyEvent>) -> S...
    method new (line 131) | pub fn new(_address: SocketAddr, _wakeup_channel: Sender<KeyEvent>) ->...
    method start (line 136) | pub fn start(&mut self, kanata: Arc<Mutex<Kanata>>) {
    method start (line 467) | pub fn start(&mut self, _kanata: Arc<Mutex<Kanata>>) {}
  function simple_sexpr_to_json_array (line 471) | pub fn simple_sexpr_to_json_array(exprs: &[SimpleSExpr]) -> serde_json::...

FILE: src/tests.rs
  function init_log (line 20) | fn init_log() {
  function parse_simple (line 43) | fn parse_simple() {
  function parse_minimal (line 53) | fn parse_minimal() {
  function parse_deflayermap (line 63) | fn parse_deflayermap() {
  function parse_default (line 73) | fn parse_default() {
  function parse_jtroo (line 83) | fn parse_jtroo() {
  function parse_f13_f24 (line 94) | fn parse_f13_f24() {
  function parse_home_row_mods (line 104) | fn parse_home_row_mods() {
  function parse_press_release_toggle_vkeys (line 121) | fn parse_press_release_toggle_vkeys() {
  function parse_automousekeys_only (line 134) | fn parse_automousekeys_only() {
  function parse_automousekeys_full_map (line 147) | fn parse_automousekeys_full_map() {
  function parse_push_msg (line 160) | fn parse_push_msg() {
  function sizeof_state (line 171) | fn sizeof_state() {

FILE: src/tests/passthru_macos_tests.rs
  function passthru_args (line 6) | fn passthru_args() -> ValidatedArgs {
  function passthru_runtime_output_channel_is_ready_and_emits_events (line 16) | fn passthru_runtime_output_channel_is_ready_and_emits_events() {

FILE: src/tests/sim_tests/block_keys_tests.rs
  function block_does_not_block_buttons (line 4) | fn block_does_not_block_buttons() {
  function block_does_not_block_wheel (line 22) | fn block_does_not_block_wheel() {

FILE: src/tests/sim_tests/capsword_sim_tests.rs
  constant CFG (line 3) | const CFG: &str = r##"
  function caps_word_behaves_correctly (line 15) | fn caps_word_behaves_correctly() {
  function caps_word_custom_behaves_correctly (line 30) | fn caps_word_custom_behaves_correctly() {
  function caps_word_times_out (line 45) | fn caps_word_times_out() {
  function caps_word_custom_times_out (line 56) | fn caps_word_custom_times_out() {
  function caps_word_does_not_toggle (line 67) | fn caps_word_does_not_toggle() {
  function caps_word_custom_does_not_toggle (line 77) | fn caps_word_custom_does_not_toggle() {
  function caps_word_toggle_does_toggle (line 87) | fn caps_word_toggle_does_toggle() {
  function caps_word_custom_toggle_does_toggle (line 97) | fn caps_word_custom_toggle_does_toggle() {

FILE: src/tests/sim_tests/chord_sim_tests.rs
  function sim_chord_basic_repeated_last_release (line 15) | fn sim_chord_basic_repeated_last_release() {
  function sim_chord_min_idle_takes_effect (line 28) | fn sim_chord_min_idle_takes_effect() {
  function sim_timeout_hold_key (line 47) | fn sim_timeout_hold_key() {
  function sim_chord_basic_repeated_first_release (line 59) | fn sim_chord_basic_repeated_first_release() {
  function sim_chord_overlapping_timeout (line 83) | fn sim_chord_overlapping_timeout() {
  function sim_chord_overlapping_timeout_v2 (line 89) | fn sim_chord_overlapping_timeout_v2() {
  function sim_chord_overlapping_release (line 108) | fn sim_chord_overlapping_release() {
  function sim_presses_for_old_chord_repress_into_new_chord (line 118) | fn sim_presses_for_old_chord_repress_into_new_chord() {
  function sim_chord_activate_largest_overlapping (line 128) | fn sim_chord_activate_largest_overlapping() {
  function sim_chord_layer_1_switch_disabled (line 152) | fn sim_chord_layer_1_switch_disabled() {
  function sim_chord_layer_2_switch_disabled (line 164) | fn sim_chord_layer_2_switch_disabled() {
  function sim_chord_layer_3_switch_disabled (line 176) | fn sim_chord_layer_3_switch_disabled() {
  function sim_chord_layer_1_held_disabled (line 188) | fn sim_chord_layer_1_held_disabled() {
  function sim_chord_layer_2_held_disabled (line 200) | fn sim_chord_layer_2_held_disabled() {
  function sim_chord_layer_3_held_disabled (line 212) | fn sim_chord_layer_3_held_disabled() {
  function sim_chord_layer_3_repeat (line 224) | fn sim_chord_layer_3_repeat() {
  function sim_chord_into_tap_hold (line 246) | fn sim_chord_into_tap_hold() {
  function sim_chord_pending_tap_hold (line 267) | fn sim_chord_pending_tap_hold() {
  function sim_denies_transparent (line 287) | fn sim_denies_transparent() {
  function sim_chord_eager_tapholdpress_activation (line 292) | fn sim_chord_eager_tapholdpress_activation() {
  function sim_chord_eager_tapholdrelease_activation (line 317) | fn sim_chord_eager_tapholdrelease_activation() {
  function sim_chord_release_nonchord_key_has_correct_order (line 351) | fn sim_chord_release_nonchord_key_has_correct_order() {
  function sim_chord_simultaneous_macro (line 371) | fn sim_chord_simultaneous_macro() {
  function sim_chord_error_on_duplicate_keyset (line 398) | fn sim_chord_error_on_duplicate_keyset() {
  function sim_chord_oneshot (line 414) | fn sim_chord_oneshot() {
  function sim_chord_timeout_events (line 435) | fn sim_chord_timeout_events() {
  function sim_chordsv2_quick_release (line 462) | fn sim_chordsv2_quick_release() {
  function sim_chordsv1_key_history_updates_once (line 484) | fn sim_chordsv1_key_history_updates_once() {

FILE: src/tests/sim_tests/delay_tests.rs
  function on_press_delay_must_be_single_threaded (line 5) | fn on_press_delay_must_be_single_threaded() {
  function on_release_delay_must_be_single_threaded (line 20) | fn on_release_delay_must_be_single_threaded() {
  function no_delay_must_be_single_threaded (line 35) | fn no_delay_must_be_single_threaded() {

FILE: src/tests/sim_tests/layer_sim_tests.rs
  function transparent_base (line 4) | fn transparent_base() {
  function delegate_base (line 15) | fn delegate_base() {
  function delegate_base_but_base_is_transparent (line 28) | fn delegate_base_but_base_is_transparent() {
  function layer_switching (line 41) | fn layer_switching() {
  function layer_holding (line 67) | fn layer_holding() {
  function ls_sim_switch_to_layer (line 105) | fn ls_sim_switch_to_layer() {
  function ls_sim_switch_multiple_layers (line 118) | fn ls_sim_switch_multiple_layers() {
  function ls_sim_switch_back_to_base (line 132) | fn ls_sim_switch_back_to_base() {
  function ls_sim_layer_switch_prefix (line 145) | fn ls_sim_layer_switch_prefix() {
  function ls_sim_with_delegate_to_first_layer (line 157) | fn ls_sim_with_delegate_to_first_layer() {
  function ls_sim_transparent_no_delegate (line 172) | fn ls_sim_transparent_no_delegate() {

FILE: src/tests/sim_tests/macro_sim_tests.rs
  function macro_cancel_on_press (line 4) | fn macro_cancel_on_press() {
  function test_on_press (line 15) | fn test_on_press(cfg: &str) {
  function macro_release_cancel_and_cancel_on_press (line 41) | fn macro_release_cancel_and_cancel_on_press() {
  function test_release_and_on_press (line 52) | fn test_release_and_on_press(cfg: &str) {
  function macro_repeat (line 87) | fn macro_repeat() {
  function macro_release_cancel (line 118) | fn macro_release_cancel() {
  function test_release (line 129) | fn test_release(cfg: &str) {

FILE: src/tests/sim_tests/mod.rs
  function parse_fakekey_spec (line 19) | fn parse_fakekey_spec(spec: &str) -> (&str, FakeKeyAction) {
  function apply_fakekey_action (line 38) | fn apply_fakekey_action(k: &mut Kanata, name: &str, action: FakeKeyActio...
  function apply_layer_switch (line 47) | fn apply_layer_switch(k: &mut Kanata, layer_name: &str) {
  function simulate (line 80) | fn simulate<S: AsRef<str>>(cfg: S, sim: S) -> String {
  function simulate_with_file_content (line 84) | fn simulate_with_file_content<S: AsRef<str>>(
  type SimTransform (line 156) | trait SimTransform {
    method to_spaces (line 158) | fn to_spaces(self) -> Self;
    method no_releases (line 160) | fn no_releases(self) -> Self;
    method no_time (line 162) | fn no_time(self) -> Self;
    method to_ascii (line 164) | fn to_ascii(self) -> Self;
    method to_spaces (line 168) | fn to_spaces(self) -> Self {
    method no_time (line 172) | fn no_time(self) -> Self {
    method no_releases (line 179) | fn no_releases(self) -> Self {
    method to_ascii (line 186) | fn to_ascii(self) -> Self {

FILE: src/tests/sim_tests/oneshot_tests.rs
  function oneshot_pause (line 4) | fn oneshot_pause() {
  function oneshot_multi_with_chord (line 46) | fn oneshot_multi_with_chord() {
  function oneshot_multi_with_layer (line 60) | fn oneshot_multi_with_layer() {

FILE: src/tests/sim_tests/output_chord_tests.rs
  function output_chord_samekey_has_release (line 4) | fn output_chord_samekey_has_release() {
  function output_chord_follows_processing_delay_config (line 19) | fn output_chord_follows_processing_delay_config() {

FILE: src/tests/sim_tests/override_tests.rs
  function override_with_unmod (line 4) | fn override_with_unmod() {
  function override_release_mod_change_key (line 30) | fn override_release_mod_change_key() {
  function override_eagerly_releases (line 55) | fn override_eagerly_releases() {
  function config_with_both_overrides (line 74) | fn config_with_both_overrides() {
  function config_with_two_overrides (line 89) | fn config_with_two_overrides() {
  function config_with_both_overridesv2 (line 104) | fn config_with_both_overridesv2() {
  function config_with_overridev2 (line 118) | fn config_with_overridev2() {

FILE: src/tests/sim_tests/release_sim_tests.rs
  function release_standard (line 4) | fn release_standard() {
  function release_reversed (line 19) | fn release_reversed() {

FILE: src/tests/sim_tests/repeat_sim_tests.rs
  function repeat_standard (line 4) | fn repeat_standard() {
  function repeat_layer_while_held (line 21) | fn repeat_layer_while_held() {
  function repeat_layer_switch (line 39) | fn repeat_layer_switch() {
  function repeat_layer_held_trans (line 57) | fn repeat_layer_held_trans() {
  function repeat_many_layer_held_trans (line 75) | fn repeat_many_layer_held_trans() {
  function repeat_base_layer_trans (line 100) | fn repeat_base_layer_trans() {
  function repeat_delegate_to_base_layer_trans (line 117) | fn repeat_delegate_to_base_layer_trans() {

FILE: src/tests/sim_tests/seq_sim_tests.rs
  function special_nop_keys (line 4) | fn special_nop_keys() {
  function chorded_keys_visible_backspaced (line 24) | fn chorded_keys_visible_backspaced() {
  constant OVERLAP_CFG (line 51) | const OVERLAP_CFG: &str = "
  function overlapping_activate_overlap (line 74) | fn overlapping_activate_overlap() {
  function overlapping_activate_nonoverlap (line 85) | fn overlapping_activate_nonoverlap() {
  function overlapping_then_nonoverlap_activate_overlap (line 96) | fn overlapping_then_nonoverlap_activate_overlap() {
  function overlapping_then_nonoverlap_activate_non_overlap (line 107) | fn overlapping_then_nonoverlap_activate_non_overlap() {
  function overlapping_then_overlap_activate_overlap1 (line 118) | fn overlapping_then_overlap_activate_overlap1() {
  function overlapping_then_overlap_activate_overlap2 (line 129) | fn overlapping_then_overlap_activate_overlap2() {
  function overlapping_then_overlap_activate_overlap3 (line 140) | fn overlapping_then_overlap_activate_overlap3() {
  function overlapping_then_overlap_activate_nonoverlap (line 151) | fn overlapping_then_overlap_activate_nonoverlap() {
  function non_overlapping_then_overlap_activate_overlap (line 162) | fn non_overlapping_then_overlap_activate_overlap() {
  function non_overlapping_then_overlap_activate_nothing (line 173) | fn non_overlapping_then_overlap_activate_nothing() {
  function noerase (line 212) | fn noerase() {
  function tap_hold_pending (line 241) | fn tap_hold_pending() {

FILE: src/tests/sim_tests/switch_sim_tests.rs
  function sim_switch_layer (line 4) | fn sim_switch_layer() {
  function sim_switch_base_layer (line 22) | fn sim_switch_base_layer() {
  function sim_switch_noop (line 40) | fn sim_switch_noop() {
  function sim_switch_trans_not_top_layer (line 56) | fn sim_switch_trans_not_top_layer() {

FILE: src/tests/sim_tests/tap_dance_tests.rs
  function tap_dance_eager_with_mlft (line 4) | fn tap_dance_eager_with_mlft() {

FILE: src/tests/sim_tests/tap_hold_tests.rs
  function delayed_timedout_released_taphold_can_still_tap (line 4) | fn delayed_timedout_released_taphold_can_still_tap() {
  function delayed_timedout_released_taphold_can_hold (line 25) | fn delayed_timedout_released_taphold_can_hold() {
  function tap_hold_release_timeout_no_reset (line 43) | fn tap_hold_release_timeout_no_reset() {
  function tap_hold_release_timeout_with_reset (line 56) | fn tap_hold_release_timeout_with_reset() {
  function on_physical_idle_with_tap_repress (line 69) | fn on_physical_idle_with_tap_repress() {
  function tap_hold_release_tap_keys_release (line 92) | fn tap_hold_release_tap_keys_release() {
  function tap_hold_release_keys (line 124) | fn tap_hold_release_keys() {
  function tap_hold_tap_keys (line 144) | fn tap_hold_tap_keys() {
  function opposite_hand_cfg (line 177) | fn opposite_hand_cfg() -> &'static str {
  function opposite_hand_press_resolves_hold (line 190) | fn opposite_hand_press_resolves_hold() {
  function same_hand_press_resolves_tap (line 200) | fn same_hand_press_resolves_tap() {
  function same_hand_ignore_defers_to_timeout (line 216) | fn same_hand_ignore_defers_to_timeout() {
  function neutral_key_ignore_defers (line 233) | fn neutral_key_ignore_defers() {
  function neutral_key_tap_resolves_immediately (line 253) | fn neutral_key_tap_resolves_immediately() {
  function unknown_hand_key_defers_by_default (line 272) | fn unknown_hand_key_defers_by_default() {
  function timeout_default_is_tap (line 289) | fn timeout_default_is_tap() {
  function timeout_hold_option (line 296) | fn timeout_hold_option() {
  function release_before_timeout_taps (line 312) | fn release_before_timeout_taps() {
  function multiple_options_combined (line 319) | fn multiple_options_combined() {
  function unknown_hand_tap_resolves_immediately (line 341) | fn unknown_hand_tap_resolves_immediately() {
  function unknown_hand_hold_resolves_immediately (line 357) | fn unknown_hand_hold_resolves_immediately() {
  function neutral_key_hold_resolves_immediately (line 376) | fn neutral_key_hold_resolves_immediately() {
  function waiting_key_unassigned_in_defhands (line 395) | fn waiting_key_unassigned_in_defhands() {
  function neutral_keys_override_defhands_assignment (line 413) | fn neutral_keys_override_defhands_assignment() {
  function tap_hold_require_prior_idle_typing_streak_resolves_tap (line 434) | fn tap_hold_require_prior_idle_typing_streak_resolves_tap() {
  function tap_hold_require_prior_idle_idle_long_enough_enters_hold (line 452) | fn tap_hold_require_prior_idle_idle_long_enough_enters_hold() {
  function tap_hold_require_prior_idle_no_prior_key_enters_hold (line 470) | fn tap_hold_require_prior_idle_no_prior_key_enters_hold() {
  function tap_hold_require_prior_idle_boundary_just_within_threshold (line 487) | fn tap_hold_require_prior_idle_boundary_just_within_threshold() {
  function tap_hold_require_prior_idle_boundary_just_outside_threshold (line 505) | fn tap_hold_require_prior_idle_boundary_just_outside_threshold() {
  function tap_hold_require_prior_idle_with_opposite_hand (line 524) | fn tap_hold_require_prior_idle_with_opposite_hand() {
  function tap_hold_require_prior_idle_with_tap_hold_interval (line 546) | fn tap_hold_require_prior_idle_with_tap_hold_interval() {
  function tap_hold_require_prior_idle_ignores_virtual_keys (line 565) | fn tap_hold_require_prior_idle_ignores_virtual_keys() {
  function per_action_require_prior_idle_overrides_global (line 588) | fn per_action_require_prior_idle_overrides_global() {
  function per_action_require_prior_idle_disable_overrides_global (line 607) | fn per_action_require_prior_idle_disable_overrides_global() {
  function per_action_require_prior_idle_enables_without_global (line 627) | fn per_action_require_prior_idle_enables_without_global() {
  function per_action_require_prior_idle_mixed_actions (line 644) | fn per_action_require_prior_idle_mixed_actions() {
  function per_action_require_prior_idle_with_tap_hold_release (line 671) | fn per_action_require_prior_idle_with_tap_hold_release() {
  function per_action_require_prior_idle_with_opposite_hand (line 690) | fn per_action_require_prior_idle_with_opposite_hand() {
  function tap_hold_order_clean_tap (line 722) | fn tap_hold_order_clean_tap() {
  function tap_hold_order_hold_other_released_first (line 737) | fn tap_hold_order_hold_other_released_first() {
  function tap_hold_order_tap_modifier_released_first (line 755) | fn tap_hold_order_tap_modifier_released_first() {
  function tap_hold_order_buffer_ignores_fast_typing (line 770) | fn tap_hold_order_buffer_ignores_fast_typing() {
  function tap_hold_order_hold_after_buffer_expires (line 788) | fn tap_hold_order_hold_after_buffer_expires() {
  function tap_hold_order_with_require_prior_idle (line 809) | fn tap_hold_order_with_require_prior_idle() {
  function tap_hold_order_no_prior_idle_enters_normal_resolution (line 825) | fn tap_hold_order_no_prior_idle_enters_normal_resolution() {

FILE: src/tests/sim_tests/template_sim_tests.rs
  function nested_template (line 4) | fn nested_template() {

FILE: src/tests/sim_tests/timing_tests.rs
  function one_second_is_roughly_1000_counted_ticks (line 9) | fn one_second_is_roughly_1000_counted_ticks() {

FILE: src/tests/sim_tests/unicode_sim_tests.rs
  function unicode (line 4) | fn unicode() {
  function macos_unicode_handling (line 26) | fn macos_unicode_handling() {
  function unicode_pulus (line 42) | fn unicode_pulus() {

FILE: src/tests/sim_tests/unmod_sim_tests.rs
  function unmod_keys_functionality_works (line 4) | fn unmod_keys_functionality_works() {
  function unmod_keys_mod_list_cannot_be_empty (line 47) | fn unmod_keys_mod_list_cannot_be_empty() {
  function unmod_keys_mod_list_cannot_have_nonmod_key (line 60) | fn unmod_keys_mod_list_cannot_have_nonmod_key() {
  function unmod_keys_mod_list_cannot_have_empty_keys_after_mod_list (line 73) | fn unmod_keys_mod_list_cannot_have_empty_keys_after_mod_list() {
  function unmod_keys_mod_list_cannot_have_empty_keys (line 86) | fn unmod_keys_mod_list_cannot_have_empty_keys() {
  function unmod_keys_mod_list_cannot_have_invalid_keys (line 99) | fn unmod_keys_mod_list_cannot_have_invalid_keys() {

FILE: src/tests/sim_tests/use_defsrc_sim_tests.rs
  function use_defsrc_deflayer (line 4) | fn use_defsrc_deflayer() {
  function use_defsrc_deflayermap (line 26) | fn use_defsrc_deflayermap() {

FILE: src/tests/sim_tests/vkey_sim_tests.rs
  function hold_for_duration (line 4) | fn hold_for_duration() {
  function vk_sim_default_press (line 34) | fn vk_sim_default_press() {
  function vk_sim_explicit_press (line 48) | fn vk_sim_explicit_press() {
  function vk_sim_press_shorthand (line 61) | fn vk_sim_press_shorthand() {
  function vk_sim_release (line 73) | fn vk_sim_release() {
  function vk_sim_tap (line 86) | fn vk_sim_tap() {
  function vk_sim_tap_shorthand (line 99) | fn vk_sim_tap_shorthand() {
  function vk_sim_toggle (line 111) | fn vk_sim_toggle() {
  function vk_sim_toggle_shorthand (line 125) | fn vk_sim_toggle_shorthand() {
  function vk_sim_fakekey_prefix (line 137) | fn vk_sim_fakekey_prefix() {
  function vk_sim_virtualkey_prefix (line 149) | fn vk_sim_virtualkey_prefix() {
  function vk_sim_emoji_prefix (line 161) | fn vk_sim_emoji_prefix() {
  function vk_sim_layer_switch (line 173) | fn vk_sim_layer_switch() {
  function vk_sim_multiple_vkeys (line 187) | fn vk_sim_multiple_vkeys() {
  function on_idle_must_be_single_threaded (line 221) | fn on_idle_must_be_single_threaded() {

FILE: src/tests/sim_tests/zippychord_sim_tests.rs
  function simulate_with_zippy_file_content (line 22) | fn simulate_with_zippy_file_content(cfg: &str, input: &str, content: &st...
  function sim_zippychord_capitalize (line 29) | fn sim_zippychord_capitalize() {
  function sim_zippychord_followup_with_prev (line 52) | fn sim_zippychord_followup_with_prev() {
  function sim_zippychord_followup_no_prev (line 70) | fn sim_zippychord_followup_no_prev() {
  function sim_zippychord_washington (line 86) | fn sim_zippychord_washington() {
  function sim_zippychord_overlap (line 107) | fn sim_zippychord_overlap() {
  function sim_zippychord_lsft (line 133) | fn sim_zippychord_lsft() {
  function sim_zippychord_rsft (line 182) | fn sim_zippychord_rsft() {
  function sim_zippychord_ralt (line 231) | fn sim_zippychord_ralt() {
  function sim_zippychord_caps_word (line 280) | fn sim_zippychord_caps_word() {
  function sim_zippychord_triple_combo (line 310) | fn sim_zippychord_triple_combo() {
  function sim_zippychord_disabled_by_typing (line 329) | fn sim_zippychord_disabled_by_typing() {
  function sim_zippychord_prefix (line 340) | fn sim_zippychord_prefix() {
  function sim_zippychord_smartspace_full (line 372) | fn sim_zippychord_smartspace_full() {
  function sim_zippychord_smartspace_spaceonly (line 403) | fn sim_zippychord_smartspace_spaceonly() {
  function sim_zippychord_smartspace_none (line 434) | fn sim_zippychord_smartspace_none() {
  function sim_zippychord_smartspace_overlap (line 465) | fn sim_zippychord_smartspace_overlap() {
  function sim_zippychord_smartspace_followup (line 498) | fn sim_zippychord_smartspace_followup() {
  constant CUSTOM_PUNC_CFG (line 516) | const CUSTOM_PUNC_CFG: &str = "\
  function sim_zippychord_smartspace_custom_punc (line 528) | fn sim_zippychord_smartspace_custom_punc() {
  function sim_zippychord_non_followup_subsequent_with_potential_followups_available (line 622) | fn sim_zippychord_non_followup_subsequent_with_potential_followups_avail...
  constant DEAD_KEYS_CFG (line 639) | const DEAD_KEYS_CFG: &str = "\
  function sim_zippychord_noerase (line 662) | fn sim_zippychord_noerase() {
  function sim_zippychord_single_output (line 697) | fn sim_zippychord_single_output() {

FILE: tcp_protocol/src/lib.rs
  type ServerMessage (line 11) | pub enum ServerMessage {
    method as_bytes (line 79) | pub fn as_bytes(&self) -> Vec<u8> {
  type ServerResponse (line 65) | pub enum ServerResponse {
    method as_bytes (line 71) | pub fn as_bytes(&self) -> Vec<u8> {
  type ClientMessage (line 88) | pub enum ClientMessage {
  type FakeKeyActionMessage (line 147) | pub enum FakeKeyActionMessage {
  type Err (line 155) | type Err = serde_json::Error;
  method from_str (line 157) | fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
  function test_server_response_json_format (line 167) | fn test_server_response_json_format() {
  function test_as_bytes_includes_newline (line 175) | fn test_as_bytes_includes_newline() {
  function test_hello_ok_json_format (line 181) | fn test_hello_ok_json_format() {
  function test_reload_with_wait (line 193) | fn test_reload_with_wait() {
  function test_reload_minimal (line 204) | fn test_reload_minimal() {
  function test_existing_commands_unchanged (line 218) | fn test_existing_commands_unchanged() {
  function test_request_fake_key_names (line 232) | fn test_request_fake_key_names() {
  function test_fake_key_names_response (line 239) | fn test_fake_key_names_response() {
  function test_fake_key_names_empty (line 260) | fn test_fake_key_names_empty() {
  function test_hold_activated_json_format (line 267) | fn test_hold_activated_json_format() {
  function test_tap_activated_json_format (line 276) | fn test_tap_activated_json_format() {

FILE: wasm/src/lib.rs
  function init (line 11) | pub fn init() {
  function check_config (line 18) | pub fn check_config(cfg: &str) -> JsValue {
  function simulate (line 28) | pub fn simulate(cfg: &str, sim: &str) -> JsValue {
  function split_cfg_and_sim_files (line 35) | fn split_cfg_and_sim_files(original_cfg: &str) -> (String, FxHashMap<Str...
  function parse_fakekey_spec (line 75) | fn parse_fakekey_spec(spec: &str) -> Result<(&str, FakeKeyAction)> {
  function apply_fakekey_action (line 97) | fn apply_fakekey_action(k: &mut K
Condensed preview — 272 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,487K chars).
[
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 618,
    "preview": "{\n\t\"name\": \"Rust\",\n\t\"image\": \"mcr.microsoft.com/devcontainers/rust:1-buster\"\n\n\t// Features to add to the dev container. "
  },
  {
    "path": ".gitattributes",
    "chars": 19,
    "preview": "* text=auto eol=lf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 2974,
    "preview": "name: \"Bug report\"\ndescription: Create a report to help the project improve.\nlabels: [\"bug\"]\nassignees: [\"jtroo\"]\ntitle:"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 172,
    "preview": "blank_issues_enabled: true\ncontact_links:\n  - name: Discussions\n    url: https://github.com/jtroo/kanata/discussions\n   "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 1117,
    "preview": "name: \"Feature request\"\ndescription: Suggest an idea for this project\ntitle: 'Feature request: feature_summary_goes_here"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 296,
    "preview": "## Describe your changes. Use imperative present tense.\n\n## Checklist\n\n- Add documentation to docs/config.adoc\n  - [ ] Y"
  },
  {
    "path": ".github/workflows/build-everything.yml",
    "chars": 327,
    "preview": "name: build-everything\n\non:\n  workflow_dispatch:\n    branches: [ \"main\" ]\n\nenv:\n  CARGO_TERM_COLOR: always\n  RUSTFLAGS: "
  },
  {
    "path": ".github/workflows/linux-build.yml",
    "chars": 864,
    "preview": "name: linux-build\n\non:\n  workflow_dispatch:\n    branches: [ \"main\" ]\n  workflow_call:\n\nenv:\n  CARGO_TERM_COLOR: always\n\n"
  },
  {
    "path": ".github/workflows/macos-build.yml",
    "chars": 1778,
    "preview": "name: macos-build\n\non:\n  workflow_dispatch:\n    branches: [ \"main\" ]\n  workflow_call:\n\nenv:\n  CARGO_TERM_COLOR: always\n\n"
  },
  {
    "path": ".github/workflows/rust.yml",
    "chars": 5235,
    "preview": "name: cargo-checks\n\non:\n  push:\n    branches: [ \"main\" ]\n    paths:\n      - Cargo.*\n      - src/**/*\n      - keyberon/**"
  },
  {
    "path": ".github/workflows/windows-build.yml",
    "chars": 4977,
    "preview": "name: windows-build\n\non:\n  workflow_dispatch:\n    branches: [ \"main\" ]\n  workflow_call:\n\nenv:\n  CARGO_TERM_COLOR: always"
  },
  {
    "path": ".gitignore",
    "chars": 106,
    "preview": "**/target\n.vscode/\nCLAUDE.md\n.DS_Store\nPLAN.md\n\n# Manual testing files\ntest_*.kbd\nmanual_test/\n*.test.kbd\n"
  },
  {
    "path": "Cargo.toml",
    "chars": 4903,
    "preview": "[workspace]\nmembers = [\n\t\"./\",\n\t\"parser\",\n\t\"keyberon\",\n\t\"example_tcp_client\",\n\t\"tcp_protocol\",\n\t\"windows_key_tester\",\n\t\""
  },
  {
    "path": "EnableUIAccess/EnableUIAccess_launch.ahk",
    "chars": 5247,
    "preview": "#requires AutoHotkey v2.0\n#SingleInstance Off ; Needed for elevation with *runas.\n/* v2 based on EnableUIAccess.ahk v1.0"
  },
  {
    "path": "EnableUIAccess/Lib/EnableUIAccess.ahk",
    "chars": 10458,
    "preview": "#requires AutoHotkey v2.0\n\nEnableUIAccess(ExePath) {\n  static CertName := \"AutoHotkey\"\n  hStore := DllCall(\"Crypt32\\Cert"
  },
  {
    "path": "EnableUIAccess/README.md",
    "chars": 148,
    "preview": "# EnableUIAccess\n\nSee [the guide documentation for context](https://github.com/jtroo/kanata/blob/main/docs/config.adoc#w"
  },
  {
    "path": "LICENSE",
    "chars": 7651,
    "preview": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007"
  },
  {
    "path": "README.md",
    "chars": 13364,
    "preview": "<h1 align=\"center\">Kanata</h1>\n\n<h3 align=\"center\">\n  <img\n    alt=\"Image of a keycap with the letter K on it in pink to"
  },
  {
    "path": "build.rs",
    "chars": 3252,
    "preview": "fn main() -> std::io::Result<()> {\n    #[cfg(feature = \"win_manifest\")]\n    {\n        windows::build()?;\n    }\n    Ok(()"
  },
  {
    "path": "cfg_samples/artsey.kbd",
    "chars": 1662,
    "preview": ";; ARTSEY MINI 0.2 https://github.com/artseyio/artsey/issues/7\n\n;; Exactly one defcfg entry is required. This is used fo"
  },
  {
    "path": "cfg_samples/automousekeys-full-map.kbd",
    "chars": 2123,
    "preview": "(defcfg\n  ;; F* keys and arrow keys are left unmapped\n  process-unmapped-keys yes\n\n  ;; you may wish to only capture a t"
  },
  {
    "path": "cfg_samples/automousekeys-only.kbd",
    "chars": 1232,
    "preview": "(defcfg\n  ;; we are only mapping the keys we want to use for mouse keys\n  process-unmapped-keys yes\n\n  ;; you may wish t"
  },
  {
    "path": "cfg_samples/chords.tsv",
    "chars": 1569,
    "preview": "rus\trust\ncol\tcool\nnice\tnice\nyou\tyou\nth\tthe\n a\ta\n an\tan\nman\tman\nname\tname\nan\tand\nas\tas\nor\tor\nbu\tbut\nif\tif\nso\tso\ndn\tthen\nb"
  },
  {
    "path": "cfg_samples/colemak.kbd",
    "chars": 1246,
    "preview": ";;\n;;  Learn Colemak, a few keys at a time.\n;;\n;;  The \"j\" key moves around the keyboard each step,\n;;  until you reach "
  },
  {
    "path": "cfg_samples/deflayermap.kbd",
    "chars": 738,
    "preview": ";; A configuration showcasing deflayermap.\n;;\n;; The process-unmapped-keys defcfg item is not used\n;; and the lctl and r"
  },
  {
    "path": "cfg_samples/f13_f24.kbd",
    "chars": 236,
    "preview": "(defcfg\n  linux-dev /dev/input/by-path/platform-i8042-serio-0-event-kbd\n)\n\n(defsrc\n       f13  f14  f15  f16  f17  f18  "
  },
  {
    "path": "cfg_samples/fancy_symbols.kbd",
    "chars": 1908,
    "preview": ";; Turns   ⎇›            RightAlt into a symbol key to insert valid kanata unicode symbols for the pressed key\n;; Turns "
  },
  {
    "path": "cfg_samples/home-row-mod-advanced.kbd",
    "chars": 2038,
    "preview": ";; Home row mods QWERTY example with more complexity.\n;; Some of the changes from the basic example:\n;; - when a home ro"
  },
  {
    "path": "cfg_samples/home-row-mod-basic.kbd",
    "chars": 830,
    "preview": ";; Basic home row mods example using QWERTY\n;; For a more complex but perhaps usable configuration,\n;; see home-row-mod-"
  },
  {
    "path": "cfg_samples/home-row-mod-prior-idle.kbd",
    "chars": 1748,
    "preview": ";; Home row mods with tap-hold-require-prior-idle.\n;;\n;; This replaces the layer-switching workaround in home-row-mod-ad"
  },
  {
    "path": "cfg_samples/included-file.kbd",
    "chars": 67,
    "preview": "(defalias\n  included-alias (macro i spc a m spc i n c l u d e d)\n)\n"
  },
  {
    "path": "cfg_samples/japanese_mac_eisu_kana.kbd",
    "chars": 417,
    "preview": "#|\n  Using meta keys as japanese eisu and kana on Mac with US keyboard.\n\n  | Source  | Tap          | Hold |\n  | -------"
  },
  {
    "path": "cfg_samples/jtroo.kbd",
    "chars": 5412,
    "preview": "(defsrc\n  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc\n  tab  q    w    e    r    t    y    u  "
  },
  {
    "path": "cfg_samples/kanata.kbd",
    "chars": 63293,
    "preview": "#|\nThis is a sample configuration file that showcases every feature in kanata.\nA more detailed and less terse configurat"
  },
  {
    "path": "cfg_samples/key-toggle_press-only_release-only.kbd",
    "chars": 754,
    "preview": "#|\n\nThis configuration showcases all of:\n\t- key toggle\n\t- press-only\n\t- release-only\n\n|#\n\n(deftemplate toggle-key (vkey-"
  },
  {
    "path": "cfg_samples/minimal.kbd",
    "chars": 1391,
    "preview": "#|\nThis minimal config changes Caps Lock to act as Caps Lock on quick tap, but\nif held, it will act as Left Ctrl. It als"
  },
  {
    "path": "cfg_samples/opposite-hand-hrm.kbd",
    "chars": 1313,
    "preview": ";; Home row mods using tap-hold-opposite-hand\n;;\n;; Hold activates only when the next key is on the opposite hand,\n;; wh"
  },
  {
    "path": "cfg_samples/push-msg.kbd",
    "chars": 3272,
    "preview": ";; push-msg Sample Configuration\n;;\n;; This configuration demonstrates the push-msg action for sending\n;; messages to ex"
  },
  {
    "path": "cfg_samples/simple.kbd",
    "chars": 3727,
    "preview": ";; Comments are prefixed by double-semicolon. A single semicolon is parsed as the\n;; keyboard key. Comments are ignored "
  },
  {
    "path": "cfg_samples/tray-icon/license_icons.txt",
    "chars": 1299,
    "preview": "BSD 2-Clause License\n\nCopyright (c) 2024, Fred Vatin\n\nRedistribution and use in source and binary forms, with or without"
  },
  {
    "path": "cfg_samples/tray-icon/tray-icon.kbd",
    "chars": 2321,
    "preview": "(defcfg\n  process-unmapped-keys\t\tyes\t;;|no| enable processing of keys that are not in defsrc, useful if mapping a few ke"
  },
  {
    "path": "docs/README.md",
    "chars": 201,
    "preview": "\n### Converting \".adoc\" to html\n\nTo generate html from the these documentation files, use [\"asciidoctor\"](https://asciid"
  },
  {
    "path": "docs/config-stylesheet.css",
    "chars": 31333,
    "preview": "html{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:ho"
  },
  {
    "path": "docs/config.adoc",
    "chars": 189327,
    "preview": "= Kanata Configuration Guide\n:last-update-label!:\nifndef::env-github[]\n:toc: left\nendif::[]\n:stylesheet: config-styleshe"
  },
  {
    "path": "docs/design.md",
    "chars": 1036,
    "preview": "# Design doc\n\n## Obligatory diagram\n\n<img src=\"./kanata-basic-diagram.svg\">\n\n## main\n\n- read args\n- read config\n- start "
  },
  {
    "path": "docs/fancy_symbols.md",
    "chars": 2749,
    "preview": "### Supported key symbols\n\n  |Symbol(s)[^1] \t|Key `name`                                \t|\n  |---------     \t|--------  "
  },
  {
    "path": "docs/interception.md",
    "chars": 979,
    "preview": "# Windows Interception driver implementation notes\n\n- Interception handle is `!Send` and `!Sync`\n  - means a single thre"
  },
  {
    "path": "docs/kmonad_comparison.md",
    "chars": 1512,
    "preview": "# Comparison with kmonad\n\nThe kmonad project is the closest alternative for this project.\n\n## Benefits of kmonad over ka"
  },
  {
    "path": "docs/locales.adoc",
    "chars": 8825,
    "preview": "////\nCommented out since it doesn't seem to add anything for now, but maybe in the future\n:sectlinks:\n:sectanchors:\n////"
  },
  {
    "path": "docs/platform-known-issues.adoc",
    "chars": 3999,
    "preview": "= Hardware known issues\n\nAt the electric circuit layer of many keyboards,\ncost-saving measures can lead to key presses n"
  },
  {
    "path": "docs/release-template.md",
    "chars": 6975,
    "preview": "## Configuration guide\n\n<!-- NOTE: GitHub release doc seems to not support multiline paragraph joining as opposed to oth"
  },
  {
    "path": "docs/sequence-adding-chords-ideas.md",
    "chars": 5534,
    "preview": "# Sequence improvement: sequence chords\n\n## Preface\n\nThis document is a record of designing/braindumping\nfor the improve"
  },
  {
    "path": "docs/setup-linux.md",
    "chars": 4116,
    "preview": "# Instructions\n\nIn Linux, kanata needs to be able to access the input and uinput subsystem to inject events. To do this,"
  },
  {
    "path": "docs/simulated_output/sim.kbd",
    "chars": 1497,
    "preview": "(defcfg\n  process-unmapped-keys\tyes\t;;|no| enable processing of keys that are not in defsrc, useful if mapping a few key"
  },
  {
    "path": "docs/simulated_output/sim.txt",
    "chars": 60,
    "preview": "↓j 🕐1600 ↓l 🕐5000 ↓1 🕐50 ↑1 🕐50 ↓1 🕐50 ↑1 🕐50 ↑j 🕐50 ↑l 🕐50\n"
  },
  {
    "path": "docs/simulated_output/sim_out.txt",
    "chars": 1094,
    "preview": "🕐Δms│           1500    100        1500    3500            50      50            50      50              50\nIn───┼──────"
  },
  {
    "path": "docs/simulated_passthru_ahk/[COPY HERE] kanata_passthru.dll _",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/simulated_passthru_ahk/kanata_dll.kbd",
    "chars": 555,
    "preview": ";;Test config for kanata.dll use by AutoHotkey, only maps two keys (f,j) to left/right modtap home row mod Shifts\n(defcf"
  },
  {
    "path": "docs/simulated_passthru_ahk/kanata_passthru.ahk",
    "chars": 10758,
    "preview": "#Requires AutoHotKey 2.1-alpha.4\n/*\nA short example of using Kanata as a library with AutoHotkey, first F8 press will lo"
  },
  {
    "path": "docs/switch-design",
    "chars": 3092,
    "preview": "# Preface:\n\nThis document is a scratch space for the design of the switch action.\nIt may be out of date and is kept arou"
  },
  {
    "path": "example_tcp_client/.gitignore",
    "chars": 7,
    "preview": "target\n"
  },
  {
    "path": "example_tcp_client/Cargo.toml",
    "chars": 367,
    "preview": "[package]\nname = \"kanata_example_tcp_client\"\ndescription = \"Example kanata TCP client\"\nversion = \"1.1.0\"\nedition = \"2021"
  },
  {
    "path": "example_tcp_client/src/main.rs",
    "chars": 8877,
    "preview": "use clap::Parser;\nuse kanata_tcp_protocol::*;\nuse simplelog::*;\nuse std::io::{BufRead, BufReader, Write, stdin};\nuse std"
  },
  {
    "path": "interception/Cargo.toml",
    "chars": 441,
    "preview": "[workspace]\nmembers = [\".\"]\n\n[package]\nname = \"kanata-interception\"\ndescription = \"Safe wrapper for Interception. Forked"
  },
  {
    "path": "interception/src/lib.rs",
    "chars": 9780,
    "preview": "pub extern crate interception_sys;\n\n#[macro_use]\nextern crate bitflags;\n\npub use interception_sys as raw;\npub mod scanco"
  },
  {
    "path": "interception/src/scancode.rs",
    "chars": 4853,
    "preview": "use num_enum::TryFromPrimitive;\nuse serde::{Deserialize, Serialize};\n\n// ref: https://handmade.network/wiki/2823-keyboar"
  },
  {
    "path": "justfile",
    "chars": 5215,
    "preview": "set windows-shell := [\"powershell.exe\", \"-NoLogo\", \"-Command\"]\n\n# Build the release binaries for Linux and put the binar"
  },
  {
    "path": "key-sort-add/Cargo.toml",
    "chars": 210,
    "preview": "[workspace]\nmembers = [\".\"]\n\n[package]\nname = \"key-sort-add\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and the"
  },
  {
    "path": "key-sort-add/README.md",
    "chars": 83,
    "preview": "# key-sort-add\n\nA small program that was used to sort and fill in OsCode mappings.\n"
  },
  {
    "path": "key-sort-add/mapping.txt",
    "chars": 43054,
    "preview": "=== kc to osc\nKeyCode::Escape => OsCode::KEY_ESC,\nKeyCode::Kb1 => OsCode::KEY_1,\nKeyCode::Kb2 => OsCode::KEY_2,\nKeyCode:"
  },
  {
    "path": "key-sort-add/src/main.rs",
    "chars": 3745,
    "preview": "//! one:\n//!\n//! Takes a file formatted as:\n//!\n//!     KEY_RESERVED = 0,\n//!     KEY_ESC = 1,\n//!     KEY_1 = 2,\n//!   "
  },
  {
    "path": "keyberon/.gitignore",
    "chars": 61,
    "preview": "# Ignore Cargo.lock since this is a library crate\nCargo.lock\n"
  },
  {
    "path": "keyberon/CHANGELOG.md",
    "chars": 1477,
    "preview": "# v0.2.0\n\n* New Keyboard::leds_mut function for getting underlying leds object.\n* Made Layout::current_layer public for "
  },
  {
    "path": "keyberon/Cargo.toml",
    "chars": 665,
    "preview": "[package]\nname = \"kanata-keyberon\"\nversion = \"0.1110.0\"\nauthors = [\"Guillaume Pinot <texitoi@texitoi.eu>\", \"Robin Krahl "
  },
  {
    "path": "keyberon/KEYBOARDS.md",
    "chars": 3522,
    "preview": "| Keyboard                                                                   | PCB or Handwired | MCU       | Feature St"
  },
  {
    "path": "keyberon/LICENSE",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2019 Guillaume P.\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "keyberon/README.md",
    "chars": 313,
    "preview": "# kanata-keyberon\n\n## Note\n\nThis is a fork intended for use by the [kanata keyboard remapper software](https://github.co"
  },
  {
    "path": "keyberon/keyberon-macros/Cargo.toml",
    "chars": 282,
    "preview": "[package]\nname = \"kanata-keyberon-macros\"\nversion = \"0.2.0\"\nauthors = [\"Antoni Simka <antonisimka.8@gmail.com>\"]\nedition"
  },
  {
    "path": "keyberon/keyberon-macros/README.md",
    "chars": 253,
    "preview": "# kanata keyberon macros\n\n## Note\n\nThis is a fork intended for use by the [kanata keyboard remapper software](https://gi"
  },
  {
    "path": "keyberon/keyberon-macros/src/lib.rs",
    "chars": 10536,
    "preview": "extern crate proc_macro;\nuse proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, TokenStream, TokenTree};\nuse quote"
  },
  {
    "path": "keyberon/src/action/switch.rs",
    "chars": 42152,
    "preview": "//! Handle processing of the switch action for Keyberon.\n//!\n//! Limitations:\n//! - Maximum opcode length: 4095\n//! - Ma"
  },
  {
    "path": "keyberon/src/action.rs",
    "chars": 19490,
    "preview": "//! The different actions that can be executed via any given key.\n\nuse crate::key_code::KeyCode;\nuse crate::layout::{KCo"
  },
  {
    "path": "keyberon/src/chord.rs",
    "chars": 23798,
    "preview": "//! Module for chords v2 implementation.\n\nuse std::cell::Cell;\n\nuse arraydeque::ArrayDeque;\nuse heapless::Vec as HVec;\nu"
  },
  {
    "path": "keyberon/src/key_code.rs",
    "chars": 16507,
    "preview": "//! Key code definitions.\n\n/// Used for switch opcode purposes. Keys should not exceed this amount.\npub const KEY_MAX: u"
  },
  {
    "path": "keyberon/src/layout/contextual_execution.rs",
    "chars": 760,
    "preview": "//! Information about what state the keyberon layout is in\r\n//! and handling conditional execution based on state.\r\n\r\nus"
  },
  {
    "path": "keyberon/src/layout.rs",
    "chars": 206205,
    "preview": "//! Layout management.\n\n/// A procedural macro to generate [Layers](type.Layers.html)\n/// ## Syntax\n/// Items inside the"
  },
  {
    "path": "keyberon/src/lib.rs",
    "chars": 281,
    "preview": "//! This is a fork intended for use by the [kanata keyboard remapper software](https://github.com/jtroo/kanata).\n//! Ple"
  },
  {
    "path": "keyberon/src/multikey_buffer.rs",
    "chars": 2731,
    "preview": "//! Module for `MultiKeyBuffer`.\n\nuse std::{array, slice};\n\nuse crate::action::{Action, ONE_SHOT_MAX_ACTIVE};\nuse crate:"
  },
  {
    "path": "keyberon/src/tap_hold_tracker.rs",
    "chars": 3750,
    "preview": "//! Tracks tap-hold activation events for external consumers (e.g. TCP broadcast).\n//!\n//! When the `tap_hold_tracker` f"
  },
  {
    "path": "parser/.gitignore",
    "chars": 67,
    "preview": "# Ignore Cargo.lock since this is a library crate\nCargo.lock\ntarget"
  },
  {
    "path": "parser/Cargo.toml",
    "chars": 942,
    "preview": "[package]\nname = \"kanata-parser\"\nversion = \"0.1110.0\"\nauthors = [\"jtroo <j.andreitabs@gmail.com>\"]\ndescription = \"A pars"
  },
  {
    "path": "parser/LICENSE",
    "chars": 7651,
    "preview": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007"
  },
  {
    "path": "parser/README.md",
    "chars": 168,
    "preview": "# kanata-parser\n\nA parser for configuration language of [kanata](https://github.com/jtroo/kanata).\n\nThis crate does not "
  },
  {
    "path": "parser/src/cfg/alloc.rs",
    "chars": 4330,
    "preview": "//! This module contains a helper struct for generating 'static lifetime allocations while still\n//! keeping track of th"
  },
  {
    "path": "parser/src/cfg/arbitrary_code.rs",
    "chars": 617,
    "preview": "use super::*;\n\nuse crate::bail;\nuse anyhow::anyhow;\n\npub(crate) fn parse_arbitrary_code(\n    ac_params: &[SExpr],\n    s:"
  },
  {
    "path": "parser/src/cfg/caps_word.rs",
    "chars": 3474,
    "preview": "use super::*;\n\nuse crate::bail;\n\npub(crate) fn parse_caps_word(\n    ac_params: &[SExpr],\n    repress_behaviour: CapsWord"
  },
  {
    "path": "parser/src/cfg/chord.rs",
    "chars": 11553,
    "preview": "use itertools::Itertools;\nuse kanata_keyberon::chord::{ChordV2, ChordsForKey, ChordsForKeys, ReleaseBehaviour};\nuse rust"
  },
  {
    "path": "parser/src/cfg/chord_v1.rs",
    "chars": 12578,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::anyhow_span;\nuse crate::bail;\nuse crate::bail_expr;\nuse crate::bail_sp"
  },
  {
    "path": "parser/src/cfg/clipboard.rs",
    "chars": 3052,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail;\nuse crate::bail_expr;\n\npub(crate) fn parse_clipboard_set(\n    ac"
  },
  {
    "path": "parser/src/cfg/cmd.rs",
    "chars": 5133,
    "preview": "use super::*;\n\nuse crate::bail;\nuse crate::bail_expr;\n\npub(crate) enum CmdType {\n    /// Execute command in own thread.\n"
  },
  {
    "path": "parser/src/cfg/custom_tap_hold.rs",
    "chars": 9301,
    "preview": "use kanata_keyberon::layout::{Event, KCoord, QueuedIter, REAL_KEY_ROW, WaitingAction};\n\nuse crate::keys::OsCode;\n\nuse su"
  },
  {
    "path": "parser/src/cfg/defcfg.rs",
    "chars": 51093,
    "preview": "use super::HashSet;\nuse super::sexpr::SExpr;\nuse super::{TrimAtomQuotes, error::*};\nuse crate::cfg::check_first_expr;\nus"
  },
  {
    "path": "parser/src/cfg/defhands.rs",
    "chars": 9232,
    "preview": "use super::sexpr::*;\nuse super::*;\nuse crate::{anyhow_expr, bail, bail_expr};\n\npub(super) fn parse_defhands(expr: &[SExp"
  },
  {
    "path": "parser/src/cfg/deflayer.rs",
    "chars": 12494,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::anyhow_span;\nuse crate::bail;\nuse crate::bail_expr;\nuse crate::bail_sp"
  },
  {
    "path": "parser/src/cfg/deflocalkeys.rs",
    "chars": 3444,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail_expr;\n\n#[cfg(all(\n    not(feature = \"interception_driver\"),\n    a"
  },
  {
    "path": "parser/src/cfg/defsrc.rs",
    "chars": 3752,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail_expr;\n\n/// Parse mapped keys from an expression starting with def"
  },
  {
    "path": "parser/src/cfg/deftemplate.rs",
    "chars": 21166,
    "preview": "//! This file is responsible for template expansion.\n//! For simplicity of implementation, there is performance left off"
  },
  {
    "path": "parser/src/cfg/error.rs",
    "chars": 2433,
    "preview": "// # Regarding #[allow(unused_assignments)]\n//\n// Seems the miette macros no longer trigger the compiler to find usage.\n"
  },
  {
    "path": "parser/src/cfg/fake_key.rs",
    "chars": 13275,
    "preview": "use super::*;\n\nuse crate::{anyhow_expr, bail, bail_expr};\n\n#[allow(unused_variables)]\nfn set_virtual_key_reference_lsp_h"
  },
  {
    "path": "parser/src/cfg/fork.rs",
    "chars": 768,
    "preview": "use super::*;\n\nuse crate::bail;\n\npub(crate) fn parse_fork(ac_params: &[SExpr], s: &ParserState) -> Result<&'static Kanat"
  },
  {
    "path": "parser/src/cfg/is_a_button.rs",
    "chars": 3433,
    "preview": "pub(crate) fn is_a_button(osc: u16) -> bool {\n    if cfg!(target_os = \"windows\") {\n        matches!(osc, 1..=6 | 256..)\n"
  },
  {
    "path": "parser/src/cfg/key_outputs.rs",
    "chars": 5729,
    "preview": "use super::*;\n\n// Note: this uses a Vec inside the HashMap instead of a HashSet because ordering matters, e.g. for\n// ch"
  },
  {
    "path": "parser/src/cfg/key_override.rs",
    "chars": 9599,
    "preview": "//! Contains code to handle global override keys.\n\nuse anyhow::{Result, anyhow, bail};\nuse rustc_hash::FxHashMap as Hash"
  },
  {
    "path": "parser/src/cfg/layer_opts.rs",
    "chars": 2104,
    "preview": "use crate::cfg::*;\nuse crate::*;\n\npub(crate) const DEFLAYER_ICON: [&str; 3] = [\"icon\", \"🖻\", \"🖼\"];\npub(crate) type LayerI"
  },
  {
    "path": "parser/src/cfg/list_actions.rs",
    "chars": 10909,
    "preview": "//! Contains all list action names and a function to check that an action name is that of a list\n//! action.\n\n// Note: c"
  },
  {
    "path": "parser/src/cfg/live_reload.rs",
    "chars": 1473,
    "preview": "use super::*;\n\nuse crate::bail;\nuse crate::bail_expr;\n\npub(crate) fn parse_live_reload_num(\n    ac_params: &[SExpr],\n   "
  },
  {
    "path": "parser/src/cfg/macro.rs",
    "chars": 10972,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail;\nuse crate::bail_expr;\n\nconst MACRO_ERR: &str = \"Action macro onl"
  },
  {
    "path": "parser/src/cfg/mod.rs",
    "chars": 64397,
    "preview": "//! This parses the configuration language to create a `kanata_keyberon::layout::Layout` as well as\n//! associated metad"
  },
  {
    "path": "parser/src/cfg/mouse.rs",
    "chars": 4911,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail;\n\npub(crate) fn parse_distance(expr: &SExpr, s: &ParserState, lab"
  },
  {
    "path": "parser/src/cfg/multi.rs",
    "chars": 1922,
    "preview": "use super::*;\n\nuse crate::bail;\n\npub(crate) fn parse_multi(ac_params: &[SExpr], s: &ParserState) -> Result<&'static Kana"
  },
  {
    "path": "parser/src/cfg/oneshot.rs",
    "chars": 1184,
    "preview": "use super::*;\n\nuse crate::bail;\n\npub(crate) fn parse_one_shot(\n    ac_params: &[SExpr],\n    s: &ParserState,\n    end_con"
  },
  {
    "path": "parser/src/cfg/override.rs",
    "chars": 5319,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail_expr;\n\npub(crate) fn parse_overrides(exprs: &[SExpr], s: &ParserS"
  },
  {
    "path": "parser/src/cfg/permutations.rs",
    "chars": 1322,
    "preview": "//! Implements Heap's algorithm.\n\n/*\nFrom Wikipedia:\n\nprocedure generate(k: integer, A : array of any):\n    if k = 1 the"
  },
  {
    "path": "parser/src/cfg/platform.rs",
    "chars": 7004,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail_expr;\nuse crate::bail_span;\nuse crate::err_expr;\n\npub(crate) fn f"
  },
  {
    "path": "parser/src/cfg/push_msg.rs",
    "chars": 1138,
    "preview": "use super::*;\n\nuse crate::bail;\n\npub(crate) fn parse_push_message(\n    ac_params: &[SExpr],\n    s: &ParserState,\n) -> Re"
  },
  {
    "path": "parser/src/cfg/releases.rs",
    "chars": 873,
    "preview": "use super::*;\n\nuse crate::bail;\nuse crate::err_expr;\n\npub(crate) fn parse_release_key(\n    ac_params: &[SExpr],\n    s: &"
  },
  {
    "path": "parser/src/cfg/sequence.rs",
    "chars": 11356,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail;\nuse crate::bail_expr;\n\nconst SEQ_ERR: &str = \"defseq expects pai"
  },
  {
    "path": "parser/src/cfg/sexpr.rs",
    "chars": 18408,
    "preview": "use std::ops::Index;\nuse std::rc::Rc;\nuse std::str::Bytes;\nuse std::{fmt::Debug, iter};\n\ntype HashMap<K, V> = rustc_hash"
  },
  {
    "path": "parser/src/cfg/str_ext.rs",
    "chars": 787,
    "preview": "pub trait TrimAtomQuotes {\n    fn trim_atom_quotes(&self) -> &str;\n}\n\nimpl TrimAtomQuotes for str {\n    fn trim_atom_quo"
  },
  {
    "path": "parser/src/cfg/switch.rs",
    "chars": 11689,
    "preview": "use super::*;\nuse crate::{anyhow_expr, bail, bail_expr};\n\npub fn parse_switch(ac_params: &[SExpr], s: &ParserState) -> R"
  },
  {
    "path": "parser/src/cfg/tap_dance.rs",
    "chars": 994,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail;\n\npub(crate) fn parse_tap_dance(\n    ac_params: &[SExpr],\n    s: "
  },
  {
    "path": "parser/src/cfg/tap_hold.rs",
    "chars": 11639,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail;\nuse crate::bail_expr;\n\n/// Options that can be specified as trai"
  },
  {
    "path": "parser/src/cfg/tests/ambiguous.rs",
    "chars": 707,
    "preview": "use super::*;\n\n#[test]\nfn parse_double_dollar_var() {\n    let source = r#\"\n(defsrc)\n(deflayer base)\n(defvar $$num 100\n  "
  },
  {
    "path": "parser/src/cfg/tests/defcfg.rs",
    "chars": 8547,
    "preview": "use super::*;\n\n#[test]\nfn disallow_same_key_in_defsrc_unmapped_except() {\n    let source = \"\n(defcfg process-unmapped-ke"
  },
  {
    "path": "parser/src/cfg/tests/defhands.rs",
    "chars": 3585,
    "preview": "use super::*;\n\n#[test]\nfn opposite_hand_no_args() {\n    let source = \"\n(defhands (left a s d f) (right j k l ;))\n(defsrc"
  },
  {
    "path": "parser/src/cfg/tests/device_detect.rs",
    "chars": 2220,
    "preview": "#[cfg(any(target_os = \"linux\", target_os = \"android\"))]\nmod linux {\n    use super::super::*;\n\n    #[test]\n    fn linux_d"
  },
  {
    "path": "parser/src/cfg/tests/environment.rs",
    "chars": 1079,
    "preview": "use super::*;\n\nfn parse_cfg_env(cfg: &str, env_vars: Vec<(String, String)>) -> Result<IntermediateCfg> {\n    let _lk = l"
  },
  {
    "path": "parser/src/cfg/tests/macros.rs",
    "chars": 800,
    "preview": "use super::*;\n\n#[test]\nfn unsupported_action_in_macro_triggers_error() {\n    let source = r#\"\n(defsrc)\n(deflayer base)\n("
  },
  {
    "path": "parser/src/cfg/tests.rs",
    "chars": 56247,
    "preview": "use super::*;\n#[allow(unused_imports)]\nuse crate::cfg::sexpr::{Span, parse};\nuse kanata_keyberon::action::BooleanOperato"
  },
  {
    "path": "parser/src/cfg/unicode.rs",
    "chars": 1588,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail;\nuse crate::bail_expr;\n\npub(crate) fn parse_unicode(ac_params: &["
  },
  {
    "path": "parser/src/cfg/unmod.rs",
    "chars": 3412,
    "preview": "use super::*;\n\nuse crate::anyhow_expr;\nuse crate::bail;\nuse crate::bail_expr;\n\npub(crate) fn parse_unmod(\n    unmod_type"
  },
  {
    "path": "parser/src/cfg/vars.rs",
    "chars": 2317,
    "preview": "use super::*;\n\nuse crate::bail_expr;\n\npub(crate) fn parse_vars(\n    exprs: &[&Vec<SExpr>],\n    _lsp_hints: &mut LspHints"
  },
  {
    "path": "parser/src/cfg/zippychord.rs",
    "chars": 33831,
    "preview": "//! Zipchord-like parsing. Probably not 100% compatible.\n//!\n//! Example lines in input file.\n//! The \" => \" string repr"
  },
  {
    "path": "parser/src/custom_action.rs",
    "chars": 9681,
    "preview": "//! This module contains the \"Custom\" actions that are used with the keyberon layout.\n//!\n//! When adding a new custom a"
  },
  {
    "path": "parser/src/keys/linux.rs",
    "chars": 34338,
    "preview": "// This file is taken from the original ktrl project's keys.rs file with modifications.\n\nuse super::OsCode;\n\nimpl OsCode"
  },
  {
    "path": "parser/src/keys/macos.rs",
    "chars": 74317,
    "preview": "use super::OsCode;\n\n// because the parser can't handle oscode u16 values > 767\n// and macos has fucked up key coding (pa"
  },
  {
    "path": "parser/src/keys/mappings.rs",
    "chars": 15837,
    "preview": "use super::KeyCode;\nuse super::OsCode;\n\nimpl From<KeyCode> for OsCode {\n    fn from(item: KeyCode) -> Self {\n        uns"
  },
  {
    "path": "parser/src/keys/mod.rs",
    "chars": 36910,
    "preview": "//! Platform specific code for OS key code mappings.\n\nuse kanata_keyberon::key_code::*;\nuse once_cell::sync::Lazy;\nuse p"
  },
  {
    "path": "parser/src/keys/windows.rs",
    "chars": 48508,
    "preview": "// This file is adapted from the original ktrl's `keys.rs` file for Windows.\n\nuse super::OsCode;\n\n#[allow(unused)]\nmod k"
  },
  {
    "path": "parser/src/layers.rs",
    "chars": 1970,
    "preview": "use kanata_keyberon::key_code::KeyCode;\nuse kanata_keyberon::layout::*;\n\nuse crate::cfg::KanataAction;\nuse crate::cfg::a"
  },
  {
    "path": "parser/src/lib.rs",
    "chars": 242,
    "preview": "//! A parser for configuration language of [kanata](https://github.com/jtroo/kanata), a keyboard remapper.\n\npub mod cfg;"
  },
  {
    "path": "parser/src/lsp_hints.rs",
    "chars": 2419,
    "preview": "use crate::cfg::sexpr::SExpr;\n\npub use inner::*;\n\n#[cfg(not(feature = \"lsp\"))]\nmod inner {\n    #[derive(Debug, Default)]"
  },
  {
    "path": "parser/src/sequences.rs",
    "chars": 883,
    "preview": "use kanata_keyberon::key_code::KeyCode;\n\npub const MASK_KEYCODES: u16 = 0x03FF;\npub const MASK_MODDED: u16 = 0xFC00;\npub"
  },
  {
    "path": "parser/src/subset.rs",
    "chars": 6212,
    "preview": "//! Collection where keys are slices of a type, and supports a get operation to check if the key\n//! exists, is a subset"
  },
  {
    "path": "parser/src/trie.rs",
    "chars": 1996,
    "preview": "//! Wrapper around a trie type for (hopefully) easier swapping of libraries if desired.\n\nuse bytemuck::cast_slice;\nuse p"
  },
  {
    "path": "parser/test_cfgs/all_keys_in_defsrc.kbd",
    "chars": 1504,
    "preview": "(defcfg)\n\n(defsrc\n  grv\n  1\n  2\n  3\n  4\n  5\n  6\n  7\n  8\n  9\n  0\n  min\n  eql\n  bspc\n  tab\n  q\n  w\n  e\n  r\n  t\n  y\n  u\n  i"
  },
  {
    "path": "parser/test_cfgs/ancestor_seq.kbd",
    "chars": 104,
    "preview": "(defcfg)\n\n(defsrc a b c)\n\n(deflayer base _ _ _)\n\n(deffakekeys a a)\n\n(defseq a (a b c))\n(defseq a (a b))\n"
  },
  {
    "path": "parser/test_cfgs/bad_multi.kbd",
    "chars": 85,
    "preview": "(defcfg)\n(defsrc 1)\n(deflayer base (multi (tap-hold 1 1 a b) (tap-dance 1 (a b c))))\n"
  },
  {
    "path": "parser/test_cfgs/descendant_seq.kbd",
    "chars": 104,
    "preview": "(defcfg)\n\n(defsrc a b c)\n\n(deflayer base _ _ _)\n\n(deffakekeys a a)\n\n(defseq a (a b))\n(defseq a (a b c))\n"
  },
  {
    "path": "parser/test_cfgs/icon_bad_dupe.kbd",
    "chars": 117,
    "preview": ";; This config file is invalid and should be rejected\n(defcfg)\n(defsrc 1)\n(deflayer\t(base\ticon base.png 🖻 n.ico\t) 1)\n"
  },
  {
    "path": "parser/test_cfgs/icon_good.kbd",
    "chars": 249,
    "preview": "(defcfg)\n(defsrc 1)\n(deflayer\t(base       \ticon base.png   \t) 1)\n(deflayer\t(1emoji     \t🖻 1symbols.png  \t) 1)\n(deflayer\t"
  },
  {
    "path": "parser/test_cfgs/include-bad.kbd",
    "chars": 38,
    "preview": "(defsrc a)\n(include included-bad.kbd)\n"
  },
  {
    "path": "parser/test_cfgs/include-bad2.kbd",
    "chars": 66,
    "preview": "(defsrc a)\n(include included-bad2.kbd)\n(defalias no-action-uh-oh)\n"
  },
  {
    "path": "parser/test_cfgs/include-good-optional-absent.kbd",
    "chars": 80,
    "preview": "(defsrc a)\n(include included-non-existing-file.kbd)\n(include included-good.kbd)\n"
  },
  {
    "path": "parser/test_cfgs/include-good.kbd",
    "chars": 39,
    "preview": "(defsrc a)\n(include included-good.kbd)\n"
  },
  {
    "path": "parser/test_cfgs/included-bad.kbd",
    "chars": 31,
    "preview": "(deflayer not-enough-elements)\n"
  },
  {
    "path": "parser/test_cfgs/included-bad2.kbd",
    "chars": 18,
    "preview": "(deflayer base a)\n"
  },
  {
    "path": "parser/test_cfgs/included-good.kbd",
    "chars": 18,
    "preview": "(deflayer base a)\n"
  },
  {
    "path": "parser/test_cfgs/macro-chord-dont-panic.kbd",
    "chars": 43,
    "preview": "(defsrc a)\n(deflayer test (macro @ch|bas))\n"
  },
  {
    "path": "parser/test_cfgs/multiline_comment.kbd",
    "chars": 557,
    "preview": "(defcfg)\n\n#|\n\nTop level multi-line comment\nHello world\n\n|#\n\n(defsrc #||# a #| |# b #|  |# c #|   |#)\n\n(deflayer\nbase _\n\n"
  },
  {
    "path": "parser/test_cfgs/nested_tap_hold.kbd",
    "chars": 223,
    "preview": "(defcfg\n  linux-dev /dev/input/by-path/platform-i8042-serio-0-event-kbd\n)\n\n(defsrc\n       a\n)\n\n;; Note: this config file"
  },
  {
    "path": "parser/test_cfgs/test.zch",
    "chars": 65,
    "preview": "dy\tday\ndy 1\tMonday\n abc\tAlphabet\nr df\trecipient\n w  a\tWashington\n"
  },
  {
    "path": "parser/test_cfgs/testzch.kbd",
    "chars": 45,
    "preview": "(defsrc)\n(deflayer base)\n(defzippy test.zch)\n"
  },
  {
    "path": "parser/test_cfgs/unknown_defcfg_opt.kbd",
    "chars": 60,
    "preview": "(defcfg\n  this-should-error yes\n)\n\n(defsrc)\n(deflayer base)\n"
  },
  {
    "path": "parser/test_cfgs/utf8bom-included.kbd",
    "chars": 187,
    "preview": "#|\n\nBOM should have been added via:\n\n  $f = Get-Content .\\utf8bom-included.kbd\n  $f | Out-File -Encoding UTF8 .\\utf8bom"
  },
  {
    "path": "parser/test_cfgs/utf8bom.kbd",
    "chars": 206,
    "preview": "#|\n\nBOM should have been added via:\n\n  $f = Get-Content .\\utf8bom.kbd\n  $f | Out-File -Encoding UTF8 .\\utf8bom.kbd\n\n|#\n"
  },
  {
    "path": "rustfmt.toml",
    "chars": 40,
    "preview": "edition = \"2024\"\nstyle_edition = \"2024\"\n"
  },
  {
    "path": "scripts/test_linux_list_devices.sh",
    "chars": 4458,
    "preview": "#!/bin/bash\n\n# Linux Testing Script for kanata --list functionality\n# Run this on your Ubuntu machine after cloning the "
  },
  {
    "path": "simulated_input/.gitignore",
    "chars": 12,
    "preview": "Cargo.lock\r\n"
  },
  {
    "path": "simulated_input/Cargo.toml",
    "chars": 926,
    "preview": "[package]\nname = \"kanata-sim\"\nversion = \"0.1.0\"\nauthors = [\"jtroo <j.andreitabs@gmail.com>\"]\ndescription = \"Simulated in"
  },
  {
    "path": "simulated_input/README.md",
    "chars": 371,
    "preview": "# Kanata simulated input\n\nA CLI tool that lets you run simulated kanata input.\n\nUse the `-c` flag to specify a kanata co"
  },
  {
    "path": "simulated_input/src/sim.rs",
    "chars": 15829,
    "preview": "use anyhow::Result;\nuse anyhow::{anyhow, bail};\nuse clap::Parser;\nuse kanata_state_machine::kanata::handle_fakekey_actio"
  },
  {
    "path": "simulated_passthru/.gitignore",
    "chars": 12,
    "preview": "Cargo.lock\r\n"
  },
  {
    "path": "simulated_passthru/Cargo.toml",
    "chars": 1017,
    "preview": "[package]\nname   \t= \"simulated_passthru\"\nversion\t= \"0.0.1\"\nedition\t= \"2021\"\n\n[lib]\nname      \t= \"kanata_passthru\"\npath  "
  },
  {
    "path": "simulated_passthru/ReadMe.md",
    "chars": 373,
    "preview": "# Kanata passthru (simulated input and output)\n\nA Windows dynamic library (DLL) that lets you run simulated kanata input"
  },
  {
    "path": "simulated_passthru/src/key_in.rs",
    "chars": 1684,
    "preview": "use kanata_state_machine::oskbd::*;\nuse log::*;\n\nuse winapi::ctypes::*;\nuse winapi::shared::minwindef::*;\n\nuse crate::os"
  },
  {
    "path": "simulated_passthru/src/key_out.rs",
    "chars": 4161,
    "preview": "use anyhow::Result;\n\nuse kanata_state_machine::oskbd::*;\nuse log::*;\n\nuse winapi::ctypes::*;\nuse winapi::shared::minwind"
  },
  {
    "path": "simulated_passthru/src/lib_passthru.rs",
    "chars": 4660,
    "preview": "#![cfg(all(feature = \"passthru_ahk\", target_os = \"windows\"))]\nuse anyhow::Result;\nuse anyhow::bail;\n\nuse kanata_state_ma"
  },
  {
    "path": "simulated_passthru/src/log_win.rs",
    "chars": 3565,
    "preview": "//! A logger that prints to OutputDebugString (Windows only)\nuse log::{Level, Metadata, Record};\n\n/// Implements `log::L"
  },
  {
    "path": "src/gui/mod.rs",
    "chars": 766,
    "preview": "pub mod win;\npub use win::*;\npub mod win_dbg_logger;\npub mod win_nwg_ext;\npub use win_dbg_logger as log_win;\npub use win"
  },
  {
    "path": "src/gui/win.rs",
    "chars": 71707,
    "preview": "use crate::Kanata;\nuse anyhow::{Result, bail};\nuse core::cell::RefCell;\nuse kanata_parser::cfg::CfgOptionsGui;\nuse log::"
  },
  {
    "path": "src/gui/win_dbg_logger/mod.rs",
    "chars": 10559,
    "preview": "#![allow(non_upper_case_globals)]\n//! A logger for use with Windows debuggers.\n//!\n//! This crate integrates with the ub"
  },
  {
    "path": "src/gui/win_dbg_logger/win_dbg_logger.toml",
    "chars": 582,
    "preview": "[package]\nname = \"win_dbg_logger\"\nversion = \"0.1.0\"\nauthors = [\"Arlie Davis <ardavis@microsoft.com>\"]\nedition = \"2018\"\nl"
  },
  {
    "path": "src/gui/win_nwg_ext/license-MIT",
    "chars": 1105,
    "preview": "The MIT License (MIT)\n=====================\n\nCopyright © `2024` `Niccolò Betto`\n\nPermission is hereby granted, free of c"
  },
  {
    "path": "src/gui/win_nwg_ext/license-nwg-MIT",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2019 Gabriel Dube\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "src/gui/win_nwg_ext/mod.rs",
    "chars": 7856,
    "preview": "// based on https://github.com/lynxnb/wsl-usb-manager/blob/master/src/gui/nwg_ext.rs\nuse native_windows_gui as nwg;\nuse "
  },
  {
    "path": "src/kanata/caps_word.rs",
    "chars": 2381,
    "preview": "use kanata_keyberon::key_code::KeyCode;\nuse rustc_hash::FxHashSet as HashSet;\n\nuse kanata_parser::custom_action::CapsWor"
  },
  {
    "path": "src/kanata/cfg_forced.rs",
    "chars": 696,
    "preview": "//! Options in the configuration file that are overidden/forced to some value other than what's in\n//! the configuration"
  },
  {
    "path": "src/kanata/clipboard.rs",
    "chars": 10626,
    "preview": "use super::*;\n\n#[cfg(not(any(target_arch = \"wasm32\", target_os = \"android\")))]\npub use real::*;\n#[cfg(not(any(target_arc"
  },
  {
    "path": "src/kanata/cmd.rs",
    "chars": 7539,
    "preview": "#![cfg_attr(feature = \"simulated_output\", allow(dead_code, unused_imports))]\n\nuse std::fmt::Write;\n\nuse kanata_parser::c"
  }
]

// ... and 72 more files (download for full content)

About this extraction

This page contains the full source code of the jtroo/kanata GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 272 files (2.3 MB), approximately 609.2k tokens, and a symbol index with 2523 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!