What Is Simkey?
Simkey is a simple language to write repetitive macros (essentially, a sequence of doing things—like pressing keys and moving the mouse—that you can use to automate things such as movements in a video game).
While there are more powerful options, Simkey strives to make repetitive tasks that don't require active inputs or screen readers easy and efficient to automate.
You can press, hold, and release keys, as well as move the cursor and scroll, all while controlling the timing with concise and easy to understand code. This code gets run in an app that is beginner-friendly without an intimidating GUI.
Basic Syntax
Simkey aims to strike a balance between conciseness and capability. The most fundamental parts to understand are key expressions
and delays
. With these tools, you will easily be able to create useful macros.
Key Expressions
The fundamental idea is that, with some exceptions for functions and variables/constants, everything you write will be interpreted as a literal expression to manipulate key presses/releases. We refer to these as key expressions
.
Each key expression
generally contains keys that will be pressed together for a certain time, and then released roughly simultaneously. There is an alternative however, for when you want to hold some key till you specify otherwise.
Here are some examples:
abc # a,b,c are pressed together then released #
|abc| # Holds a,b,c until released #
|abc| # Since they're already held, releases them #
As you can see when you type a key expression, it is pretty literal, with |...|
syntax being used to indicate holding till a later point. We will discuss this in greater detail in the Key Expressions section.
Unlike most other languages, every form of whitespace is treated the same as a new line. That example above could have all been written on a single line.
Delays
The way of controlling how long keys are pressed before being released, and the wait after the fact, is by setting delays
. There are two types of delays
, one of them is hold
, and one of them is wait
.
hold
controls how long keys are held down (not referring to |...|
syntax), while wait
controls how key expressions are separated by time. There are generally three ways to set the two of these.
One way is setting a default delay, using the @delay
builtin function:
@delay [50,50] # First argument is `hold`, second is `wait` #
abc # Presses a,b,c then sleeps for 50ms, releases a,b,c then sleeps for 50ms #
# ...every key expression will have the 50ms `wait` and 50ms `hold` delay by default #
Alternatively, you can set the hold
and wait
separately by using their builtin functions:
@hold [50] # Sets the `hold` #
@wait [50] # Sets the `wait` #
abc # Presses a,b,c then sleeps for 50ms, releases a,b,c then sleeps for 50ms #
# ...every key expression will have the 50ms `wait` and 50ms `hold` delay by default #
The last way is by setting them inline. The key expressions
allow you to use tags on each side to set delays; the one on the left being hold
, and the other being wait
. A note is that you do not need to include both, and this does not affect the default delay.
Here's an example:
@delay [50,50] # First argument is `hold`, second is `wait` #
<100>abc<100> # Presses a,b,c then sleeps for 100ms, releases a,b,c then sleeps for 100ms #
<100>abc # Presses a,b,c then sleeps for 100ms, releases a,b,c then sleeps for 50ms (from default) #
# ...every key expression will have the 50ms `wait` and 50ms `hold` delay by default #
If you just want to have the program sleep for some time, you can use a tag without any keys to the right and it'll simply wait.
For example:
@delay [50,50] # First argument is `hold`, second is `wait` #
abc # Presses a,b,c then sleeps for 50ms, releases a,b,c then sleeps for 50ms #
<5000> # Wait for 5 seconds #
# ...everything later will come 5100 ms after the first `key expression` #
By default, the delay
set is 100 ms for hold, and 100 ms for wait.
Sections
We will not go into too much detail here, visit Sections for more information.
Sections are used to differentiate between different parts of the program. They exist partly to organize things, but also as a way to get past the fact everything is interpreted as a key expression
by default.
So, sections offer a different focused "environment" where you can declare variables, add metadata, or make functions depending on the type.
You set the section by simply using tags, with no need for a closing one. We will showcase a few types, with some comments to help, but not too much detail.
MACRO
This is the main part of the program (where the above code snippets would be running), and is the default section, so there is no need to explicitly set it unless you have already set it to another section. It must come last in the file.
Example:
<MACRO> # Unnecessary, just for showcase #
@delay [50,50] # First argument is `hold`, second is `wait` #
abc # Presses a,b,c then sleeps for 50ms, releases a,b,c then sleeps for 50ms #
VECTORS
This section allows you to set VECTORS, which are essentially variable arrays in other words. The assignments would be taken literally as key expressions
otherwise. Here's an example:
<VECTORS> # Setting the section to be VECTORS #
$my_delay = 50,50
<MACRO> # Now it's necessary, as VECTORS was the section beforehand #
@delay [$my_delay] # Will set `hold` to the first component of $my_delay, `wait` to the second. #
abc # Presses a,b,c then sleeps for 50ms, releases a,b,c then sleeps for 50ms #
FUNCS
This section is for declaring functions for reusable purposes. Here's an example:
<FUNCS> # Setting the section to be FUNCS #
@press_w { # Function definition #
w # Key expression: presses then releases w #
}
<MACRO> # Now it's necessary, as FUNCS was the section beforehand #
@press_w # Calls function, so presses then releases w #
What Happens to the Code
The code is compiled to another format we called .keyc
. This is a very simple format which you can use yourself, and which will likely be very useful to know later on.
It contains 5 different types of instruction:
p
- Presses a keyr
- Releases a keyw
- Waits for a certain number of msc
- Moves the cursor to some positions
- Scrolls by a certain number of notches
Each instruction is written on its own line, with the letter associated with the type first, then the value after. For example, abc
in Simkey
with the delays being 100,100
will result in this .keyc
file:
pa
pb
pc
w100
ra
rb
rc
w100
This will come in handy in the Importable Functions section of the documentation, as those allow you to create reusable functions that can be called within a Simkey
program and which can place code straight into the compiled code.
Getting Set Up
You can get the Simkey App to run Simkey code by visiting the Getting Started page.