bevy_keyboard_shortcuts 0.1.2

Keyboard shortcut system for Bevy applications
Documentation
# bevy_keyboard_shortcuts

A Bevy plugin for handling keyboard shortcuts with modifier support.

This crate provides a flexible way to define and check keyboard shortcuts in Bevy applications,
with support for modifier keys (Ctrl, Alt, Shift, Super) and both single-press and repeating inputs.

## Features

- Define keyboard shortcuts with optional modifiers
- Support for repeating shortcuts (held keys) and single-press shortcuts
- Serialization/deserialization support via serde for easy configuration
- Pretty-printing of shortcuts for UI display

## Example

```rust
use bevy::prelude::*;
use bevy_keyboard_shortcuts::Shortcuts;

fn check_shortcuts(keyboard: Res<ButtonInput<KeyCode>>) {
    let jump = Shortcuts::single_press(&[KeyCode::Space]);
    let save = Shortcuts::single_press(&[KeyCode::KeyS]).with_ctrl();

    if jump.pressed(&keyboard) {
        println!("Jump!");
    }
    if save.pressed(&keyboard) {
        println!("Saving!");
    }
}
```

## Usage Pattern

A typical usage pattern involves creating a Bevy Resource with your shortcuts:

```rust
use bevy::prelude::*;
use bevy_keyboard_shortcuts::Shortcuts;
use serde::{Deserialize, Serialize};

#[derive(Resource)]
pub struct ShortcutSettings {
    pub move_left: Shortcuts,
    pub move_right: Shortcuts,
    pub quick_save: Shortcuts,
}

impl Default for ShortcutSettings {
    fn default() -> Self {
        Self {
            move_left: Shortcuts::repeating(&[KeyCode::KeyA, KeyCode::ArrowLeft]),
            move_right: Shortcuts::repeating(&[KeyCode::KeyD, KeyCode::ArrowRight]),
            quick_save: Shortcuts::single_press(&[KeyCode::KeyS]).with_ctrl(),
        }
    }
}

fn handle_input(
    keyboard: Res<ButtonInput<KeyCode>>,
    shortcuts: Res<ShortcutSettings>,
) {
    if shortcuts.move_left.pressed(&keyboard) {
        // Move left
    }
    if shortcuts.move_right.pressed(&keyboard) {
        // Move right
    }
    if shortcuts.quick_save.pressed(&keyboard) {
        // Save game
    }
}
```

## YAML Configuration

This crate works well with configuration files. Here's an example YAML configuration:

```yaml
# Camera controls - repeating shortcuts (continuous input)
move_left:
  repeats: true
  shortcuts:
    - key: "KeyA"
    - key: "ArrowLeft"

move_right:
  repeats: true
  shortcuts:
    - key: "KeyD"
    - key: "ArrowRight"

# Example with modifiers
save:
  repeats: false
  shortcuts:
    - key: "KeyS"
      modifiers:
        control: RequirePressed
```

## Key Names Reference

Key names in YAML/JSON configuration match Bevy's `KeyCode` enum variants exactly. Remove the `KeyCode::` prefix:

- Letters: `KeyA`, `KeyB`, ..., `KeyZ`
- Numbers: `Digit0`, `Digit1`, ..., `Digit9`
- Function keys: `F1`, `F2`, ..., `F12`
- Arrows: `ArrowUp`, `ArrowDown`, `ArrowLeft`, `ArrowRight`
- Special keys: `Space`, `Enter`, `Escape`, `Tab`, `Backspace`, `Delete`
- Numpad: `Numpad0`, `Numpad1`, ..., `Numpad9`, `NumpadAdd`, `NumpadSubtract`

For example: `KeyCode::KeyA` becomes `"KeyA"`, `KeyCode::Space` becomes `"Space"`.

For the complete list, see [Bevy's KeyCode documentation](https://docs.rs/bevy/latest/bevy/input/keyboard/enum.KeyCode.html).

## Modifier Behavior

By default, **all modifiers are ignored** - shortcuts trigger regardless of modifier state.

Each modifier key (Ctrl, Alt, Shift, Super) can be configured:

- **Ignore** (DEFAULT) - Don't check this modifier (works with or without)
  - This is the default if no modifier methods are called
  - The shortcut triggers regardless of the modifier's state
- **RequirePressed** - The modifier MUST be pressed
  - Use `.with_ctrl()`, `.with_alt()`, `.with_shift()`, `.with_super()`
  - In YAML: `control: RequirePressed`, `alt: RequirePressed`, etc.
- **RequireNotPressed** - The modifier must NOT be pressed
  - Use `.without_ctrl()`, `.without_alt()`, `.without_shift()`, `.without_super()`
  - In YAML: `control: RequireNotPressed`, `alt: RequireNotPressed`, etc.

### Examples

```rust
// Default - ignores all modifiers
let flexible = Shortcuts::single_press(&[KeyCode::KeyA]);

// Requires Ctrl
let save = Shortcuts::single_press(&[KeyCode::KeyS]).with_ctrl();

// Requires Ctrl AND Shift
let redo = Shortcuts::single_press(&[KeyCode::KeyZ]).with_ctrl().with_shift();

// Forbids Ctrl (S without Ctrl)
let action = Shortcuts::single_press(&[KeyCode::KeyS]).without_ctrl();
```