input-remapper/readme/macros.md

260 lines
5.4 KiB
Markdown
Raw Normal View History

2021-04-25 17:28:02 +00:00
# Macros
key-mapper comes with an optional custom macro language with support for cross-device
variables, conditions and named parameters.
Syntax errors are shown in the UI on save. Each `k` function adds a short delay of 10ms
between key-down, key-up and at the end. See [usage.md](usage.md#configuration-files)
for more info.
2021-04-25 17:28:48 +00:00
Bear in mind that anti-cheat software might detect macros in games.
### key
> Acts like a pressed key. All names that are available in regular mappings can be used
> here.
>
> You don't have to use quotes around the symbol constants.
>
> Shorthand: `k`
>
> ```c#
> key(symbol: str)
> ```
>
> Examples:
>
> ```c#
> key(symbol=KEY_A)
> key(b).key(space)
> ```
### wait
> Waits in milliseconds before continuing the macro
>
> Shorthand: `w`
>
> ```c#
> wait(time: int)
> ```
>
> Examples:
>
> ```c#
> wait(time=100)
> wait(500)
> ```
### repeat
> Repeats the execution of the second parameter a few times
>
> Shorthand: `r`
>
> ```c#
> repeat(repeats: int, macro: Macro)
> ```
>
> Examples:
>
> ```c#
> repeat(1, key(KEY_A))
> repeat(repeats=2, key(space))
> ```
### modify
> Holds a modifier while executing the second parameter
>
> Shorthand: `m`
>
> ```c#
> modify(modifier: str, macro: Macro)
> ```
>
> Examples:
>
> ```c#
> modify(Control_L, k(a).k(x))
> ```
### hold
> Executes the child macro repeatedly as long as the key is pressed down.
>
> If a symbol string like KEY_A is provided, it will hold down that symbol as
> long as the key is pressed down.
>
> Shorthand: `h`
>
> ```c#
> hold(macro: Macro | str)
> ```
>
> Examples:
>
> ```c#
> hold(KEY_A)
> hold(key(space))
> ```
### mouse
> Moves the mouse cursor
>
> ```c#
> mouse(direction: str, speed: int)
> ```
>
> Examples:
>
> ```c#
> mouse(up, 1)
> mouse(left, 2)
> ```
2021-04-25 17:28:02 +00:00
### wheel
> Injects scroll wheel events
>
> ```c#
> wheel(direction: str, speed: int)
> ```
>
> Examples:
>
> ```c#
> mouse(up, 1)
> mouse(left, 2)
> ```
### event
> Writes an event. type, code and value of existing keys be found via the `sudo evtest`
> command
>
> Shorthand: `e`
>
> ```c#
> event(type: str | int, code: str | int, value: int)
> ```
>
> Examples:
>
> ```c#
> event(EV_KEY, KEY_A, 1)
> event(2, 8, 1)
> ```
### set
> Set a variable to a value. This variable and its value is available in all injection
> processes.
>
> Variables can be used in function arguments by adding a `$` in front of their name:
> `repeat($foo, key(KEY_A))`
>
> ```c#
> set(variable: str, value: str | int)
> ```
>
> Examples:
>
> ```c#
> set(foo, 1)
> set(foo, "qux")
> ```
### if_eq
> Compare two values and run different macros depending on the outcome
>
> ```c#
> if_eq(value_1: str | int, value_2: str | int, then: Macro | None, else: Macro | None)
> ```
>
> Examples:
>
> ```c#
> set(a, 1).if_eq($a, 1, key(KEY_A), key(KEY_B))
> set(a, 1).set(b, 1).if_eq($a, $b, else=key(KEY_B).key(KEY_C))
> set(a, "foo").if_eq("foo", $a, key(KEY_A))
> ```
### if_tap
> If the key is tapped quickly, run the `then` macro, otherwise the
> second. The third param is the optional time in milliseconds and defaults to
> 300ms
>
> ```c#
> if_tap(then: Macro | None, else: Macro | None, timeout: int)
> ```
>
> Examples:
>
> ```c#
> if_tap(key(KEY_A), key(KEY_B), timeout=500)
> if_tap(then=key(KEY_A), else=key(KEY_B))
> ```
### if_single
> If the key that is mapped to the macro is pressed and released, run the `then` macro.
>
> If another key is pressed while the triggering key is held down, run the `else` macro.
>
> ```c#
> if_single(then: Macro | None, else: Macro | None)
> ```
>
> Examples:
>
> ```c#
> if_single(key(KEY_A), key(KEY_B))
> if_single(then=key(KEY_A), else=key(KEY_B))
> ```
## Syntax
2021-04-25 17:28:02 +00:00
Multiple functions are chained using `.`.
Unlike other programming languages, `qux(bar())` would not run `bar` and then
`qux`. Instead, `cux` can decide to run `bar` during runtime depending on various
other factors. Like `repeat` is running its parameter multiple times.
2021-04-25 17:28:02 +00:00
Whitespaces, newlines and tabs don't have any meaning and are removed when the macro
gets compiled.
2021-04-25 17:28:02 +00:00
Similar to python, arguments can be either positional or keyword arguments.
`key(symbol=KEY_A)` is the same as `key(KEY_A)`.
2021-04-25 17:28:02 +00:00
Using `$` resolves a variable during runtime. For example `set(a, $1)` and
`if_eq($a, 1, key(KEY_A), key(KEY_B))`.
2021-04-25 17:28:02 +00:00
## Combinations spanning multiple devices
2021-04-25 17:28:48 +00:00
For regular combinations on only single devices it is not required to
2021-07-25 08:36:00 +00:00
configure macros. See [readme/usage.md](usage.md#combinations).
2021-04-25 17:28:02 +00:00
**Keyboard** `space` `set(foo, 1).h(space).set(foo, 0)`
2021-04-25 17:28:02 +00:00
**Mouse** `middle` `if_eq($foo, 1, h(a), h(BTN_MIDDLE))`
2021-04-25 17:28:02 +00:00
2021-04-25 17:28:48 +00:00
Apply both presets. If you press space on your keyboard, it will write a
space exactly like it used to. If you hold down space and press the middle
button of your mouse, it will write "a" instead. If you just press the
middle button of your mouse it behaves like a regular middle mouse button.
2021-04-25 17:28:02 +00:00
2021-04-25 17:28:48 +00:00
**Explanation**
2021-04-25 17:28:02 +00:00
2021-04-25 17:28:48 +00:00
`h(space)` makes your key work exactly like if it was mapped to "space".
It will inject a key-down event if you press it, does nothing as long you
hold your key down, and injects a key-up event after releasing.
2021-04-25 17:28:02 +00:00
`set(foo, 1).set(foo, 0)` sets "foo" to 1 and then sets "foo" to 0.
`set` and `if_eq` work on shared memory, so all injections will see your
2021-04-25 17:28:48 +00:00
variables. Combine both to get a key that works like a normal key, but that also
works as a modifier for other keys of other devices. `ifeq($foo, 1, ..., ...)`
runs the first param if foo is 1, or the second one if foo is not 1.