[Erez & Jack] Packages Space Cadet shifts into keycodes
This commit is contained in:
parent
f4a426a0b1
commit
1237025963
6 changed files with 65 additions and 98 deletions
62
README.md
62
README.md
|
@ -118,6 +118,20 @@ We've added shortcuts to make common modifier/tap (mod-tap) mappings more compac
|
||||||
* `LCAG_T(kc)` - is CtrlAltGui when held and *kc* when tapped
|
* `LCAG_T(kc)` - is CtrlAltGui when held and *kc* when tapped
|
||||||
* `MEH_T(kc)` - is like Hyper, but not as cool -- does not include the Cmd/Win key, so just sends Alt+Ctrl+Shift.
|
* `MEH_T(kc)` - is like Hyper, but not as cool -- does not include the Cmd/Win key, so just sends Alt+Ctrl+Shift.
|
||||||
|
|
||||||
|
### Space Cadet Shift: The future, built in
|
||||||
|
|
||||||
|
Steve Losh [described](http://stevelosh.com/blog/2012/10/a-modern-space-cadet/) the Space Cadet Shift quite well. Essentially, you hit the left Shift on its own, and you get an opening parenthesis; hit the right Shift on its own, and you get the closing one. When hit with other keys, the Shift key keeps working as it always does. Yes, it's as cool as it sounds.
|
||||||
|
|
||||||
|
To use it, use `KC_LSPO` (Left Shift, Parens Open) for your left Shift on your keymap, and `KC_RSPC` (Right Shift, Parens Close) for your right Shift.
|
||||||
|
|
||||||
|
The only other thing you're going to want to do is create a `makefile.mk` in your keymap directory and set the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
COMMAND_ENABLE = no # Commands for debug and configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
This is just to keep the keyboard from going into command mode when you hold both Shift keys at the same time.
|
||||||
|
|
||||||
### The Leader key: A new kind of modifier
|
### The Leader key: A new kind of modifier
|
||||||
|
|
||||||
If you've ever used Vim, you know what a Leader key is. If not, you're about to discover a wonderful concept. :) Instead of hitting Alt+Shift+W for example (holding down three keys at the same time), what if you could hit a _sequence_ of keys instead? So you'd hit our special modifier (the Leader key), followed by W and then C (just a rapid succession of keys), and something would happen.
|
If you've ever used Vim, you know what a Leader key is. If not, you're about to discover a wonderful concept. :) Instead of hitting Alt+Shift+W for example (holding down three keys at the same time), what if you could hit a _sequence_ of keys instead? So you'd hit our special modifier (the Leader key), followed by W and then C (just a rapid succession of keys), and something would happen.
|
||||||
|
@ -296,7 +310,7 @@ if (timer_elapsed(key_timer) < 100) {
|
||||||
|
|
||||||
It's best to declare the `static uint16_t key_timer;` outside of the macro block (top of file, etc).
|
It's best to declare the `static uint16_t key_timer;` outside of the macro block (top of file, etc).
|
||||||
|
|
||||||
#### Example 1: Single-key copy/paste (hold to copy, tap to paste)
|
#### Example: Single-key copy/paste (hold to copy, tap to paste)
|
||||||
|
|
||||||
With QMK, it's easy to make one key do two things, as long as one of those things is being a modifier. :) So if you want a key to act as Ctrl when held and send the letter R when tapped, that's easy: `CTL_T(KC_R)`. But what do you do when you want that key to send Ctrl-V (paste) when tapped, and Ctrl-C (copy) when held?
|
With QMK, it's easy to make one key do two things, as long as one of those things is being a modifier. :) So if you want a key to act as Ctrl when held and send the letter R when tapped, that's easy: `CTL_T(KC_R)`. But what do you do when you want that key to send Ctrl-V (paste) when tapped, and Ctrl-C (copy) when held?
|
||||||
|
|
||||||
|
@ -330,52 +344,6 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||||
|
|
||||||
And then, to assign this macro to a key on your keyboard layout, you just use `M(0)` on the key you want to press for copy/paste.
|
And then, to assign this macro to a key on your keyboard layout, you just use `M(0)` on the key you want to press for copy/paste.
|
||||||
|
|
||||||
#### Example 2: Space Cadet Shift (making it easy to send opening and closing parentheses)
|
|
||||||
|
|
||||||
In the [Modern Space Cadet Keyboard](http://stevelosh.com/blog/2012/10/a-modern-space-cadet/#shift-parentheses), one of cooler features is the Shift Parentheses. To quote Steve Losh:
|
|
||||||
|
|
||||||
> When held while pressing other keys, act like Shift.
|
|
||||||
> When pressed and released on their own, type an opening or closing parenthesis (left and right shift respectively).
|
|
||||||
|
|
||||||
```
|
|
||||||
static uint16_t key_timer;
|
|
||||||
|
|
||||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
|
||||||
{
|
|
||||||
switch(id) {
|
|
||||||
case 0: {
|
|
||||||
if (record->event.pressed) {
|
|
||||||
key_timer = timer_read(); // if the key is being pressed, we start the timer.
|
|
||||||
register_code(KC_LSFT); // we're now holding down Shift.
|
|
||||||
} else { // this means the key was just released, so we can figure out how long it was pressed for (tap or "held down").
|
|
||||||
if (timer_elapsed(key_timer) < 150) { // 150 being 150ms, the threshhold we pick for counting something as a tap.
|
|
||||||
register_code(KC_9); // sending 9 while Shift is held down gives us an opening paren
|
|
||||||
unregister_code(KC_9); // now let's let go of that key
|
|
||||||
}
|
|
||||||
unregister_code(KC_LSFT); // let's release the Shift key now.
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
if (record->event.pressed) {
|
|
||||||
key_timer = timer_read(); // Now we're doing the same thing, only for the right shift/close paren key
|
|
||||||
register_code(KC_RSFT);
|
|
||||||
} else {
|
|
||||||
if (timer_elapsed(key_timer) < 150) {
|
|
||||||
register_code(KC_0);
|
|
||||||
unregister_code(KC_0);
|
|
||||||
}
|
|
||||||
unregister_code(KC_RSFT);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MACRO_NONE;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
And then, to assign this macro to a key on your keyboard layout, you just use `M(0)` on the key you want to press for left shift/opening parens, and `M(1)` for right shift/closing parens.
|
|
||||||
|
|
||||||
## Additional keycode aliases for software-implemented layouts (Colemak, Dvorak, etc)
|
## Additional keycode aliases for software-implemented layouts (Colemak, Dvorak, etc)
|
||||||
|
|
||||||
Everything is assuming you're in Qwerty (in software) by default, but there is built-in support for using a Colemak or Dvorak layout by including this at the top of your keymap:
|
Everything is assuming you're in Qwerty (in software) by default, but there is built-in support for using a Colemak or Dvorak layout by including this at the top of your keymap:
|
||||||
|
|
Binary file not shown.
|
@ -7,8 +7,6 @@
|
||||||
#define SYMB 1 // symbols
|
#define SYMB 1 // symbols
|
||||||
#define MDIA 2 // media keys
|
#define MDIA 2 // media keys
|
||||||
|
|
||||||
#define LSFTO M(0) // Left shift, open parens when tapped
|
|
||||||
#define RSFTC M(1) // Right shift, close parens when tapped
|
|
||||||
#define LEADER_TIMEOUT 300
|
#define LEADER_TIMEOUT 300
|
||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
@ -40,7 +38,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
|
KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
|
||||||
KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
|
KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
|
||||||
KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
|
KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
|
||||||
LSFTO, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_LBRC),
|
KC_LSPO, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_LBRC),
|
||||||
LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
|
LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
|
||||||
ALT_T(KC_APP), KC_LGUI,
|
ALT_T(KC_APP), KC_LGUI,
|
||||||
KC_HOME,
|
KC_HOME,
|
||||||
|
@ -49,7 +47,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
KC_RGHT, KC_6,KC_7, KC_8, KC_9, KC_0, KC_MINS,
|
KC_RGHT, KC_6,KC_7, KC_8, KC_9, KC_0, KC_MINS,
|
||||||
TG(SYMB), KC_Y,KC_U, KC_I, KC_O, KC_P, KC_BSLS,
|
TG(SYMB), KC_Y,KC_U, KC_I, KC_O, KC_P, KC_BSLS,
|
||||||
KC_H,ALT_T(KC_J),KC_K, KC_L, LT(MDIA,KC_SCLN),GUI_T(KC_QUOT),
|
KC_H,ALT_T(KC_J),KC_K, KC_L, LT(MDIA,KC_SCLN),GUI_T(KC_QUOT),
|
||||||
MEH_T(KC_RBRC),KC_N,KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), RSFTC,
|
MEH_T(KC_RBRC),KC_N,KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSPC,
|
||||||
KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, LT(SYMB,KC_MINS),
|
KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, LT(SYMB,KC_MINS),
|
||||||
KC_LALT, CTL_T(KC_ESC),
|
KC_LALT, CTL_T(KC_ESC),
|
||||||
KC_PGUP,
|
KC_PGUP,
|
||||||
|
@ -150,48 +148,7 @@ static uint16_t key_timer;
|
||||||
|
|
||||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||||
{
|
{
|
||||||
switch(id) {
|
return MACRO_NONE;
|
||||||
case 0:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
register_mods(MOD_BIT(KC_LSFT));
|
|
||||||
if (record->tap.count && !record->tap.interrupted) {
|
|
||||||
register_code(KC_9);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
record->tap.count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (record->tap.count) {
|
|
||||||
unregister_code(KC_9);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
}
|
|
||||||
unregister_mods(MOD_BIT(KC_LSFT));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
if (record->event.pressed) {
|
|
||||||
register_mods(MOD_BIT(KC_LSFT));
|
|
||||||
if (record->tap.count && !record->tap.interrupted) {
|
|
||||||
register_code(KC_0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
record->tap.count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (record->tap.count) {
|
|
||||||
unregister_code(KC_0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
}
|
|
||||||
unregister_mods(MOD_BIT(KC_LSFT));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return MACRO_NONE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Runs just one time when the keyboard initializes.
|
// Runs just one time when the keyboard initializes.
|
||||||
|
@ -242,7 +199,5 @@ void matrix_scan_user(void) {
|
||||||
unregister_code(KC_LCTL);
|
unregister_code(KC_LCTL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
# for your own particular keymap
|
# for your own particular keymap
|
||||||
|
|
||||||
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
||||||
|
COMMAND_ENABLE = no # Commands for debug and configuration
|
||||||
|
|
|
@ -240,6 +240,8 @@ extern const uint16_t fn_actions[];
|
||||||
#define BL_TOGG 0x5082
|
#define BL_TOGG 0x5082
|
||||||
#define BL_STEP 0x5083
|
#define BL_STEP 0x5083
|
||||||
|
|
||||||
|
#define KC_LSPO 0x5084 // Left shift, open parens when tapped
|
||||||
|
#define KC_RSPC 0x5085 // Right shift, close parens when tapped
|
||||||
// GOTO layer - 16 layers max
|
// GOTO layer - 16 layers max
|
||||||
// when:
|
// when:
|
||||||
// ON_PRESS = 1
|
// ON_PRESS = 1
|
||||||
|
|
|
@ -21,6 +21,7 @@ void leader_end(void) {}
|
||||||
uint8_t starting_note = 0x0C;
|
uint8_t starting_note = 0x0C;
|
||||||
int offset = 7;
|
int offset = 7;
|
||||||
|
|
||||||
|
|
||||||
#ifdef AUDIO_ENABLE
|
#ifdef AUDIO_ENABLE
|
||||||
bool music_activated = false;
|
bool music_activated = false;
|
||||||
|
|
||||||
|
@ -59,6 +60,8 @@ uint8_t chord_key_down = 0;
|
||||||
static uint8_t input_mode;
|
static uint8_t input_mode;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool shift_interrupted[] = {0, 0, 0};
|
||||||
|
|
||||||
bool keys_chord(uint8_t keys[]) {
|
bool keys_chord(uint8_t keys[]) {
|
||||||
uint8_t keys_size = sizeof(keys)/sizeof(keys[0]);
|
uint8_t keys_size = sizeof(keys)/sizeof(keys[0]);
|
||||||
bool pass = true;
|
bool pass = true;
|
||||||
|
@ -415,6 +418,45 @@ bool process_record_quantum(keyrecord_t *record) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
switch(keycode) {
|
||||||
|
case KC_LSPO: {
|
||||||
|
if (record->event.pressed) {
|
||||||
|
shift_interrupted[0] = false;
|
||||||
|
register_mods(MOD_BIT(KC_LSFT));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!shift_interrupted[0]) {
|
||||||
|
register_code(KC_9);
|
||||||
|
unregister_code(KC_9);
|
||||||
|
}
|
||||||
|
unregister_mods(MOD_BIT(KC_LSFT));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case KC_RSPC: {
|
||||||
|
if (record->event.pressed) {
|
||||||
|
shift_interrupted[1] = false;
|
||||||
|
register_mods(MOD_BIT(KC_RSFT));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!shift_interrupted[1]) {
|
||||||
|
register_code(KC_0);
|
||||||
|
unregister_code(KC_0);
|
||||||
|
}
|
||||||
|
unregister_mods(MOD_BIT(KC_RSFT));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
shift_interrupted[0] = true;
|
||||||
|
shift_interrupted[1] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return process_action_kb(record);
|
return process_action_kb(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,4 +523,4 @@ void audio_on_user() {}
|
||||||
__attribute__ ((weak))
|
__attribute__ ((weak))
|
||||||
void music_scale_user() {}
|
void music_scale_user() {}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue