chordgen 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chordgen-0.1.0/PKG-INFO +277 -0
- chordgen-0.1.0/README.md +263 -0
- chordgen-0.1.0/pyproject.toml +23 -0
- chordgen-0.1.0/src/chordgen/__init__.py +0 -0
- chordgen-0.1.0/src/chordgen/alt_generator.py +33 -0
- chordgen-0.1.0/src/chordgen/assets/chords.csv +1999 -0
- chordgen-0.1.0/src/chordgen/chord.py +41 -0
- chordgen-0.1.0/src/chordgen/cli.py +65 -0
- chordgen-0.1.0/src/chordgen/config.py +85 -0
- chordgen-0.1.0/src/chordgen/gen.py +93 -0
- chordgen-0.1.0/src/chordgen/keyboards/__init__.py +4 -0
- chordgen-0.1.0/src/chordgen/keyboards/standard.py +279 -0
- chordgen-0.1.0/src/chordgen/output/__init__.py +0 -0
- chordgen-0.1.0/src/chordgen/output/kanata.py +105 -0
- chordgen-0.1.0/src/chordgen/output/qmk.py +74 -0
- chordgen-0.1.0/src/chordgen/output/zmk.py +149 -0
- chordgen-0.1.0/src/chordgen/pydantic.py +20 -0
- chordgen-0.1.0/src/chordgen/scorer.py +29 -0
- chordgen-0.1.0/src/chordgen/utils.py +41 -0
chordgen-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: chordgen
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author: Dane Lipscombe
|
|
6
|
+
Author-email: Dane Lipscombe <danelipscombe@gmail.com>
|
|
7
|
+
Requires-Dist: patternlite>=3.6
|
|
8
|
+
Requires-Dist: pydantic>=2.12.5
|
|
9
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
10
|
+
Requires-Dist: tqdm>=4.67.3
|
|
11
|
+
Requires-Dist: typer>=0.24.1
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# chordgen
|
|
16
|
+
|
|
17
|
+
Abbreviation generator for chording and text expansion
|
|
18
|
+
|
|
19
|
+
Every day, we find ourselves typing commonly used words repetitively, consuming time and effort. Text expansion offers a solution by allowing us to replace these frequently used words with unique abbreviations, thereby saving keystrokes. For instance, typing 't' with a trigger key could automatically generate 'the '. The objective isn't to abbreviate every word, but rather to focus on those that offer significant savings for the effort invested in memorization. Ideally you also want the abbreviations to be the most comfortable effort wise for your particular keyboard layout (qwerty, colemak, canary etc).
|
|
20
|
+
|
|
21
|
+
However, compiling such a list manually can be a daunting task. This is where chordgen comes in handy, it helps by automating the generation of the initial list and streamlines the process of importing them into different tools, so you can enhance and customize them over time.
|
|
22
|
+
|
|
23
|
+
Given a list of common words it can generate a list like the following, the way you input each word and alternate word depends on if you are using chording or text expansion
|
|
24
|
+
|
|
25
|
+
| Word | Abbreviation | Alt1 | Alt2 | Alt3 |
|
|
26
|
+
| ---- | ------------ | ----- | ------ | ------- |
|
|
27
|
+
| look | l | looks | looked | looking |
|
|
28
|
+
| give | ge | gives | gave | giving |
|
|
29
|
+
|
|
30
|
+
## Chording vs text expansion
|
|
31
|
+
|
|
32
|
+
Chording involves pressing multiple keys at the same time, while text expansion is typing as usual followed by a trigger key. There are pros and cons of each approach to consider:
|
|
33
|
+
|
|
34
|
+
### Chording Pros and Cons
|
|
35
|
+
|
|
36
|
+
- Quicker since the time taken is about the same as a single key press
|
|
37
|
+
- Can take time to get used to pressing multiple keys together
|
|
38
|
+
- Heavier on the fingers especially if you have heavy key switches
|
|
39
|
+
|
|
40
|
+
### Text Expansion Pros and Cons
|
|
41
|
+
|
|
42
|
+
- More possible combinations since you can use abbreviations that reverse and repeat letters
|
|
43
|
+
- Easier to set up with a standard keyboard
|
|
44
|
+
- Can be buggy with some programs due to the way it replaces text
|
|
45
|
+
- Can be a security issue at work since it captures key presses and might need administrator privilages to install
|
|
46
|
+
|
|
47
|
+
### Chording
|
|
48
|
+
|
|
49
|
+
The approach it takes with combos is to define combo, shift, and alt1/2 keys that are pressed in combination with the abbreviation to get the desired output. These keys work well on the thumbs to ensure all the abbreviations are possible to press with them. There are some extra combos to help with punctuation.
|
|
50
|
+
|
|
51
|
+
| Input | Output |
|
|
52
|
+
| ------------------------------- | ----------------------- |
|
|
53
|
+
| l + combo | look`<space>` |
|
|
54
|
+
| l + combo + shift | Look`<space>` |
|
|
55
|
+
| l + combo + alt1 | looked`<space>` |
|
|
56
|
+
| l + combo + alt2 | looking`<space>` |
|
|
57
|
+
| l + combo + alt1 + alt2 | looks`<space>` |
|
|
58
|
+
| l + combo + shift + alt1 + alt2 | Looks`<space>` |
|
|
59
|
+
| . + combo | `<backspace>`.`<space>` |
|
|
60
|
+
| , + combo | `<backspace>`,`<space>` |
|
|
61
|
+
| ; + combo | `<backspace>`;`<space>` |
|
|
62
|
+
|
|
63
|
+
This is how I have set up my 4 key thumb cluster from left to right:
|
|
64
|
+
|
|
65
|
+
- alt1 (normally tab on tap or my navigation/number/symbol layer on hold, with hold preferred setting)
|
|
66
|
+
- alt2 (normally space on tap or my media/function layer on hold, with tap preferred setting)
|
|
67
|
+
- shift (normally backspace on tap or shift on hold, with hold preferred setting)
|
|
68
|
+
- combo (normally delete word, this is great when making mistakes while learning)
|
|
69
|
+
|
|
70
|
+
### Text Expansion
|
|
71
|
+
|
|
72
|
+
The approach it takes with text expansion is to define a trigger which you type after the abbreviation. The default trigger is `,;`. Read below about setting up a trigger key so you can automate typing this on one key. Alternate versions and punctuation is accessed by adding an extra suffix after the abbreviation.
|
|
73
|
+
|
|
74
|
+
| Input | Output |
|
|
75
|
+
| ------------- | ---------------- |
|
|
76
|
+
| l`<trigger>` | look`<space>` |
|
|
77
|
+
| lq`<trigger>` | looked`<space>` |
|
|
78
|
+
| lj`<trigger>` | looking`<space>` |
|
|
79
|
+
| lz`<trigger>` | looks`<space>` |
|
|
80
|
+
| L`<trigger>` | Look`<space>` |
|
|
81
|
+
| L.`<trigger>` | Look.`<space>` |
|
|
82
|
+
| L,`<trigger>` | Look,`<space>` |
|
|
83
|
+
| L;`<trigger>` | Look;`<space>` |
|
|
84
|
+
|
|
85
|
+
## Setup
|
|
86
|
+
|
|
87
|
+
Clone the repo `git clone https://github.com/dlip/chordgen.git` and change to the directory with `cd chordgen`
|
|
88
|
+
|
|
89
|
+
### Python
|
|
90
|
+
|
|
91
|
+
- Install [Python 3.11+](https://www.python.org/downloads/)
|
|
92
|
+
- Run `pip install -r requirements.txt`
|
|
93
|
+
|
|
94
|
+
### Nix (Alternative to Python setup)
|
|
95
|
+
|
|
96
|
+
If you have [Nix](https://nixos.org/download) you can run `nix develop` to get into a shell with Python and the required dependencies. If you have [direnv](https://direnv.net/docs/installation.html) also, you can run `direnv allow` instead to have the dependencies available as soon as you change to the directory.
|
|
97
|
+
|
|
98
|
+
### Running
|
|
99
|
+
|
|
100
|
+
To run the commands use `python <file.py>`
|
|
101
|
+
|
|
102
|
+
## Commands
|
|
103
|
+
|
|
104
|
+
### chordgen.py
|
|
105
|
+
|
|
106
|
+
This reads `words.tsv` and outputs abbreviations in tsv format to `abbr.tsv`:
|
|
107
|
+
|
|
108
|
+
The approach it uses is:
|
|
109
|
+
|
|
110
|
+
- Generate all combinations of the letters in the word which start with the first letter and keep the order from left to right
|
|
111
|
+
- Reject abbreviations it has already used
|
|
112
|
+
- Reject abbreviations that are shorter than a minimum amount of characters or don't provide a minimum percentage improvement over typing the full word
|
|
113
|
+
- Score remaining abbreviations by effort and select the best option depending on your particular keyboard layout and if you are using chorded mode
|
|
114
|
+
- Add alt versions
|
|
115
|
+
- Use [alt.tsv](./alt.tsv) if available, else:
|
|
116
|
+
- Add verb tenses and plurals using [pattern](https://github.com/clips/pattern)
|
|
117
|
+
|
|
118
|
+
There are some options that you might want to change near the top of [chordgen.py](chordgen.py). In particular set `chorded_mode` to `True` or `False` depending on what method you are using.
|
|
119
|
+
|
|
120
|
+
### training.py
|
|
121
|
+
|
|
122
|
+
This generates a [training.txt](training.txt) file from `abbr.tsv` for you to copy a line of 10 words at a time into a typing practice tool like [Monkeytype](https://monkeytype.com/) custom mode to help learn the abbreviations:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
the and you have that for with this not but
|
|
126
|
+
t a y h th f w ti n b
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### qmk-chorded.py
|
|
130
|
+
|
|
131
|
+
This is a chorded importer for [QMK](https://qmk.fm) which is a firmware for custom keyboards.
|
|
132
|
+
|
|
133
|
+
You can check my config [here](https://github.com/dlip/qmk_firmware/tree/dlip/keyboards/mushi/keymaps/dlip) for reference
|
|
134
|
+
|
|
135
|
+
- Setup combos as per this [gboards guide](https://combos.gboards.ca/docs/install/)
|
|
136
|
+
- Add definitions for KC_COMBO, KC_COMBO_SFT, KC_COMBO_ALT1, KC_COMBO_ALT2 thumb keys to your `keymap.c`. Feel free to change the actions here to whatever works for you. If you have other special keys on your letters eg. home row mods, add definitions for these also so they can be referred to in the script. Use these in your keymap.
|
|
137
|
+
- Move the `#include "g/keymap_combo.h"` line below all your definitions
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
// Other definitions
|
|
141
|
+
|
|
142
|
+
#define KC_COMBO_ALT1 LT(1, KC_TAB)
|
|
143
|
+
#define KC_COMBO_ALT2 LT(2, KC_SPC)
|
|
144
|
+
#define KC_COMBO_SFT MT(MOD_LSFT, KC_BSPC)
|
|
145
|
+
#define KC_COMBO C(KC_BSPC)
|
|
146
|
+
|
|
147
|
+
#include "g/keymap_combo.h"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
- Open [qmk-chorded.py](qmk-chorded.py) and ensure `key_map` matches any other custom definitions you may have
|
|
151
|
+
- Run `python qmk-chorded.py`
|
|
152
|
+
- It will generate `abbr.def` which you need to copy to your QMK keymap directory
|
|
153
|
+
- Add `#include "abbr.def"` to the top of your QMK `combos.def` file
|
|
154
|
+
- Flash your keyboard
|
|
155
|
+
|
|
156
|
+
### zmk-chorded.py
|
|
157
|
+
|
|
158
|
+
This is a chorded importer for [ZMK](https://zmk.dev/) which is a firmware for custom keyboards.
|
|
159
|
+
|
|
160
|
+
You can check my config [here](https://github.com/dlip/zmk-sweep/blob/main/config/cradio.keymap) for reference
|
|
161
|
+
|
|
162
|
+
- Open [zmk-chorded.py](zmk-chorded.py) and ensure `key_positions` matches all the key positions on your keyboard
|
|
163
|
+
- Run `python zmk-chorded.py`
|
|
164
|
+
- It will generate `macros.dtsi` and `combos.dtsi` which you can then copy to your zmk keymap directory
|
|
165
|
+
- Include these lines in your zmk keymap keymap file
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
macros {
|
|
169
|
+
#include "macros.dtsi"
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
combos {
|
|
173
|
+
compatible = "zmk,combos";
|
|
174
|
+
#include "combos.dtsi"
|
|
175
|
+
};
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
- Include these lines in your zmk keymap conf file, you may have to increase `CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY` if you are able to fit more combos on your controller
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY=512
|
|
182
|
+
CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO=10
|
|
183
|
+
CONFIG_ZMK_COMBO_MAX_PRESSED_COMBOS=10
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- Flash your keyboard
|
|
187
|
+
|
|
188
|
+
### kanata-chorded.py
|
|
189
|
+
|
|
190
|
+
This is a chorded importer for [Kanata](https://github.com/jtroo/kanata) which is a software keyboard remapper. It uses the experimental chords v2 feature which requires at least Kanata v1.6.1.
|
|
191
|
+
|
|
192
|
+
Be aware that many keyboards, especially laptop ones do not support having many keys held at the same time. You can check what combinations work for your one [here](https://www.mechanical-keyboard.org/key-rollover-test/)
|
|
193
|
+
|
|
194
|
+
- Open [kanata-chorded.py](kanata-chorded.py) and customize the `mapping` dictionary with your base mappings and the combo etc. keys
|
|
195
|
+
- Run `python kanata-chorded.py` and copy [abbr.kbd](./abbr.kbd) to your keymap directory
|
|
196
|
+
- Follow the example in [engram-chorded.kbd](./engram-chorded.kbd) and update your keymap
|
|
197
|
+
- Add `concurrent-tap-hold yes` to the `defcfg` section
|
|
198
|
+
- Add `(include abbr.kbd)`
|
|
199
|
+
- Run `sudo kanata -c <keymap.kbd>`
|
|
200
|
+
|
|
201
|
+
### espanso-text-expansion.py
|
|
202
|
+
|
|
203
|
+
This is a text expansion importer for [Espanso](https://espanso.org)
|
|
204
|
+
|
|
205
|
+
It reads `abbr.tsv` and generates `abbr.yml` which you can then copy to `~/.config/espanso/match/`. The yaml file is quite verbose since it adds multiple matches for all the possible suffixes, so you'll probably want to make any changes to `abbr.tsv` then run this command again.
|
|
206
|
+
|
|
207
|
+
Here are some settings you might want to change:
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
# suffix to add to the end of an abbreviation to trigger the expansion
|
|
211
|
+
expand_trigger = ",;"
|
|
212
|
+
# suffix to add before the trigger to use the alternate forms in `abbr.tsv`
|
|
213
|
+
alt_suffix_1 = "q"
|
|
214
|
+
alt_suffix_2 = "j"
|
|
215
|
+
alt_suffix_3 = "z"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
It might be preferable to disable `undo_backspace` in `~/.config/espanso/config/default.yml` in case you want to backspace without loosing the whole word
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
undo_backspace: false
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
The `abbr.yml` file is very verbose, so if you want to add/update words I recommend reading on so you can edit `abbr.tsv` then generate the file again from that.
|
|
225
|
+
|
|
226
|
+
### Setting up a trigger key for text expansion
|
|
227
|
+
|
|
228
|
+
Having to type 2 characters eg. ',;' reduces the improvement gain considerably, especially for shorter words. You can bind a key on your keyboard that you don't usually use eg. right alt, caps lock via softwarwe or programmable keyboard firmware
|
|
229
|
+
|
|
230
|
+
#### Kanata (software)
|
|
231
|
+
|
|
232
|
+
Install [Kanata](https://github.com/jtroo/kanata) and add this alias to your config. You and then bind `@tgr` to a key of your choosing.
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
(defalias
|
|
236
|
+
tgr (macro , ;)
|
|
237
|
+
)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
#### ZMK (firmware)
|
|
241
|
+
|
|
242
|
+
Add this macro to your config, then you can bind `&tgr` to a key
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
macros {
|
|
246
|
+
ZMK_MACRO (tgr,
|
|
247
|
+
wait-ms = <30>;
|
|
248
|
+
tap-ms = <40>;
|
|
249
|
+
bindings = <&kp COMMA &kp SEMI>;
|
|
250
|
+
)
|
|
251
|
+
};
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### QMK (firmware)
|
|
255
|
+
|
|
256
|
+
Add this custom keycode to your config, then you can bind `TGR` to a key
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
enum custom_keycodes {
|
|
260
|
+
TGR = SAFE_RANGE,
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
264
|
+
switch (keycode) {
|
|
265
|
+
case TGR:
|
|
266
|
+
if (record->event.pressed) {
|
|
267
|
+
SEND_STRING(",;");
|
|
268
|
+
}
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
return true;
|
|
272
|
+
};
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Credits
|
|
276
|
+
|
|
277
|
+
- [English frequency list](https://tmh.conlang.org/word-frequency/)
|
chordgen-0.1.0/README.md
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# chordgen
|
|
2
|
+
|
|
3
|
+
Abbreviation generator for chording and text expansion
|
|
4
|
+
|
|
5
|
+
Every day, we find ourselves typing commonly used words repetitively, consuming time and effort. Text expansion offers a solution by allowing us to replace these frequently used words with unique abbreviations, thereby saving keystrokes. For instance, typing 't' with a trigger key could automatically generate 'the '. The objective isn't to abbreviate every word, but rather to focus on those that offer significant savings for the effort invested in memorization. Ideally you also want the abbreviations to be the most comfortable effort wise for your particular keyboard layout (qwerty, colemak, canary etc).
|
|
6
|
+
|
|
7
|
+
However, compiling such a list manually can be a daunting task. This is where chordgen comes in handy, it helps by automating the generation of the initial list and streamlines the process of importing them into different tools, so you can enhance and customize them over time.
|
|
8
|
+
|
|
9
|
+
Given a list of common words it can generate a list like the following, the way you input each word and alternate word depends on if you are using chording or text expansion
|
|
10
|
+
|
|
11
|
+
| Word | Abbreviation | Alt1 | Alt2 | Alt3 |
|
|
12
|
+
| ---- | ------------ | ----- | ------ | ------- |
|
|
13
|
+
| look | l | looks | looked | looking |
|
|
14
|
+
| give | ge | gives | gave | giving |
|
|
15
|
+
|
|
16
|
+
## Chording vs text expansion
|
|
17
|
+
|
|
18
|
+
Chording involves pressing multiple keys at the same time, while text expansion is typing as usual followed by a trigger key. There are pros and cons of each approach to consider:
|
|
19
|
+
|
|
20
|
+
### Chording Pros and Cons
|
|
21
|
+
|
|
22
|
+
- Quicker since the time taken is about the same as a single key press
|
|
23
|
+
- Can take time to get used to pressing multiple keys together
|
|
24
|
+
- Heavier on the fingers especially if you have heavy key switches
|
|
25
|
+
|
|
26
|
+
### Text Expansion Pros and Cons
|
|
27
|
+
|
|
28
|
+
- More possible combinations since you can use abbreviations that reverse and repeat letters
|
|
29
|
+
- Easier to set up with a standard keyboard
|
|
30
|
+
- Can be buggy with some programs due to the way it replaces text
|
|
31
|
+
- Can be a security issue at work since it captures key presses and might need administrator privilages to install
|
|
32
|
+
|
|
33
|
+
### Chording
|
|
34
|
+
|
|
35
|
+
The approach it takes with combos is to define combo, shift, and alt1/2 keys that are pressed in combination with the abbreviation to get the desired output. These keys work well on the thumbs to ensure all the abbreviations are possible to press with them. There are some extra combos to help with punctuation.
|
|
36
|
+
|
|
37
|
+
| Input | Output |
|
|
38
|
+
| ------------------------------- | ----------------------- |
|
|
39
|
+
| l + combo | look`<space>` |
|
|
40
|
+
| l + combo + shift | Look`<space>` |
|
|
41
|
+
| l + combo + alt1 | looked`<space>` |
|
|
42
|
+
| l + combo + alt2 | looking`<space>` |
|
|
43
|
+
| l + combo + alt1 + alt2 | looks`<space>` |
|
|
44
|
+
| l + combo + shift + alt1 + alt2 | Looks`<space>` |
|
|
45
|
+
| . + combo | `<backspace>`.`<space>` |
|
|
46
|
+
| , + combo | `<backspace>`,`<space>` |
|
|
47
|
+
| ; + combo | `<backspace>`;`<space>` |
|
|
48
|
+
|
|
49
|
+
This is how I have set up my 4 key thumb cluster from left to right:
|
|
50
|
+
|
|
51
|
+
- alt1 (normally tab on tap or my navigation/number/symbol layer on hold, with hold preferred setting)
|
|
52
|
+
- alt2 (normally space on tap or my media/function layer on hold, with tap preferred setting)
|
|
53
|
+
- shift (normally backspace on tap or shift on hold, with hold preferred setting)
|
|
54
|
+
- combo (normally delete word, this is great when making mistakes while learning)
|
|
55
|
+
|
|
56
|
+
### Text Expansion
|
|
57
|
+
|
|
58
|
+
The approach it takes with text expansion is to define a trigger which you type after the abbreviation. The default trigger is `,;`. Read below about setting up a trigger key so you can automate typing this on one key. Alternate versions and punctuation is accessed by adding an extra suffix after the abbreviation.
|
|
59
|
+
|
|
60
|
+
| Input | Output |
|
|
61
|
+
| ------------- | ---------------- |
|
|
62
|
+
| l`<trigger>` | look`<space>` |
|
|
63
|
+
| lq`<trigger>` | looked`<space>` |
|
|
64
|
+
| lj`<trigger>` | looking`<space>` |
|
|
65
|
+
| lz`<trigger>` | looks`<space>` |
|
|
66
|
+
| L`<trigger>` | Look`<space>` |
|
|
67
|
+
| L.`<trigger>` | Look.`<space>` |
|
|
68
|
+
| L,`<trigger>` | Look,`<space>` |
|
|
69
|
+
| L;`<trigger>` | Look;`<space>` |
|
|
70
|
+
|
|
71
|
+
## Setup
|
|
72
|
+
|
|
73
|
+
Clone the repo `git clone https://github.com/dlip/chordgen.git` and change to the directory with `cd chordgen`
|
|
74
|
+
|
|
75
|
+
### Python
|
|
76
|
+
|
|
77
|
+
- Install [Python 3.11+](https://www.python.org/downloads/)
|
|
78
|
+
- Run `pip install -r requirements.txt`
|
|
79
|
+
|
|
80
|
+
### Nix (Alternative to Python setup)
|
|
81
|
+
|
|
82
|
+
If you have [Nix](https://nixos.org/download) you can run `nix develop` to get into a shell with Python and the required dependencies. If you have [direnv](https://direnv.net/docs/installation.html) also, you can run `direnv allow` instead to have the dependencies available as soon as you change to the directory.
|
|
83
|
+
|
|
84
|
+
### Running
|
|
85
|
+
|
|
86
|
+
To run the commands use `python <file.py>`
|
|
87
|
+
|
|
88
|
+
## Commands
|
|
89
|
+
|
|
90
|
+
### chordgen.py
|
|
91
|
+
|
|
92
|
+
This reads `words.tsv` and outputs abbreviations in tsv format to `abbr.tsv`:
|
|
93
|
+
|
|
94
|
+
The approach it uses is:
|
|
95
|
+
|
|
96
|
+
- Generate all combinations of the letters in the word which start with the first letter and keep the order from left to right
|
|
97
|
+
- Reject abbreviations it has already used
|
|
98
|
+
- Reject abbreviations that are shorter than a minimum amount of characters or don't provide a minimum percentage improvement over typing the full word
|
|
99
|
+
- Score remaining abbreviations by effort and select the best option depending on your particular keyboard layout and if you are using chorded mode
|
|
100
|
+
- Add alt versions
|
|
101
|
+
- Use [alt.tsv](./alt.tsv) if available, else:
|
|
102
|
+
- Add verb tenses and plurals using [pattern](https://github.com/clips/pattern)
|
|
103
|
+
|
|
104
|
+
There are some options that you might want to change near the top of [chordgen.py](chordgen.py). In particular set `chorded_mode` to `True` or `False` depending on what method you are using.
|
|
105
|
+
|
|
106
|
+
### training.py
|
|
107
|
+
|
|
108
|
+
This generates a [training.txt](training.txt) file from `abbr.tsv` for you to copy a line of 10 words at a time into a typing practice tool like [Monkeytype](https://monkeytype.com/) custom mode to help learn the abbreviations:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
the and you have that for with this not but
|
|
112
|
+
t a y h th f w ti n b
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### qmk-chorded.py
|
|
116
|
+
|
|
117
|
+
This is a chorded importer for [QMK](https://qmk.fm) which is a firmware for custom keyboards.
|
|
118
|
+
|
|
119
|
+
You can check my config [here](https://github.com/dlip/qmk_firmware/tree/dlip/keyboards/mushi/keymaps/dlip) for reference
|
|
120
|
+
|
|
121
|
+
- Setup combos as per this [gboards guide](https://combos.gboards.ca/docs/install/)
|
|
122
|
+
- Add definitions for KC_COMBO, KC_COMBO_SFT, KC_COMBO_ALT1, KC_COMBO_ALT2 thumb keys to your `keymap.c`. Feel free to change the actions here to whatever works for you. If you have other special keys on your letters eg. home row mods, add definitions for these also so they can be referred to in the script. Use these in your keymap.
|
|
123
|
+
- Move the `#include "g/keymap_combo.h"` line below all your definitions
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
// Other definitions
|
|
127
|
+
|
|
128
|
+
#define KC_COMBO_ALT1 LT(1, KC_TAB)
|
|
129
|
+
#define KC_COMBO_ALT2 LT(2, KC_SPC)
|
|
130
|
+
#define KC_COMBO_SFT MT(MOD_LSFT, KC_BSPC)
|
|
131
|
+
#define KC_COMBO C(KC_BSPC)
|
|
132
|
+
|
|
133
|
+
#include "g/keymap_combo.h"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- Open [qmk-chorded.py](qmk-chorded.py) and ensure `key_map` matches any other custom definitions you may have
|
|
137
|
+
- Run `python qmk-chorded.py`
|
|
138
|
+
- It will generate `abbr.def` which you need to copy to your QMK keymap directory
|
|
139
|
+
- Add `#include "abbr.def"` to the top of your QMK `combos.def` file
|
|
140
|
+
- Flash your keyboard
|
|
141
|
+
|
|
142
|
+
### zmk-chorded.py
|
|
143
|
+
|
|
144
|
+
This is a chorded importer for [ZMK](https://zmk.dev/) which is a firmware for custom keyboards.
|
|
145
|
+
|
|
146
|
+
You can check my config [here](https://github.com/dlip/zmk-sweep/blob/main/config/cradio.keymap) for reference
|
|
147
|
+
|
|
148
|
+
- Open [zmk-chorded.py](zmk-chorded.py) and ensure `key_positions` matches all the key positions on your keyboard
|
|
149
|
+
- Run `python zmk-chorded.py`
|
|
150
|
+
- It will generate `macros.dtsi` and `combos.dtsi` which you can then copy to your zmk keymap directory
|
|
151
|
+
- Include these lines in your zmk keymap keymap file
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
macros {
|
|
155
|
+
#include "macros.dtsi"
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
combos {
|
|
159
|
+
compatible = "zmk,combos";
|
|
160
|
+
#include "combos.dtsi"
|
|
161
|
+
};
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- Include these lines in your zmk keymap conf file, you may have to increase `CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY` if you are able to fit more combos on your controller
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY=512
|
|
168
|
+
CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO=10
|
|
169
|
+
CONFIG_ZMK_COMBO_MAX_PRESSED_COMBOS=10
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- Flash your keyboard
|
|
173
|
+
|
|
174
|
+
### kanata-chorded.py
|
|
175
|
+
|
|
176
|
+
This is a chorded importer for [Kanata](https://github.com/jtroo/kanata) which is a software keyboard remapper. It uses the experimental chords v2 feature which requires at least Kanata v1.6.1.
|
|
177
|
+
|
|
178
|
+
Be aware that many keyboards, especially laptop ones do not support having many keys held at the same time. You can check what combinations work for your one [here](https://www.mechanical-keyboard.org/key-rollover-test/)
|
|
179
|
+
|
|
180
|
+
- Open [kanata-chorded.py](kanata-chorded.py) and customize the `mapping` dictionary with your base mappings and the combo etc. keys
|
|
181
|
+
- Run `python kanata-chorded.py` and copy [abbr.kbd](./abbr.kbd) to your keymap directory
|
|
182
|
+
- Follow the example in [engram-chorded.kbd](./engram-chorded.kbd) and update your keymap
|
|
183
|
+
- Add `concurrent-tap-hold yes` to the `defcfg` section
|
|
184
|
+
- Add `(include abbr.kbd)`
|
|
185
|
+
- Run `sudo kanata -c <keymap.kbd>`
|
|
186
|
+
|
|
187
|
+
### espanso-text-expansion.py
|
|
188
|
+
|
|
189
|
+
This is a text expansion importer for [Espanso](https://espanso.org)
|
|
190
|
+
|
|
191
|
+
It reads `abbr.tsv` and generates `abbr.yml` which you can then copy to `~/.config/espanso/match/`. The yaml file is quite verbose since it adds multiple matches for all the possible suffixes, so you'll probably want to make any changes to `abbr.tsv` then run this command again.
|
|
192
|
+
|
|
193
|
+
Here are some settings you might want to change:
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
# suffix to add to the end of an abbreviation to trigger the expansion
|
|
197
|
+
expand_trigger = ",;"
|
|
198
|
+
# suffix to add before the trigger to use the alternate forms in `abbr.tsv`
|
|
199
|
+
alt_suffix_1 = "q"
|
|
200
|
+
alt_suffix_2 = "j"
|
|
201
|
+
alt_suffix_3 = "z"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
It might be preferable to disable `undo_backspace` in `~/.config/espanso/config/default.yml` in case you want to backspace without loosing the whole word
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
undo_backspace: false
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The `abbr.yml` file is very verbose, so if you want to add/update words I recommend reading on so you can edit `abbr.tsv` then generate the file again from that.
|
|
211
|
+
|
|
212
|
+
### Setting up a trigger key for text expansion
|
|
213
|
+
|
|
214
|
+
Having to type 2 characters eg. ',;' reduces the improvement gain considerably, especially for shorter words. You can bind a key on your keyboard that you don't usually use eg. right alt, caps lock via softwarwe or programmable keyboard firmware
|
|
215
|
+
|
|
216
|
+
#### Kanata (software)
|
|
217
|
+
|
|
218
|
+
Install [Kanata](https://github.com/jtroo/kanata) and add this alias to your config. You and then bind `@tgr` to a key of your choosing.
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
(defalias
|
|
222
|
+
tgr (macro , ;)
|
|
223
|
+
)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### ZMK (firmware)
|
|
227
|
+
|
|
228
|
+
Add this macro to your config, then you can bind `&tgr` to a key
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
macros {
|
|
232
|
+
ZMK_MACRO (tgr,
|
|
233
|
+
wait-ms = <30>;
|
|
234
|
+
tap-ms = <40>;
|
|
235
|
+
bindings = <&kp COMMA &kp SEMI>;
|
|
236
|
+
)
|
|
237
|
+
};
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
#### QMK (firmware)
|
|
241
|
+
|
|
242
|
+
Add this custom keycode to your config, then you can bind `TGR` to a key
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
enum custom_keycodes {
|
|
246
|
+
TGR = SAFE_RANGE,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
250
|
+
switch (keycode) {
|
|
251
|
+
case TGR:
|
|
252
|
+
if (record->event.pressed) {
|
|
253
|
+
SEND_STRING(",;");
|
|
254
|
+
}
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
return true;
|
|
258
|
+
};
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Credits
|
|
262
|
+
|
|
263
|
+
- [English frequency list](https://tmh.conlang.org/word-frequency/)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "chordgen"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Add your description here"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Dane Lipscombe", email = "danelipscombe@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"patternlite>=3.6",
|
|
12
|
+
"pydantic>=2.12.5",
|
|
13
|
+
"pyyaml>=6.0.3",
|
|
14
|
+
"tqdm>=4.67.3",
|
|
15
|
+
"typer>=0.24.1",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.scripts]
|
|
19
|
+
chordgen = "chordgen.cli:app"
|
|
20
|
+
|
|
21
|
+
[build-system]
|
|
22
|
+
requires = ["uv_build>=0.10.2,<0.11.0"]
|
|
23
|
+
build-backend = "uv_build"
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from chordgen.chord import Chord
|
|
3
|
+
from chordgen.config import Config
|
|
4
|
+
|
|
5
|
+
from pattern import en
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AltGenerator:
|
|
9
|
+
def __init__(self, config: Config) -> None:
|
|
10
|
+
self.config = config
|
|
11
|
+
|
|
12
|
+
def add_alt(self, chord: Chord) -> Chord:
|
|
13
|
+
word = chord["word"]
|
|
14
|
+
type = chord["type"]
|
|
15
|
+
if self.config.overwrite_alts:
|
|
16
|
+
chord["alt1"] = ""
|
|
17
|
+
chord["alt2"] = ""
|
|
18
|
+
chord["alt3"] = ""
|
|
19
|
+
|
|
20
|
+
if type == "VERB":
|
|
21
|
+
if not chord["alt1"]:
|
|
22
|
+
chord["alt1"] = en.conjugate(word, "3sg")
|
|
23
|
+
if not chord["alt2"]:
|
|
24
|
+
chord["alt2"] = en.conjugate(word, "1sgp")
|
|
25
|
+
if not chord["alt3"]:
|
|
26
|
+
chord["alt3"] = en.conjugate(word, "part")
|
|
27
|
+
elif type == "NOUN":
|
|
28
|
+
if not chord["alt1"]:
|
|
29
|
+
chord["alt1"] = en.pluralize(word, pos=en.NOUN)
|
|
30
|
+
logging.debug(
|
|
31
|
+
f"Alts for word {word}: {chord['alt1']}, {chord['alt2']}, {chord['alt3']}"
|
|
32
|
+
)
|
|
33
|
+
return chord
|