Sequence-Transform is a user library for QMK that enables a rich declarative ruleset for transforming a sequence of keypresses into any output you would like.
Inspiration for Sequence-Transform was taken from Pascal Getreuer's innovative Autocorrect feature, without which we would not have even conceived this idea!
THIS LIBRARY IS NOT FINALIZED. A user who isn't looking to get involved in development should only use this right now if they want to test things out and are willing to deal with frequent breaking design changes.
Here is a working example of a fairly minimal keymap that is using this library.
From a terminal with the current working directory set to your keymap directory (example: qmk_userspace/keyboard/moonlander/keymaps/ikcelaks), run this
command to add the library as a git submodule (no need to create a fork first):
git submodule add https://github.com/ikcelaks/qmk_sequence_transform.git sequence_transform
At the end of the rules.mk file in your keymap folder, add the following lines:
# sequence_transform setup
mkfile_dir := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
include $(mkfile_dir)/sequence_transform/rules_auto_generate.mk
# end sequence_transform setupCaution
If your keymap folder doesn't already contain a rules.mk file, create an new rules.mk file there that just has the snippet from above. DO NOT instead paste the snippet into a rules.mk file at another location, because the paths won't be correct.
Define custom keycodes for your Sequence Token keys (commonly referred to as "magic keys") consecutively. Example:
enum custom_keycodes {
US_MAG1 = SAFE_RANGE,
US_MAG2,
US_MAG3,
US_MAG4,
US_D_UND, // other custom keycodes start here
US_QUOT_S,
};Add the following to the list of includes in your keymap.c file.
#include "sequence_transform/sequence_transform.h"In the process_record_user function of your keymap.c file, add the following (or equivalent) (Replace US_MAG1 with whatever your first Sequence Token key is named):
if (!process_sequence_transform(keycode, record, US_MAG1)) return false;Add this line to your post_process_record_user function in keymap.c:
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
post_process_sequence_transform(); // Add this line
}Add this line to your matrix_scan_user function in keymap.c:
void matrix_scan_user(void)
{
sequence_transform_task(); // Add this line
}Compile your keymap as usual. The first time you do this, an empty sequence_transform_config.json and sequence_transform_dict.txt file will be automatically generated in the correct locations (the root of your keymap folder).
Example:
qmk compile -kb moonlander -km ikcelaksAll configuration is done by modifying the sequence_transform_config.json and sequence_transform_dict.txt files that you copied
into your keymap root folder. DO NOT make any changes to any files in the sequence_transform directory or its sub-directories.
This file is used to tell the rules generator script how to interpret your sequence_transform_dict.txt file.
A full description of each setting is provided in the Wiki (TODO).
Important
The number of Sequence Token keys defined in step 3 of the setup, must match the number of sequence_token_symbols defined in the config.
This file contains a list of all the rules that the generator script will encode into the trie structure. A full explanation of how rules are constructed, how they manipulate the result of your keypresses, and how they interact with each other is found in the Wiki (TODO).
The symbols that you will need to use when constructing your rules are included at the top of rules dictionary file when it's created (see step 8).
Tip
For ideas on what rules you can write, take a look at the sample dictionary.
You should add the custom keys you defined in step 3 of the setup to your keymap. These custom keys will be matched one to one with the sequence_token_symbols defined in your sequence_transform_config.json file. That is, the custom key that you pass to process_sequence_transform in step 5 of the setup will correspond to the first symbol defined in sequence_token_symbols, and each following custom key will be matched with the next symbol. (This is why you must have the same number of each).
Symbols chosen can be any utf-8 symbol you like. The sample config and dictionary use a pointing finger and thumb emoji to aid in remembering which Sequence Token key is being used, which you may find helpful.
No special steps are required to build your firmware while using this library! Your rule set dictionary is automatically built into the required datastructure if necessary everytime you re-compile your firmware. This is accomplished by the lines added to your keymap's rules.mk file in step 2 of the setup.
You can split your rule sets into multiple files. The rules in all files are merged together before being processed, so they must use the same symbols. The main use case is to split out rules with private or personal information into a file that is ignored by Git.
Follow these steps to create a second private rules file and add it to the .gitignore:
- Add
"sequence_transform_dict_private.txt"to therules_file_name_listin yoursequence_transform_config.jsonfile. The final result should look something like this:"rules_file_name_list": [ "sequence_transform_dict.txt", "sequence_transform_dict_private.txt" ]
- Build your firmware as normal, which will automatically generate a new rule set file named
sequence_transform_dict_private.txt. - Add
*_private.txtto the.gitignorefile of the repo you store your layout in. This is NOT the.gitignorefile contained in thesequence_transformfolder (that only manages files in the Sequence Transform library). The.gitignorefile you want to change is probably at the root of your fork of theqmk_userspaceorqmk_firmwarerepo.
Sequence Transform provides an offline tester utility that will allow you to test changes to your rules without needing to flash a new firmware to your keyboard. This tool was instrumental during the development process, but we think you will enjoy it too as you explore new and increasingly complex rules to add to your arsenal. We have tried very hard to minimize the complexities of writing and understanding rules, but even the developers sometimes write rules that work differently than envisioned.
Instructions for building and using the tester utility are found in the Wiki. (TODO)