Name | keyweave JSON |
Version |
0.12.0
JSON |
| download |
home_page | https://github.com/GregRos/keyweave |
Summary | Framework for defining global hotkeys. |
upload_time | 2025-08-31 15:39:51 |
maintainer | None |
docs_url | None |
author | GregRos |
requires_python | <4.0,>=3.13 |
license | MIT |
keywords |
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# keyweave
Keyweave is a Python package for creating and managing global keyboard hotkeys.
- Designed to be easy to observe and debug.
- Hotkeys are grouped into a Layout, which can be activated as a context manager.
- Handlers are attached to Commands, which have labels and descriptions.
- Hotkeys are typically defined using decorators on functions or methods.
## Overview
Key-related objects:
- `Key`: Represents a single mouse, keyboard, or controller key.
- `KeyState`: Represents a `Key` together with a state: `up` or `down`.
- `Hotkey`: A trigger `KeyState` and an unordered set of `KeyState` modifiers.
Command-related objects:
- `CommandMeta`: Just the metadata of a command. Has a label and a description.
- `Command`: A metadata object together with a handler (a function).
These are combined using:
- `Binding`: A Hotkey and the Command it’s bound to.
- `Layout`: A collection of `Binding` objects that listens to input events and picks which `Binding` to activate for each event, if any.
- `LayoutClass`: An object-oriented way of defining a `Layout`.
### Key
An object that describes a mouse or keyboard key. You can access most keys using the `key` import:
```python
import key from keyweave
a = key.a
```
Other keys can be constructed using the `Key` class:
```ts
import Key from keyweave
a = Key("a")
```
### KeyState
This describes a `Key` and whether it’s up or down. At any given time, a `KeyState` is either True or False.
KeyStates are used to filter input events as well as global input state. You can construct a `KeyState` using the `Key.down` or `Key.up` properties:
```python
import key from keyweave
a_down = key.a.down
a_up = key.a.up
```
In some cases, you can pass a `Key` instead of a `KeyState`. In that case, `down` is assumed by default.
You can create an Up `KeyState` using the `~` operator on the key:
```python
import key from keyweave
a_up = ~key.a
```
### Hotkey
A `Hotkey` is a filter on input events consisting of two parts:
- A **Trigger** `KeyState` that’s used to hook the input event.
- A set of **Modifiers**: `KeyStates` which need to be True for the Hotkey to fire.
If a `Hotkey` is triggered by an input event, the event is normally swallowed. However, none of the modifiers are swallowed. If they have side-effects, those must be handled separately.
Note that modifiers don’t just refer to classic modifier keys like `Ctrl`. Any key can be a modifier, and the package doesn’t treat these keys differently from others.
You can construct a Hotkey using the `&` operator between:
1. A `Key` or `KeyState`.
2. An iterable of `Key` or `KeyState` objects which are used as modifiers.
```python
import key from keyweave
key.a.down & [key.b]
key.a & [key.b, key.c.up, key.shift.down]
```
In most cases, you can pass a `Key` or `KeyState` directly instead of a `Hotkey`. In that case, the key can be assumed to be `down` and the modifier list is assumed to be empty.
If you want to avoid swallowing the input event, you can modify the Hotkey using its `passthrough` method:
```python
import key from keyweave
key.a.down.hotkey().passthrough
```
### Command
A Command consists of:
- `CommandMeta`: A label, description, and an emoji. Metadata.
- A handler, which is a function that handles the command.
### Layout
A Layout is an object containing lots of `Hotkey` objects bound to `Command` objects.
Layouts are what actually listens to input events. When an input event is received, each Binding’s Hotkey is checked to see if it’s applicable.
If multiple `Binding` objects turn out to be applicable to one input event, **only one of them will be invoked.** The binding that’s invoked is determined by the highest _specificity_ - the total number of keys the Hotkey references.
If the specificity is the same, then the last defined hotkey is used.
So for example, let’s say we register the hotkeys `Ctrl + Shift + A` and `Ctrl + A` under the same `Layout`. Then if `Ctrl + Shift + A` is pressed, the event matches both hotkeys. But one has a specificity of 2 while the other one has 3.
Thus only the `Ctrl + Shift + A` binding is actually invoked.
However, if you have separate Layouts with these bindings, then multiple bindings can be invoked.
### Negative modifiers
A trigger for a hotkey can be either a key down or a key up event.
Modifiers can also contain key up or key down **states**. A key up modifier is a negative modifier – it means the key should not be held down.
Normally, if you define a hotkey for `Ctrl + A`, it would be invoked even if the user presses `Alt + Ctrl + A`. If you don’t want this behavior, you can add the negative/up modifier `Ctrl + A + ~Alt`.
A negative modifier also increase specificity, which can sometimes be desirable.
## Usage
Using this package means **defining Layout objects**. This can be done
## Object-oriented
The main objects used Keyweave are:
- Command: This is metadata involving a
Bindings are partially implemented using [keyboard](https://pypi.org/project/keyboard/) but due to technical issues involving mouse input and key state, it sometimes has to use the win32 API.
- Capturing mouse input
- Getting key states
Raw data
{
"_id": null,
"home_page": "https://github.com/GregRos/keyweave",
"name": "keyweave",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.13",
"maintainer_email": null,
"keywords": null,
"author": "GregRos",
"author_email": "gregros@gregros.dev",
"download_url": "https://files.pythonhosted.org/packages/8c/7a/ac8a5fe8916aef65016fbdcdd5967d751fec5a66c071c5ea4dc569ad54e0/keyweave-0.12.0.tar.gz",
"platform": null,
"description": "# keyweave\n\nKeyweave is a Python package for creating and managing global keyboard hotkeys.\n\n- Designed to be easy to observe and debug.\n- Hotkeys are grouped into a Layout, which can be activated as a context manager.\n- Handlers are attached to Commands, which have labels and descriptions.\n- Hotkeys are typically defined using decorators on functions or methods.\n\n## Overview\n\nKey-related objects:\n\n- `Key`: Represents a single mouse, keyboard, or controller key.\n- `KeyState`: Represents a `Key` together with a state: `up` or `down`.\n- `Hotkey`: A trigger `KeyState` and an unordered set of `KeyState` modifiers.\n\nCommand-related objects:\n\n- `CommandMeta`: Just the metadata of a command. Has a label and a description.\n- `Command`: A metadata object together with a handler (a function).\n\nThese are combined using:\n\n- `Binding`: A Hotkey and the Command it\u2019s bound to.\n- `Layout`: A collection of `Binding` objects that listens to input events and picks which `Binding` to activate for each event, if any.\n- `LayoutClass`: An object-oriented way of defining a `Layout`.\n\n### Key\n\nAn object that describes a mouse or keyboard key. You can access most keys using the `key` import:\n\n```python\nimport key from keyweave\na = key.a\n```\n\nOther keys can be constructed using the `Key` class:\n\n```ts\nimport Key from keyweave\na = Key(\"a\")\n```\n\n### KeyState\n\nThis describes a `Key` and whether it\u2019s up or down. At any given time, a `KeyState` is either True or False.\n\nKeyStates are used to filter input events as well as global input state. You can construct a `KeyState` using the `Key.down` or `Key.up` properties:\n\n```python\nimport key from keyweave\na_down = key.a.down\na_up = key.a.up\n```\n\nIn some cases, you can pass a `Key` instead of a `KeyState`. In that case, `down` is assumed by default.\n\nYou can create an Up `KeyState` using the `~` operator on the key:\n\n```python\nimport key from keyweave\na_up = ~key.a\n```\n\n### Hotkey\n\nA `Hotkey` is a filter on input events consisting of two parts:\n\n- A **Trigger** `KeyState` that\u2019s used to hook the input event.\n- A set of **Modifiers**: `KeyStates` which need to be True for the Hotkey to fire.\n\nIf a `Hotkey` is triggered by an input event, the event is normally swallowed. However, none of the modifiers are swallowed. If they have side-effects, those must be handled separately.\n\nNote that modifiers don\u2019t just refer to classic modifier keys like `Ctrl`. Any key can be a modifier, and the package doesn\u2019t treat these keys differently from others.\n\nYou can construct a Hotkey using the `&` operator between:\n\n1. A `Key` or `KeyState`.\n2. An iterable of `Key` or `KeyState` objects which are used as modifiers.\n\n```python\nimport key from keyweave\n\nkey.a.down & [key.b]\nkey.a & [key.b, key.c.up, key.shift.down]\n```\n\nIn most cases, you can pass a `Key` or `KeyState` directly instead of a `Hotkey`. In that case, the key can be assumed to be `down` and the modifier list is assumed to be empty.\n\nIf you want to avoid swallowing the input event, you can modify the Hotkey using its `passthrough` method:\n\n```python\nimport key from keyweave\nkey.a.down.hotkey().passthrough\n```\n\n### Command\n\nA Command consists of:\n\n- `CommandMeta`: A label, description, and an emoji. Metadata.\n- A handler, which is a function that handles the command.\n\n### Layout\n\nA Layout is an object containing lots of `Hotkey` objects bound to `Command` objects.\n\nLayouts are what actually listens to input events. When an input event is received, each Binding\u2019s Hotkey is checked to see if it\u2019s applicable.\n\nIf multiple `Binding` objects turn out to be applicable to one input event, **only one of them will be invoked.** The binding that\u2019s invoked is determined by the highest _specificity_ - the total number of keys the Hotkey references.\n\nIf the specificity is the same, then the last defined hotkey is used.\n\nSo for example, let\u2019s say we register the hotkeys `Ctrl + Shift + A` and `Ctrl + A` under the same `Layout`. Then if `Ctrl + Shift + A` is pressed, the event matches both hotkeys. But one has a specificity of 2 while the other one has 3.\n\nThus only the `Ctrl + Shift + A` binding is actually invoked.\n\nHowever, if you have separate Layouts with these bindings, then multiple bindings can be invoked.\n\n### Negative modifiers\n\nA trigger for a hotkey can be either a key down or a key up event.\n\nModifiers can also contain key up or key down **states**. A key up modifier is a negative modifier \u2013 it means the key should not be held down.\n\nNormally, if you define a hotkey for `Ctrl + A`, it would be invoked even if the user presses `Alt + Ctrl + A`. If you don\u2019t want this behavior, you can add the negative/up modifier `Ctrl + A + ~Alt`.\n\nA negative modifier also increase specificity, which can sometimes be desirable.\n\n## Usage\n\nUsing this package means **defining Layout objects**. This can be done\n\n## Object-oriented\n\nThe main objects used Keyweave are:\n\n- Command: This is metadata involving a\n\nBindings are partially implemented using [keyboard](https://pypi.org/project/keyboard/) but due to technical issues involving mouse input and key state, it sometimes has to use the win32 API.\n\n- Capturing mouse input\n- Getting key states\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Framework for defining global hotkeys.",
"version": "0.12.0",
"project_urls": {
"Homepage": "https://github.com/GregRos/keyweave"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "59da03ec347769c30497580f527004ec99e13e92e75ce635b5d501e129d9c41c",
"md5": "118a719b1b38687a4d1e49561602968e",
"sha256": "a2275e18fbe4659e9e40b91168f9d4c7ba6e65cb09c5ace80dc70b84e4f27c3b"
},
"downloads": -1,
"filename": "keyweave-0.12.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "118a719b1b38687a4d1e49561602968e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.13",
"size": 20878,
"upload_time": "2025-08-31T15:39:50",
"upload_time_iso_8601": "2025-08-31T15:39:50.113603Z",
"url": "https://files.pythonhosted.org/packages/59/da/03ec347769c30497580f527004ec99e13e92e75ce635b5d501e129d9c41c/keyweave-0.12.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8c7aac8a5fe8916aef65016fbdcdd5967d751fec5a66c071c5ea4dc569ad54e0",
"md5": "20deb9680bd994047e4a628d9b437a9e",
"sha256": "262b6100640c7c8dbd0d99b391503f3cdef2fa4ae327e1de687d5cb9f2ff131a"
},
"downloads": -1,
"filename": "keyweave-0.12.0.tar.gz",
"has_sig": false,
"md5_digest": "20deb9680bd994047e4a628d9b437a9e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.13",
"size": 13808,
"upload_time": "2025-08-31T15:39:51",
"upload_time_iso_8601": "2025-08-31T15:39:51.616191Z",
"url": "https://files.pythonhosted.org/packages/8c/7a/ac8a5fe8916aef65016fbdcdd5967d751fec5a66c071c5ea4dc569ad54e0/keyweave-0.12.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-31 15:39:51",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "GregRos",
"github_project": "keyweave",
"github_not_found": true,
"lcname": "keyweave"
}