[Keymap] Add slotThe keyboardio/atreus keymap (#21274)

This commit is contained in:
Tony Zorman 2023-07-07 16:35:00 +02:00 committed by GitHub
parent d4610906bf
commit bb8e3796a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 651 additions and 0 deletions

View File

@ -0,0 +1,44 @@
// Copyright 2023 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
/*******************************************************************************
88888888888 888 d8b .d888 d8b 888 d8b
888 888 Y8P d88P" Y8P 888 Y8P
888 888 888 888
888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b
888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K
888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b.
888 888 888 888 X88 888 888 888 Y8b. 888 X88
888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P'
888 888
888 888
888 888
.d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888
d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888
888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888
Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888
"Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888
888
Y8b d88P
"Y88P"
*******************************************************************************/
#pragma once
// Autocorrection dictionary (4 entries):
// :alot -> a lot
// accesories -> accessories
// accomodate -> accommodate
// alledge -> allege
#define AUTOCORRECT_MIN_LENGTH 5 // ":alot"
#define AUTOCORRECT_MAX_LENGTH 10 // "accesories"
#define DICTIONARY_SIZE 73
static const uint8_t autocorrect_data[DICTIONARY_SIZE] PROGMEM = {
0x48, 0x0A, 0x00, 0x16, 0x2C, 0x00, 0x17, 0x3E, 0x00, 0x00, 0x4A, 0x11, 0x00, 0x17, 0x1B, 0x00,
0x00, 0x07, 0x08, 0x0F, 0x0F, 0x04, 0x00, 0x82, 0x67, 0x65, 0x00, 0x04, 0x07, 0x12, 0x10, 0x12,
0x06, 0x06, 0x04, 0x00, 0x84, 0x6D, 0x6F, 0x64, 0x61, 0x74, 0x65, 0x00, 0x08, 0x0C, 0x15, 0x12,
0x16, 0x08, 0x06, 0x06, 0x04, 0x00, 0x84, 0x73, 0x6F, 0x72, 0x69, 0x65, 0x73, 0x00, 0x12, 0x0F,
0x04, 0x2C, 0x00, 0x82, 0x20, 0x6C, 0x6F, 0x74, 0x00
};

View File

@ -0,0 +1,19 @@
/* © 2023 Tony Zorman <soliditsallgood@mailbox.org> (@slotThe)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define BOTH_SHIFTS_TURNS_ON_CAPS_WORD
#define TAPPING_TERM 175
#define HOLD_ON_OTHER_KEY_PRESS

View File

@ -0,0 +1,328 @@
/* © 2023 Tony Zorman <soliditsallgood@mailbox.org> (@slotThe)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
// NOTE: `M-x occur RET /// RET' gives a good overview.
/// General macros
#define LSPR_SC LGUI_T(KC_SCLN)
#define LALT_BR LALT_T(KC_LBRC)
#define LSFT_INS LSFT(KC_INS)
#define OSMSFT OSM(MOD_LSFT)
#define Z_SFT LSFT_T(KC_Z)
#define ZE_SFT LSFT_T(KC_0)
#define SL_SFT RSFT_T(KC_SLSH)
#define RETSPR LGUI_T(KC_ENT)
/// Tap dance declarations
// So far, tap dances do different things on
//
// - a single press,
// - a double press,
// - when held,
//
// so expect this many keys as comments.
enum tap_dances {
ALT_BR, // [ ] lalt (also works shifted, which gets us { and } for free)
CTL_PR, // ( ) lctl
SFT_CI, // ^ ^ lsft (working around LSFT_T not being able to output shifted keys)
SFT_EX, // ! ! lsft (ditto)
};
#define CTLPAR TD(CTL_PR)
#define ALTBRC TD(ALT_BR)
#define SFTCRC TD(SFT_CI)
#define SFTEXL TD(SFT_EX)
/// Macro declarations
enum custom_keycodes {
// -> <- =<< >>= <*> <* *> <$> <&> <|> => ::
RARR = SAFE_RANGE, LARR, LBND, RBND, APP, RAPP, LAPP, FMAP, PAMF, AALT, IMPLS, DCOL,
};
/// Key overrides
const key_override_t **key_overrides = (const key_override_t *[]){
&ko_make_basic(MOD_MASK_SHIFT, KC_BSPC, KC_DEL), // S-BSP ≡ DEL
// Emacs got me used to these, so let's convince other programs that
// we are in fact sending the correct keys.
&ko_make_basic(MOD_MASK_CTRL, KC_I, KC_TAB), // C-i ≡ Tab
&ko_make_basic(MOD_MASK_CTRL, KC_M, KC_ENT), // C-m ≡ Return
NULL // Null terminate the array of overrides
};
/// Layers
enum layer_names { _COLEMAK_DH, _LOWER, _RAISE, _ADJUST };
#define LOWER MO(_LOWER)
#define RAISE MO(_RAISE)
#define ADJUST MO(_ADJUST)
#define D_RAISE LT(_RAISE, KC_DOT)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Colemak base layer
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| Q | W | F | P | B | | J | L | U | Y | ;+S |
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| A | R | S | T | G | | M | N | E | I | O |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| S+Z | X | C | D | V | ARP | REP | K | H | , | . | S+/ |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| ESC | TAB | SPR | L1 | SPC | A[] | BSC | C() | L2 | - | ' | RET |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
*/
[_COLEMAK_DH] = LAYOUT(
KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, LSPR_SC,
KC_A, KC_R, KC_S, KC_T, KC_G, KC_M, KC_N, KC_E, KC_I, KC_O,
Z_SFT, KC_X, KC_C, KC_D, KC_V, QK_AREP, QK_REP, KC_K, KC_H, KC_COMM, D_RAISE, SL_SFT,
KC_ESC, KC_TAB, KC_LGUI, LOWER, KC_SPC, ALTBRC, KC_BSPC, CTLPAR, RAISE, KC_MINS, KC_QUOT, KC_ENT),
/* Layer 1 (LOWER)
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-------.
| & | *> | >>= | <&> | | | = | + | * | - | RET+M |
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-------.
| :: | => | =<< | <|> | @ | | LFT | UP | DWN | RGT | \ |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-------.
| !+S | <* | <*> | <$> | <- | | MEN | -> | $ | # | % | ^+S |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-------.
| | | | | | | | | L3 | ALT | | S-I |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-------.
*/
[_LOWER] = LAYOUT(
KC_AMPR, RAPP, RBND, PAMF, _______, KC_EQL, KC_PLUS, KC_ASTR, KC_MINS, RETSPR,
DCOL, IMPLS, LBND, AALT, KC_AT, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_BSLS,
SFTEXL, LAPP, APP, FMAP, LARR, _______, KC_APP, RARR, KC_DLR, KC_HASH, KC_PERC, SFTCRC,
_______, _______, _______, _______, _______, _______, _______, _______, ADJUST, KC_LALT, _______, LSFT_INS),
/* Layer 2 (RAISE)
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| | 7 | 8 | 9 | | | | + | * | - | |
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| : | 4 | 5 | 6 | = | | & | ` | _ | ' | " |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| 0+S | 1 | 2 | 3 | | | | | ! | # | % | ^+S |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| | | | L3 | | | | | | | | |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
*/
[_RAISE] = LAYOUT(
KC_DOT, KC_7, KC_8, KC_9, _______, _______, KC_PLUS, KC_ASTR, KC_MINS, _______,
KC_COLN, KC_4, KC_5, KC_6, KC_EQL, KC_AMPR, KC_GRV, KC_UNDS, KC_QUOT, KC_DQT,
ZE_SFT, KC_1, KC_2, KC_3, _______, _______, _______, _______, KC_EXLM, KC_HASH, KC_PERC, SFTCRC,
_______, _______, _______, ADJUST, _______, _______, _______, _______, _______, _______, _______, _______),
/* Layer 3 (ADJUST)
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| | | | | | | | F7 | F8 | F9 | F10 |
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| | | | | | | | F4 | F5 | F6 | F11 |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| | | | | | | | | F1 | F2 | F3 | F12 |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| | | | | | | | | | | | |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
*/
[_ADJUST] = LAYOUT(
_______, _______, _______, _______, AC_TOGG, _______, KC_F7, KC_F8, KC_F9, KC_F10,
_______, _______, _______, _______, _______, _______, KC_F4, KC_F5, KC_F6, KC_F11,
_______, _______, _______, _______, _______, _______, _______, _______, KC_F1, KC_F2, KC_F3, KC_F12,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
};
/// Macro definitions
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case RARR:
if (record->event.pressed) SEND_STRING("->"); break;
case LARR:
if (record->event.pressed) SEND_STRING("<-"); break;
case LBND:
if (record->event.pressed) SEND_STRING("=<<"); break;
case RBND:
if (record->event.pressed) SEND_STRING(">>="); break;
case APP:
if (record->event.pressed) SEND_STRING("<*>"); break;
case RAPP:
if (record->event.pressed) SEND_STRING("*>"); break;
case LAPP:
if (record->event.pressed) SEND_STRING("<*"); break;
case FMAP:
if (record->event.pressed) SEND_STRING("<$>"); break;
case PAMF:
if (record->event.pressed) SEND_STRING("<&>"); break;
case AALT:
if (record->event.pressed) SEND_STRING("<|>"); break;
case IMPLS:
if (record->event.pressed) SEND_STRING("=>"); break;
case DCOL:
if (record->event.pressed) SEND_STRING("::"); break;
}
return true;
};
//// Tap dance definitions
// Heavily inspired by:
//
// https://docs.qmk.fm/?ref=blog.splitkb.com#/feature_tap_dance?id=example-4
typedef enum {
TD_NONE,
TD_UNKNOWN,
TD_SINGLE_TAP,
TD_SINGLE_HOLD,
TD_DOUBLE_TAP,
} td_state_t;
typedef struct {
bool is_press_action;
td_state_t state;
} td_tap_t;
// Return an integer that corresponds to what kind of tap dance should
// be executed.
//
// Interrupted: If the state of a dance is "interrupted", that means
// that another key has been hit under the tapping term.
//
// Pressed: Whether or not the key is still being pressed. If this value
// is true, that means the tapping term has ended, but the key is still
// being pressed down. This generally means the key is being "held".
td_state_t cur_dance(tap_dance_state_t *state) {
if (state->count == 1) {
if (state->pressed) return TD_SINGLE_HOLD;
else return TD_SINGLE_TAP;
} else if (state->count == 2) return TD_DOUBLE_TAP;
else return TD_UNKNOWN;
}
//// ALT_BR
static td_tap_t alt_br_state = {
.is_press_action = true,
.state = TD_NONE
};
void lalt_br_finished(tap_dance_state_t *state, void *user_data) {
alt_br_state.state = cur_dance(state);
switch (alt_br_state.state) {
case TD_SINGLE_TAP: register_code(KC_LBRC); break;
case TD_SINGLE_HOLD: register_code(KC_LALT); break;
case TD_DOUBLE_TAP: register_code(KC_RBRC); break;
default: break;
}
}
void lalt_br_reset(tap_dance_state_t *state, void *user_data) {
switch (alt_br_state.state) {
case TD_SINGLE_TAP: unregister_code(KC_LBRC); break;
case TD_SINGLE_HOLD: unregister_code(KC_LALT); break;
case TD_DOUBLE_TAP: unregister_code(KC_RBRC); break;
default: break;
}
alt_br_state.state = TD_NONE;
}
//// LCTL_PR
static td_tap_t lctl_pr_state = {
.is_press_action = true,
.state = TD_NONE
};
void lctl_pr_finished(tap_dance_state_t *state, void *user_data) {
lctl_pr_state.state = cur_dance(state);
switch (lctl_pr_state.state) {
case TD_SINGLE_TAP: register_code16(KC_LPRN); break;
case TD_SINGLE_HOLD: register_code(KC_LCTL); break;
case TD_DOUBLE_TAP: register_code16(KC_RPRN); break;
default: break;
}
}
void lctl_pr_reset(tap_dance_state_t *state, void *user_data) {
switch (lctl_pr_state.state) {
case TD_SINGLE_TAP: unregister_code16(KC_LPRN); break;
case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break;
case TD_DOUBLE_TAP: unregister_code16(KC_RPRN); break;
default: break;
}
lctl_pr_state.state = TD_NONE;
}
//// SFT_CI
static td_tap_t lsft_ci_state = {
.is_press_action = true,
.state = TD_NONE
};
void lsft_ci_finished(tap_dance_state_t *state, void *user_data) {
lsft_ci_state.state = cur_dance(state);
switch (lsft_ci_state.state) {
case TD_SINGLE_TAP: register_code16(KC_CIRC); break;
case TD_SINGLE_HOLD: register_code(KC_LSFT); break;
default: break;
}
}
void lsft_ci_reset(tap_dance_state_t *state, void *user_data) {
switch (lsft_ci_state.state) {
case TD_SINGLE_TAP: unregister_code16(KC_CIRC); break;
case TD_SINGLE_HOLD: unregister_code(KC_LSFT); break;
default: break;
}
lsft_ci_state.state = TD_NONE;
}
//// SFT_EX
static td_tap_t lsft_ex_state = {
.is_press_action = true,
.state = TD_NONE
};
void lsft_ex_finished(tap_dance_state_t *state, void *user_data) {
lsft_ex_state.state = cur_dance(state);
switch (lsft_ex_state.state) {
case TD_SINGLE_TAP: register_code16(KC_EXLM); break;
case TD_SINGLE_HOLD: register_code(KC_LSFT); break;
default: break;
}
}
void lsft_ex_reset(tap_dance_state_t *state, void *user_data) {
switch (lsft_ex_state.state) {
case TD_SINGLE_TAP: unregister_code16(KC_EXLM); break;
case TD_SINGLE_HOLD: unregister_code(KC_LSFT); break;
default: break;
}
lsft_ex_state.state = TD_NONE;
}
//// Actually define the tap-dance actions
tap_dance_action_t tap_dance_actions[] = {
[ALT_BR] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, lalt_br_finished, lalt_br_reset),
[CTL_PR] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, lctl_pr_finished, lctl_pr_reset),
[SFT_CI] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, lsft_ci_finished, lsft_ci_reset),
[SFT_EX] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, lsft_ex_finished, lsft_ex_reset),
};

