Metadata-Version: 2.4
Name: charz-input
Version: 0.1.5
Summary: Versatile input interfaces, for keyboard and console
Keywords: input,keyboard,console,interface,terminal,pygame
Author: Havsalt
Author-email: Havsalt <77575424+Havsalt@users.noreply.github.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: User Interfaces
Classifier: Typing :: Typed
Requires-Dist: keyboard~=0.13.5
Requires-Dist: linflex~=0.3.3
Requires-Dist: pygame~=2.6
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/havsalt/charz-input
Project-URL: Repository, https://github.com/havsalt/charz-input
Project-URL: Documentation, https://havsalt.github.io/charz-input
Project-URL: Issues, https://github.com/havsalt/charz-input/issues
Project-URL: Changelog, https://github.com/havsalt/charz-input/blob/main/CHANGELOG.md
Description-Content-Type: text/markdown

# Charz Input

Versatile input interfaces, for keyboard and console.

## Examples

Defining an **Action Enum**, with _all_ possible actions as variants:

```python
from enum import Enum, auto


class Action(Enum):
    SWITCH_INPUT = auto()
    MOVE_LEFT = auto()
    MOVE_RIGHT = auto()
```

Switching between `Keyboard` and `Controller` input methods:

```python
# ... defined `Action` enum ...

from charz_input import Input, Keyboard, Controller
import pygame

handler: Input[Action] = Keyboard({
    Action.SWITCH_INPUT: "Space",
    Action.MOVE_LEFT: "A",
    Action.MOVE_RIGHT: "D",
})
player_position_x: int = 0

while True:
    handler.capture_states()

    if handler.is_action_just_pressed(Action.SWITCH_INPUT):
        if isinstance(handler, Keyboard):
            handler = Controller({
                Action.SWITCH_INPUT: pygame.CONTROLLER_BUTTON_A,
                Action.MOVE_LEFT: Controller.Trigger(
                    pygame.CONTROLLER_AXIS_LEFTX,
                    Controller.Trigger.Limit.NEGATIVE,
                ),
                Action.MOVE_RIGHT: Controller.Trigger(
                    pygame.CONTROLLER_AXIS_LEFTX,
                    Controller.Trigger.Limit.POSITIVE,
                    deadzone=35,
                ),
            })
        elif isinstance(handler, Controller):
            handler = Keyboard({
                Action.SWITCH_INPUT: "Space",
                Action.MOVE_LEFT: "A",
                Action.MOVE_RIGHT: "D",
            })
        continue

    if handler.is_action_pressed(Action.MOVE_LEFT):
        player_position_x -= 1
    if handler.is_action_pressed(Action.MOVE_RIGHT):
        player_position_x += 1

    print(f"The player is located at x = {player_position_x}")
```

Declearing default keybinds:

```python
import charz_input

# ... defined `Action` enum ...


class CustomKeyboard(charz_input.Keyboard):
    default_action_binds = {
        Action.SWITCH_INPUT: "Space",
        Action.MOVE_LEFT: "A",
        Action.MOVE_RIGHT: "D",
    }


handler = CustomKeyboard[Action]()
different_handler = CustomKeyboard({
    Action.MOVE_RIGHT: "Y",  # Overrides keybind
    # NOTE: The rest are set to their defaults,
    # as defined by `default_action_binds`
})

# ... logic to check for action presses ...
```

You can ensure all actions are mapped at **runtime**, using a **typed class item** when instantiating:

```python
                # ┌──────┬─────> Action enum, as class item
handler = Keyboard[Action]({
    Action.SWITCH_INPUT: "Space",
    Action.MOVE_LEFT: "A",
    # Missing `Action.MOVE_RIGHT`
})
handler.capture_states()  # This triggers the check
>> AssertionError: Missing actions

# Annotating the variable, and not the instance, will have different results:
handler: Keyboard[Action] = Keyboard({...})
```

Checking for keyboard presses with a modifier:

```python
handler = Keyboard[Action](
    # ... keybinds ...
    Action.MOVE_LEFT: "W+{modifier}",  # Dynamic, in the sense of initializing
    Action.MOVE_RIGHT: "W",
    Action.SWITCH_INPUT: "Ctrl+Space"  # Can also be hardcoded
    modifier="Space",  # Default: "Shift"
)

handler.capture_states()
print(handler.is_pressed())
handler.action_binds
handler.capture_states()
print(handler.is_pressed())
```

## Roadmap

- [ ] Expose action binds at runtime, so they can be changed
- [ ] Figure out whether automatic device detection for controller is ideal

## License

MIT
