Commit 2f43b485f146
Changed files (3)
keyboards
moonlander
keyboards/moonlander/config/config.h
@@ -31,6 +31,10 @@
// Numword configuration
#define NUMWORD_TIMEOUT 5000 // Time in ms before numword auto-disables (optional)
+// Leader key configuration
+#define LEADER_TIMEOUT 300 // Time in ms to wait for next key in leader sequence
+#define LEADER_PER_KEY_TIMING // Each key in sequence gets its own timeout
+
/* #define DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD 1 */
/* #define CAPS_WORD_INVERT_ON_SHIFT 1 */
keyboards/moonlander/config/keymap.c
@@ -71,12 +71,146 @@ const key_override_t *key_overrides[] = {
};
void leader_start_user(void) {
+ // Visual feedback when leader mode activates (optional)
}
void leader_end_user(void) {
- if (leader_sequence_one_key(KC_F)) {
- // Leader, f => Types the below string
- SEND_STRING("QMK is awesome.");
+ // ====== LAYOUT SWITCHING ======
+ // Leader + l + <key> for layout changes
+ if (leader_sequence_two_keys(KC_L, KC_B)) {
+ layer_move(BEPO);
+ } else if (leader_sequence_two_keys(KC_L, KC_E)) {
+ layer_move(ERGL);
+ } else if (leader_sequence_two_keys(KC_L, KC_Q)) {
+ layer_move(QWER);
+ }
+
+ // ====== DEVELOPMENT PATTERNS ======
+ // Leader + c + <key> for code snippets
+ else if (leader_sequence_two_keys(KC_C, KC_N)) {
+ SEND_STRING("nil");
+ } else if (leader_sequence_two_keys(KC_C, KC_E)) {
+ SEND_STRING("if err != nil {" SS_TAP(X_ENT) SS_TAP(X_TAB));
+ } else if (leader_sequence_two_keys(KC_C, KC_L)) {
+ SEND_STRING("console.log()");
+ SEND_STRING(SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_C, KC_P)) {
+ SEND_STRING("fmt.Println()");
+ SEND_STRING(SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_C, KC_F)) {
+ SEND_STRING("function() {}");
+ SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_C, KC_A)) {
+ SEND_STRING("() => {}");
+ SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ }
+
+ // ====== PERSONAL MACROS ======
+ // Leader + m + <key> for personal macros
+ else if (leader_sequence_two_keys(KC_M, KC_E)) {
+ SEND_STRING("vincent@sbr.pm"); // TODO: Update with your email
+ } else if (leader_sequence_two_keys(KC_M, KC_G)) {
+ SEND_STRING("Vincent Demeester <vincent@sbr.pm>"); // Git signature
+ } else if (leader_sequence_two_keys(KC_M, KC_S)) {
+ SEND_STRING("--" SS_TAP(X_ENT) "Vincent Demeester" SS_TAP(X_ENT) "vincent@sbr.pm");
+ } else if (leader_sequence_two_keys(KC_M, KC_T)) {
+ // ISO 8601 timestamp - you might want to use a more dynamic approach
+ SEND_STRING(SS_LCTL("u")); // This is a placeholder - QMK can't generate current date
+ }
+
+ // ====== PYTHON PATTERNS ======
+ // Leader + p + <key> for Python code snippets
+ else if (leader_sequence_two_keys(KC_P, KC_I)) {
+ SEND_STRING("if __name__ == \"__main__\":" SS_TAP(X_ENT) SS_TAP(X_TAB));
+ } else if (leader_sequence_two_keys(KC_P, KC_D)) {
+ SEND_STRING("def ():" SS_TAP(X_ENT) SS_TAP(X_TAB));
+ SEND_STRING(SS_TAP(X_UP) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_P, KC_C)) {
+ SEND_STRING("class :" SS_TAP(X_ENT) SS_TAP(X_TAB));
+ SEND_STRING(SS_TAP(X_UP) SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_P, KC_P)) {
+ SEND_STRING("print(f\"\")");
+ SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_P, KC_T)) {
+ SEND_STRING("try:" SS_TAP(X_ENT) SS_TAP(X_TAB));
+ SEND_STRING(SS_TAP(X_ENT) SS_LSFT(SS_TAP(X_TAB)) "except Exception as e:" SS_TAP(X_ENT) SS_TAP(X_TAB));
+ } else if (leader_sequence_two_keys(KC_P, KC_W)) {
+ SEND_STRING("with open(\"\", \"r\") as f:" SS_TAP(X_ENT) SS_TAP(X_TAB));
+ SEND_STRING(SS_TAP(X_UP) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ }
+
+ // ====== EMACS LISP PATTERNS ======
+ // Leader + e + <key> for Emacs Lisp snippets
+ else if (leader_sequence_two_keys(KC_E, KC_D)) {
+ SEND_STRING("(defun ()" SS_TAP(X_ENT));
+ SEND_STRING(SS_TAP(X_UP) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_E, KC_I)) {
+ SEND_STRING("(interactive)");
+ } else if (leader_sequence_two_keys(KC_E, KC_L)) {
+ SEND_STRING("(let ((");
+ } else if (leader_sequence_two_keys(KC_E, KC_S)) {
+ SEND_STRING("(setq )");
+ SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_E, KC_M)) {
+ SEND_STRING("(message \"\")");
+ SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_E, KC_R)) {
+ SEND_STRING("(require ')");
+ SEND_STRING(SS_TAP(X_LEFT));
+ }
+
+ // ====== NIX PATTERNS ======
+ // Leader + n + <key> for Nix snippets
+ else if (leader_sequence_two_keys(KC_N, KC_F)) {
+ SEND_STRING("{ pkgs, ... }:");
+ } else if (leader_sequence_two_keys(KC_N, KC_L)) {
+ SEND_STRING("let" SS_TAP(X_ENT) SS_TAP(X_TAB) SS_TAP(X_ENT) "in" SS_TAP(X_ENT));
+ SEND_STRING(SS_TAP(X_UP) SS_TAP(X_UP));
+ } else if (leader_sequence_two_keys(KC_N, KC_W)) {
+ SEND_STRING("with pkgs; [" SS_TAP(X_ENT) SS_TAP(X_TAB) SS_TAP(X_ENT) "]");
+ SEND_STRING(SS_TAP(X_UP));
+ } else if (leader_sequence_two_keys(KC_N, KC_I)) {
+ SEND_STRING("inherit ;");
+ SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_N, KC_B)) {
+ SEND_STRING("buildInputs = [ ];");
+ SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_N, KC_P)) {
+ SEND_STRING("pkgs.writeShellScriptBin \"\" ''");
+ SEND_STRING(SS_TAP(X_ENT) SS_TAP(X_TAB) SS_TAP(X_ENT) "''");
+ SEND_STRING(SS_TAP(X_UP) SS_TAP(X_UP) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ }
+
+ // ====== IMPORT PATTERNS ======
+ // Leader + i + <key> for common imports
+ else if (leader_sequence_two_keys(KC_I, KC_P)) {
+ SEND_STRING("import ");
+ } else if (leader_sequence_two_keys(KC_I, KC_F)) {
+ SEND_STRING("from import ");
+ SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT) SS_TAP(X_LEFT));
+ } else if (leader_sequence_two_keys(KC_I, KC_N)) {
+ SEND_STRING("{ pkgs }: {" SS_TAP(X_ENT) SS_TAP(X_TAB) SS_TAP(X_ENT) "}");
+ SEND_STRING(SS_TAP(X_UP));
+ } else if (leader_sequence_two_keys(KC_I, KC_E)) {
+ SEND_STRING("(use-package " SS_TAP(X_ENT) SS_TAP(X_TAB));
+ SEND_STRING(SS_TAP(X_UP) SS_TAP(X_END));
+ }
+
+ // ====== APPLICATION SHORTCUTS ======
+ // Leader + a + <key> for application launches
+ // These use the configured niri keybindings
+ else if (leader_sequence_two_keys(KC_A, KC_D)) {
+ SEND_STRING(SS_LGUI("d")); // Mod+D for fuzzel (app launcher)
+ } else if (leader_sequence_two_keys(KC_A, KC_E)) {
+ SEND_STRING(SS_LGUI(SS_LSFT(SS_TAP(X_ENT)))); // Mod+Shift+Enter for Emacs client
+ } else if (leader_sequence_two_keys(KC_A, KC_T)) {
+ SEND_STRING(SS_LGUI(SS_TAP(X_ENT))); // Mod+Enter for Terminal (kitty)
+ } else if (leader_sequence_two_keys(KC_A, KC_J)) {
+ SEND_STRING(SS_LGUI(SS_LCTL("d"))); // Mod+Control+D for emoji picker (rofimoji)
+ } else if (leader_sequence_two_keys(KC_A, KC_V)) {
+ SEND_STRING(SS_LGUI(SS_LCTL("v"))); // Mod+Control+V for clipboard history (cliphist)
+ } else if (leader_sequence_two_keys(KC_A, KC_R)) {
+ SEND_STRING(SS_LGUI(SS_LSFT("d"))); // Mod+Shift+D for raffi launcher
}
}
@@ -101,8 +235,8 @@ enum combos {
};
const uint16_t PROGMEM combo_to_bepo[] = {LT(NAVI,KC_BSPC), OS_LSFT, COMBO_END};
-const uint16_t PROGMEM combo_to_ergol[] = {LT(NUMB,KC_SPC), LT(SYMB, KC_ENT), COMBO_END};
-const uint16_t PROGMEM combo_to_qwerty[] = {KC_DEL, KC_RALT, COMBO_END};
+const uint16_t PROGMEM combo_to_ergol[] = {KC_Q, KC_P, COMBO_END}; // Q+P opposite corners
+const uint16_t PROGMEM combo_to_qwerty[] = {LT(NUMB,KC_SPC), LT(SYMB, KC_ENT), COMBO_END}; // Numb+Symb
const uint16_t PROGMEM combo_toggle_mouse[] = {KC_Q, KC_R, COMBO_END};
const uint16_t PROGMEM combo_bepo_escape[] = {HM_ALT_R, HM_GUI_N, COMBO_END};
@@ -119,7 +253,7 @@ const uint16_t PROGMEM combo_qwe_minus[] = {KC_W, HM_ALT_S, COMBO_END}; // -
const uint16_t PROGMEM combo_qwe_unds[] = {HM_CTL_F, KC_V, COMBO_END}; // _
const uint16_t PROGMEM combo_qwe_equal[] = {HM_ALT_S, KC_X, COMBO_END}; // =
-const uint16_t PROGMEM combo_qwe_leader[] = {HM_SFT_D, HM_CTL_F, COMBO_END}; // FIXME: change this most likely.
+const uint16_t PROGMEM combo_qwe_leader[] = {KC_DEL, KC_RALT, COMBO_END}; // Del+RAlt - right side thumb cluster, very deliberate
const uint16_t PROGMEM combo_qwe_lprn[] = {KC_I, HM_SFT_K, COMBO_END}; // (
const uint16_t PROGMEM combo_qwe_rprn[] = {HM_SFT_K, KC_COMM, COMBO_END}; // )
keyboards/moonlander/README.org
@@ -57,11 +57,90 @@
* Usage
-- *Layout switching*: Bépo (Nav+Shift), ErgoL (Num+Sym), QWERTY (Del+RAlt)
+- *Layout switching*: Bépo (Nav+Shift), ErgoL (Q+P), QWERTY (Numb+Symb), or via leader sequences
- *Numword*: Hold Space on Bépo layer (auto-disable after 5s)
-- *Leader*: Combo D+F on QWERTY
+- *Leader key*: Combo Del+RAlt (right thumb cluster, 300ms timeout per key)
- *Mouse toggle*: Combo Q+R
+** Leader Key Sequences
+
+The leader key is activated by pressing Del+RAlt simultaneously (right thumb cluster). After activation, you have 300ms to press each subsequent key in the sequence.
+
+*** Layout Switching (Leader + L + key)
+| Sequence | Action |
+|----------+----------------|
+| l b | Switch to Bépo |
+| l e | Switch to ErgoL|
+| l q | Switch to QWERTY|
+
+*** Development Patterns - General (Leader + C + key)
+| Sequence | Output | Notes |
+|----------+---------------------------+--------------------------------|
+| c n | nil | Go/common nil keyword |
+| c e | if err != nil {<enter><tab>| Go error handling pattern |
+| c l | console.log() | Cursor positioned inside () |
+| c p | fmt.Println() | Cursor positioned inside () |
+| c f | function() {} | Cursor positioned inside {} |
+| c a | () => {} | Arrow function, cursor inside {}|
+
+*** Development Patterns - Python (Leader + P + key)
+| Sequence | Output | Notes |
+|----------+---------------------------+--------------------------------|
+| p i | if __name__ == "__main__":| Python main block |
+| p d | def (): | Function definition, cursor at name |
+| p c | class : | Class definition, cursor at name |
+| p p | print(f"") | f-string print, cursor inside quotes |
+| p t | try:...except Exception as e: | Try-except block |
+| p w | with open("", "r") as f: | File context manager, cursor at path |
+
+*** Development Patterns - Emacs Lisp (Leader + E + key)
+| Sequence | Output | Notes |
+|----------+---------------------------+--------------------------------|
+| e d | (defun () | Function definition, cursor at name |
+| e i | (interactive) | Interactive declaration |
+| e l | (let (( | Let binding |
+| e s | (setq ) | Set variable, cursor at name |
+| e m | (message "") | Message output, cursor inside quotes |
+| e r | (require ') | Require package, cursor after quote |
+
+*** Development Patterns - Nix (Leader + N + key)
+| Sequence | Output | Notes |
+|----------+---------------------------+--------------------------------|
+| n f | { pkgs, ... }: | Nix function signature |
+| n l | let...in | Let expression, cursor in body |
+| n w | with pkgs; [...] | With statement, cursor in list |
+| n i | inherit ; | Inherit, cursor before semicolon |
+| n b | buildInputs = [ ]; | buildInputs, cursor in list |
+| n p | pkgs.writeShellScriptBin ""| Shell script, cursor at name |
+
+*** Import Patterns (Leader + I + key)
+| Sequence | Output | Notes |
+|----------+---------------------------+--------------------------------|
+| i p | import | Python simple import |
+| i f | from import | Python from import, cursor at module |
+| i n | { pkgs }: {...} | Nix module definition |
+| i e | (use-package | Emacs use-package declaration |
+
+*** Personal Macros (Leader + M + key)
+| Sequence | Output | Notes |
+|----------+-------------------------------------+------------------------|
+| m e | vincent@sbr.pm | Email address |
+| m g | Vincent Demeester <vincent@sbr.pm> | Git signature format |
+| m s | --<enter>Vincent Demeester<enter>...| Email signature |
+| m t | <Ctrl+U> | Timestamp placeholder |
+
+*** Application Shortcuts (Leader + A + key)
+| Sequence | Keybind | Action |
+|----------+-------------------+--------------------------------|
+| a d | Mod+D | Launch fuzzel app launcher |
+| a e | Mod+Shift+Enter | Launch Emacs client |
+| a t | Mod+Enter | Launch Terminal (kitty) |
+| a j | Mod+Control+D | Emoji picker (rofimoji) |
+| a v | Mod+Control+V | Clipboard history (cliphist) |
+| a r | Mod+Shift+D | Raffi launcher |
+
+*Note*: These shortcuts match your niri window manager configuration.
+
* Development
Files: =config/{config.h, keymap.c, layermodes.{c,h}, rules.mk}=, =go.sh=