View File

@ -0,0 +1,251 @@
# SlotThe's Keyboardio Atreus Keymap
Note: the following is (a relevant and shortened) excerpt from [this
rewiev](https://tony-zorman.com/posts/atreus-review.html) of the
keyboard itself. See there for, e.g., some thoughts about modifier
placement.
## Base layer
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.------.
| Q | W | F | P | B | | J | L | U | Y | M4+; |
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.------.
| A | R | S | T | G | | M | N | E | I | O |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.------.
| S+Z | X | C | D | V | ARP | REP | K | H | , | . | S+/ |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.------.
| ESC | TAB | M4 | L1 | SPC | A[] | BSC | C() | L2 | - | ' | RET |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.------.
I use [Colemak Mod-DH][colemak-dh] as my layout, so this takes up most of the base of the keyboard.
Perhaps strikingly, I opted for not putting Shift on the thumb,
but recreating the "ordinary" one-on-each-side setup from the good old typewriter days.
While I already have a key to access the `LOWER` (L1) layer with my left thumb,
I had to sacrifice Shift so I could fit a key to the `RAISE` (L2) layer on the right thumb.
This also jumps to the `ADJUST` (L3) layer when both `LOWER` and `RAISE` are held at the same time.
I will gladly trade two layers for one Shift key.
One of the most basic things—besides having layers—that one can do with QMK is [mod-taps][qmk:mod-tap].
These are keys that act as modifiers when held, and as "ordinary" keys when pressed.
For example, all of the `S+«key»` keys emit Shift when held and `«key»` when pressed.
There is a slight delay between pressing the key and the press registering,
since we have to wait for a possible tap,
which keeps me from using modifiers on the home-row, as some people like to do.
Likewise, the `M4+;` key acts as Super when held and as `;` when pressed.
At this point, it is actually my main way to press the Super key,
even though I don't find the real `M4` key particularly hard to hit with my thumb.
Sometimes these things just happen,
I suppose,
though it may help that I press both outer keys of the top row (that is, `q` and `;`) with my ring finger
instead of my pinky.
The `A[]` and `C()` keys are utilising [tap dances][qmk:tap-dance],
in order to do even more.
Tap dances are very similar to mod-taps,
only in addition to just differentiating between a "pressed" and a "held" state,
QMK now also keeps track of *how often* a key has been tapped.
So far, [my setup][qmk:slotthe:tapdances] here is quite basic;
I only check whether a key was pressed once, twice, or is being held.
This allows me to not need extra keys for parentheses,
as they can fit on the modifier keys:
- `A[]`: Alt when held, `[` when pressed once, and `]` when pressed twice.
This one is especially neat, since tap dances play well with other modifiers,
so pressing `S-M1` once will result in `{` and pressing it twice gives `}`.
- `C()`: Control when held, `(` when pressed once, and `)` when pressed twice.
I don't mind having the extra indirection for the respective closed delimiter,
as [paredit][emacs:paredit],
[puni][emacs:puni],
`electric-pair-mode`,
or a different package of choice usually takes care of inserting it.
The `REP` and `AREP` keys make use of the [Repeat Key][qmk:repeat-key] functionality;
basically, `REP` executes the key chord that was last pressed.
On the other hand,
`AREP` is an alternative, configurable, of "repeating" things;
by default, it turns some directional movements
around—e.g., `M-f` becomes `M-b`—but
it can be made to pretty much input anything one wants.
## Layer 1
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-------.
| & | *> | >>= | <&> | | | = | + | * | - | M4+RT |
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-------.
| :: | => | =<< | <|> | @ | | LFT | UP | DWN | RGT | \ |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-------.
| S+! | <* | <*> | <$> | <- | | MEN | -> | $ | # | % | S+^ |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-------.
| | | | | | | | | L3 | ALT | | S-Ins |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-------.
Guess which programming language I like based on this layer's [macros][qmk:macros] :).
Crucially, keys that were "Shift when held,
*something* when pressed" on the base layer retain the Shift part of that functionality.
This is used for the commutativity of the modifier
keys—i.e., it does not matter whether I press `S-L1-«key»` or `L1-S-«key»`—which
would otherwise drive me insane.
The same goes for all fall-through keys:
keys that appear blank in the above layout.
These aren't blocked or anything,
just no new functionality is added
so the key falls back to what's on the next lowest layer.
In plain terms,
the key to the left of `L3` will still be Control,
as I can comfortably press that while holding down something with my left hand.
The same can't be said for the Alt key,
which is on the left hand by default,
so a separate binding for it has to be created on the right hand.
Thus,
as the two don't commute,
key chords involving the LOWER layer and Alt are to be avoided if possible.
The `S-Ins` key is not some sort of tap,
but actually just emits a Shift-Insert,
which can be used to paste stuff from the [X11 primary selection][x11:clipboard].
## Layer 2
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| | 7 | 8 | 9 | | | | + | * | - | |
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| : | 4 | 5 | 6 | = | | | ` | _ | ' | " |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| S+0 | 1 | 2 | 3 | | | | | | # | % | S+^ |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| | | | L3 | | | | | | | | |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
A relatively unspectacular layer,
RAISE is mainly used for numbers,
and number adjacent things.
Some symbols related to this,
like `=`, `+`, `*`, and `-`,
are replicated from the LOWER layer.
This is due to the above mentioned issues of inserting arithmetic.
This layer also features \` and `'` quite prominently,
as these are important for [CDLaTeX].
Plus, putting `'` and `"` on this layer circumvents the difficult to hit key on the base layer.
## Layer 3
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| | | | | | | | F7 | F8 | F9 | F10 |
.-----.-----.-----.-----.-----. .-----.-----.-----.-----.-----.
| | | | | | | | F4 | F5 | F6 | F11 |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| | | | | | | | | F1 | F2 | F3 | F12 |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
| | | | | | | | | | | | |
.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.-----.
So far, only the seldom used F-keys are present here.
As should be obvious, this is the least developed layer,
and also the one that'll probably change the most in the future.
Currently, I'm thinking of putting some XMonad specific bindings on here,
which could even to free up the Super key to be used inside of Emacs
for certain things—that would certainly be a worthwhile experiment.
Other thoughts include things like volume and brightness controls,
although this is less critical since my laptop keyboard is never far away.
## Other features
There are some features that aren't necessarily reflected in the keys themselves,
yet are quite essential for day-to-day use.
The TL;DR can be found in [rules.mk][./rules.mk].
### [Key overrides][qmk:key-overrides]
Quoting from the documentation
> Key overrides allow you to override modifier-key combinations to send a different modifier-key combination
> or perform completely custom actions.
Some keys on the keyboard are quite hard to hit.
On the default layout,
one of these turns out to be the Tab key,
which is nonetheless important in a lot of situations.
Conveniently, Emacs interprets `C-i` as Tab, so there is less need to actually hit the "real" key.
However, not all programs are quite so understanding—or old, I guess.
With key overrides, one can send a real `TAB` whenever `C-i` is pressed;
no special convention on how to interpret certain key chords required!
I also rebound `C-m` to `RET` (with the same justification), and `S-BSP` to `DEL`.
This is one of those features that I didn't know I needed,
yet now couldn't live without anymore.
I'm definitely looking forward to discovering new and interesting ways of using this!
### [Autocorrect][qmk:autocorrect]
This is a quaint little feature: auto-correct inside of your keyboard's firmware!
I promise that it's not as bad as it sounds.
It does not work automatically, thankfully, but is based off a given list of replacements.
For example,
widht -> width
would fire anytime one writes `widht`, which then gets replaced by `width`.
This is based on (a trie of) the most recently pressed keys,
so whenever one actually wants to write `widht`
all that's needed is pressing, for example, any modifier during the insertion.
As I've really just been trying this out for a laugh, my current word list is quite short:
:alot -> a lot
accesories -> accessories
accomodate -> accommodate
alledge -> allege
In general,
I think the solution to stop misspelling a word is not to remap key sequences on the firmware level,
but to—you know—learn how to spell that word.
Still,
I can imagine at least one or two use-cases where something like this could be useful,
so I figured it might be nice to make people aware of this features' existence.
In addition—as I've found out on three separate occasions so far—using the words "auto-correct, but in firmware"
makes people stare in utter disbelief and/or disgust at your keyboard.
That alone makes this feature worth it.
### [Caps Word][qmk:caps-word]
Caps Word is a clever alternative to Caps Lock,
which I enable by pressing both Shift keys together.
After that,
all of the letter keys are shifted,
and `-` becomes `_`
until a different key (excluding common sense ones like backspace) is pressed.
This is very useful for, e.g.,
writing long constants,
as these tend to have capital names separated with underscores:
writing `BOTH_SHIFTS_TURNS_ON_CAPS_WORD` has never been easier!
One thing to note is that,
while layer switching works just fine in "Caps Word mode",
the [Tri Layer][qmk:tri-layer] feature does not seem to play nicely with it;
i.e., the mode gets disabled when switching to these layers.
This is also the reason why I have an explicit LOWER, RAISE, and ADJUST setup,
instead of just using Tri Layer.
One could fiddle with the `caps_word_press_user` callback,
but it seemed much easier to just create one additional layer toggle instead.
I haven't looked at how hard it would be to hack this into Caps Word,
so maybe this is a future pull request.
[CDLaTeX]: https://github.com/cdominik/cdlatex
[colemak-dh]: https://colemakmods.github.io/mod-dh/
[emacs:paredit]: https://paredit.org/
[emacs:puni]: https://github.com/AmaiKinono/puni
[qmk:autocorrect]: https://docs.qmk.fm/#/feature_autocorrect
[qmk:caps-word]: https://docs.qmk.fm/#/feature_caps_word
[qmk:key-overrides]: https://docs.qmk.fm/#/feature_key_overrides
[qmk:macros]: https://docs.qmk.fm/#/feature_macros
[qmk:mod-tap]: https://docs.qmk.fm/#/mod_tap
[qmk:repeat-key]: https://docs.qmk.fm/#/feature_repeat_key
[qmk:slotthe:tapdances]: https://github.com/slotThe/qmk_firmware/blob/keyboardio/atreus/slotThe/keyboards/keyboardio/atreus/keymaps/slotThe/keymap.c#L187
[qmk:tap-dance]: https://docs.qmk.fm/#/feature_tap_dance
[qmk:tri-layer]: https://docs.qmk.fm/#/feature_tri_layer
[x11:clipboard]: https://www.uninformativ.de/blog/postings/2017-04-02/0/POSTING-en.html

View File

@ -0,0 +1,9 @@
TAP_DANCE_ENABLE = yes
KEY_OVERRIDE_ENABLE = yes
AUTOCORRECT_ENABLE = yes
CAPS_WORD_ENABLE = yes
REPEAT_KEY_ENABLE = yes
LTO_ENABLE = yes
COMMAND_ENABLE = no
MOUSEKEY_ENABLE = no