Karabiner

User avatar
Muirium
µ

23 Mar 2021, 12:52

Dr. Strangemod
Or: How I Learned To Stop Worrying And Love Karabiner

So, back in November, I hurried on down to Apple Princes Street and picked up an M1 MacBook Air on launch day. (16 gigs / 1 TB / space grey, obviously.) Nifty wee machine. Blew my 2013 MacBook Pro out the water, naturally, all while both eerily quiet and downright supernaturally cool. The legends… they're all true?

Well anyway, I got it in Apple's UK keyboard layout because I didn't want to wait—another lockdown was just days away—and I could always use their extended new year return period if the layout drove me nuts. See, I'm used to ANSI. How hard could going back to ISO be?

This is what I'm used to on my laptop:

MacBook Air US keyboard 0012_hardware-hero-pt-open-spgry_lg copy.jpg
MacBook Air US keyboard 0012_hardware-hero-pt-open-spgry_lg copy.jpg (199.63 KiB) Viewed 991 times

Apple's UK images still show American layout. But the layout over here is Apple's ISO style. The same as above, but with their skinny-assed Return key, the ever curious § key up above Tab and tilde tucked down by small left Shift, like this:

MLA22B.jpeg
MLA22B.jpeg (163.09 KiB) Viewed 991 times

One thing their ISO keyboards do have going for them: icon mods. I do like these! Much more stylish than having things like "delete" spelled out on the keys. (That's Backspace you dimwits!) They're a throwback to my 12" PowerBook, only higher contrast and backlit. Indeed, my distant familiarity with this layout started giving me ideas…

Apple-PowerBook-G4-12-inch_4.jpg
Apple-PowerBook-G4-12-inch_4.jpg (48.59 KiB) Viewed 991 times

As far as laptops go, the Air's keyboard is obviously much better than those from the horrific "Butterfly" era. Minimal keyfeel aside—thump-thump-thump—those butterfly laptops were aptly named when it came to reliability, so I skipped them entirely. The relevant comparison for me was with my 7 year old 15" MacBook Pro. I like these new ones much more than Apple's previous scissor-switch. They're less 'floppy', they've got tighter tolerances, and while they'll win no contests with Topre and all the other real keyboards I love, they're passable for a slim laptop, and just as reliable.

But this Apple/ISO layout keeps reminding me of my 2003 PowerBook, my first Mac. The old PowerBook's keyboard is sculpted—I still prefer the key shape to all these chiclets since—and has a lot more travel. But here's the oddball: back in those days, Mac laptops had an Enter key over to the right of the spacebar. I found myself hitting right Option when completing File > Save dialogs and the like. That old muscle memory was flowing back!

Alright already Mu, what's all this got to do with Karabiner?

Let's reprogram this thing!

I'm used to programmable keyboards. Soarer's, TMK in my HHKB, QMK in my Kishy. After hitting that accursed ` key when reaching for left Shift for the hundredth goddamn time, I knew this built in keyboard was in sore need of some modding. It was time for me to make my peace with Karabiner.

Usually, I do all my key-swapping in the keyboards themselves. MacOS does have some minimal functionality—you can reorder the modifiers on individual keyboards—but nothing like as complimacated as I was looking for:

Sys Prefs > Modifier Keys.jpg
Sys Prefs > Modifier Keys.jpg (70.98 KiB) Viewed 991 times
So, here's what I've gotten up to in Karabiner. It's complex!

Karabiner > Complex Mods.jpg
Karabiner > Complex Mods.jpg (128.31 KiB) Viewed 991 times
Karabiner calls simple key-swaps "simple modifications". You can do quite a bit with just those. But I'm a special flower, always…

Karabiner's also got a library of ready made "complex modifications" but even these weren't sufficiently complex for µ. So I rolled up my sleeves and cooked up my own in JSON. Karabiner's rule format is… clunky, but powerful. It did allow me to do quite a lot of trickery indeed, including all my usual staples like Shift + Shift > Caps Lock, and more besides.

For anyone interested, my rules come in 3 varieties, in 3 different files. First: the General Complex Rules which apply to all keyboards, including my laptop's own:

Code: Select all

{
	"title": "General Complex Rules",
	"rules": [
	    {
	        "description": "Shift + Shift ⇨ Caps Lock",
	        "manipulators": [
	            {
	                "from": {
	                    "key_code": "left_shift",
	                    "modifiers": {
	                        "mandatory": [
	                            "right_shift"
	                        ],
	                        "optional": [
	                            "any"
	                        ]
	                    }
	                },
	                "to": [
	                    {
	                        "key_code": "caps_lock"
	                    }
	                ],
	                "type": "basic"
	            },
	            {
	                "from": {
	                    "key_code": "right_shift",
	                    "modifiers": {
	                        "mandatory": [
	                            "left_shift"
	                        ],
	                        "optional": [
	                            "any"
	                        ]
	                    }
	                },
	                "to": [
	                    {
	                        "key_code": "caps_lock"
	                    }
	                ],
	                "type": "basic"
	            }
	        ]
	    },
	    {
	        "description": "Shift + Backspace ⇨ Delete",
	        "manipulators": [
	            {
	            	"conditions": [
						{
							"type": "frontmost_application_if",
							"bundle_identifiers": [
								"com.apple.finder"
							]
						}
					],
	                "from": {
	                    "key_code": "delete_or_backspace",
	                    "modifiers": {
	                        "mandatory": [
	                            "shift"
	                        ],
	                        "optional": [
	                            "option"
	                        ]
	                    }
	                },
	                "to": [
	                    {
	                        "key_code": "delete_forward"
	                    }
	                ],
	                "type": "basic"
	            },
	         	{
					"conditions": [
						{
							"type": "frontmost_application_unless",
							"bundle_identifiers": [
								"com.apple.finder"
							]
						}
					],
	                "from": {
	                    "key_code": "delete_or_backspace",
	                    "modifiers": {
	                        "mandatory": [
	                            "shift"
	                        ],
	                        "optional": [
	                            "any"
	                        ]
	                    }
	                },
	                "to": [
	                    {
	                        "key_code": "delete_forward"
	                    }
	                ],
	                "type": "basic"
	            }

	        ]
	    },
	    {
	        "description": "Right Option alone ⇨ 🗣 Enter",
	        "manipulators": [
	        {
	            "type": "basic",
	            "from": {
	                "key_code": "right_option"
	            },
	            "to": [
					{
						"key_code": "right_option"
					}
				],
	            "to_if_alone": [
	                {
	                    "key_code": "keypad_enter"
	                }
	            ]
	        },
	    	{
				"from": {
					"key_code": "right_option",
					"modifiers": {
						"mandatory": [
							"right_command"
						]
					}
				},
				"to": [
					{
						"key_code": "s",
						"modifiers": [
							"right_command",
							"right_control"
						],
						"repeat": true
					}
				],
				"type": "basic"
			}
	        ]
	    },
		{
			"description": "Fine Volume: Command ± 🔉  ⇨ Shift + Option ± 🔉",
			"manipulators": [
				{
					"from": {
						"key_code": "f11",
						"modifiers": {
							"mandatory": ["command"]
						}
					},
					"to": [
							{
								"key_code": "volume_decrement",
								"modifiers": [
									"left_shift",
									"left_alt"
								],
								"repeat": true
							}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f12",
						"modifiers": {
							"mandatory": ["command"]
						}
					},
					"to": [
						{
							"key_code": "volume_increment",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				}
			]
		},
		{
			"description": "Fine Brightness: Command ± 🔅  ⇨ Shift + Option ± 🔅",
			"manipulators": [
				{
					"from": {
						"key_code": "f1",
						"modifiers": {
							"mandatory": [
								"command"
							]
						}
					},
					"to": [
						{
							"key_code": "display_brightness_decrement",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f2",
						"modifiers": {
							"mandatory": [
								"command"
							]
						}
					},
					"to": [
						{
							"key_code": "display_brightness_increment",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				}
			]
		},
		{
			"description": "Contrast: Control ± 🔅  ⇨ Control + Option + Command ± .",
			"manipulators": [
				{
					"from": {
						"key_code": "f1",
						"modifiers": {
							"mandatory": [
								"control"
							]
						}
					},
					"to": [
						{
							"key_code": "period",
							"modifiers": [
								"left_control",
								"left_option",
								"left_command"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f2",
						"modifiers": {
							"mandatory": [
								"control"
							]
						}
					},
					"to": [
						{
							"key_code": "comma",
							"modifiers": [
								"left_control",
								"left_option",
								"left_command"
							],
							"repeat": true
						}
					],
					"type": "basic"
				}
			]
		}
	]
}
I've given them graphic looking names, to make them easier to pick out in the GUI.

What I've done here is give the right Option (Alt) key a second purpose as a (Numpad) Enter key, which I've gotten back into using as a quickly reachable confirm key. And, on top of that, I've also given it the 🗣 screen reader combo, as I used to have it set on my PowerBook. Yes, I like my computers talking to me! Well, it's a good way to hear typos in what I write. Those two keys make a great roll combo that I've missed for a decade. Now it's back!

Shift + Shift > Caps Lock, always. And Shift + Backspace for (forward) Delete is just as natural, too. I've gotten used to both of these from my programmable keyboards.

Oh, and I've made the shortcuts for fine brightness and volume control much more natural. Contrast is a handy thing to tweak sometimes too.

Here's the Built in Keyboard specific rules, just for my laptop's own keys:

Code: Select all

{
	"title": "Built in Keyboard Rules",
	"type": "device_if",
	"rules": [
		{
	        "description": "Built in Keyboard: Caps Lock ⇨ Right Control",
	        "manipulators": [
	        {
	         	"conditions": [
          		  {
				  "type": "device_if",
				  "identifiers": [
					{
					  "vendor_id": 1452,
					  "product_id": 641
					}
				  ]
            }
          ],
	            "from": {
                	"key_code": "caps_lock",
                    "modifiers": {
                    	"optional": ["any"]
                    }
                },
                "to": [
                    {
    	                "key_code": "right_control"
                    }
                    ],
                    "type": "basic"
                }
	        ]
	    },
	    {
	    	"description": "Built in Keyboard: Transform § ⇨ Backtick (Fn to override)",
	        "manipulators": [
	    	{
	         	"conditions": [
          		  {
				  "type": "device_if",
				  "identifiers": [
					{
					  "vendor_id": 1452,
					  "product_id": 641
					}
				  ]
            }
          ],
	            "type": "basic",
	            "from": {
	                "key_code": "non_us_backslash",
	                "modifiers": {
	                	"mandatory": ["fn"],
	                	"optional": ["any"]
	                }
	            },
	            "to": [
	                {
	                    "key_code": "non_us_backslash"
	                }
	            ]
	        },
	        {
	            "type": "basic",
	            "from": {
	                "key_code": "non_us_backslash",
	                "modifiers": {
	                	"optional": ["any"]
	                }
	            },
	            "to": [
	                {
	                    "key_code": "grave_accent_and_tilde"
	                }
	            ]
	        }
	    	]
	    },
	    {
	        "description": "Built in Keyboard: Backtick ⇨ Right Shift or Backtick when alone",
	        "manipulators": [
	        {
	         	"conditions": [
          		  {
				  "type": "device_if",
				  "identifiers": [
					{
					  "vendor_id": 1452,
					  "product_id": 641
					}
				  ]
            }
          ],
	            "type": "basic",
	            "from": {
	                "key_code": "grave_accent_and_tilde",
	                "modifiers": {
	                    "optional": ["any"]
	                }
	            },
	            "to": [
	                {
	                    "key_code": "right_shift",
	                    "lazy": true
	                }
	            ],
	            "to_if_alone": [
	                {
	                    "key_code": "grave_accent_and_tilde"
	                }
	            ]
	        }
	        ]
	    },
	    {
            "description": "Built in Keyboard: ❌ Backslash ⇨ Return or Backslash with Right Option",
            "manipulators": [
                {
	         	"conditions": [
          		  {
				  "type": "device_if",
				  "identifiers": [
					{
					  "vendor_id": 1452,
					  "product_id": 641
					}
				  ]
            }
          ],
                    "from": {
                        "key_code": "backslash",
                        "modifiers": {
                            "mandatory": [
                                "right_option"
                            ],
                            "optional": [
                                 "any"
                            ]
                        }
                    },
                    "to": [
                        {
                            "key_code": "backslash"
                        }
                    ],
                    "type": "basic"
                },
                {
                    "from": {
                        "key_code": "backslash",
                        "modifiers": {
                            "optional": [
                                 "any"
                            ]
                        }
                    },
                    "to": [
                        {
                            "key_code": "return_or_enter"
                        }
                    ],
                    "type": "basic"
                }
            ]
        }
	]
}
These are the fiddly special-case crew. Note the device_if all over the place. I tried making that a condition for the whole lot, but Karabiner really wants it per rule. (I asked!)

I didn't want to lose ISO's extra key, but I did want to use it as left Shift whenever I mistakenly reach for it, tucked away down there where Shift alone should be. The rule here neatly transforms ` to left Shift on the fly, whenever it's pressed in combination with other keys. Otherwise, it works like normal: ````. See!

I'm used to ` being up top, left of 1, so I put it up there too. It's really useful for typing gràvè àccènts and for Command + ` window cycling. But I can reclaim the §/± key by throwing Fn at it when I want. Complex rules are pretty sweet!

One of these rules is inactive: "Built in Keyboard: ❌ Backslash ⇨ Return or Backslash with Right Option". The big red cross in its name is a note to self, seeing as there's no comments allowed in JSON. I did try this one initially, but my fingers are adapting back to skinny assed ISO Return now, so the extension into \ is more trouble than it's worth. I'll delete it eventually.

And finally a numpad layer to match my SSK, Realforce and indeed the PowerBook:

Code: Select all

{
	"title": "🔢 Numpad Layer",
	"rules":
	[
		{
			"description": "🔢 Hold Fn + I square keys ⇨ 🔢 Numpad",
			"manipulators": [
				{
				"type": "basic",
					"from": {
						"key_code": "j",
						"modifiers": {
							"mandatory": ["fn"]
						}
					},
					"to": [
					{
						"key_code": "keypad_1"
					}
					]
				},
				{
				"type": "basic",
					"from": {
						"key_code": "k",
						"modifiers": {
							"mandatory": ["fn"]
						}
					},
					"to": [
						{
							"key_code": "keypad_2"
						}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "l",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_3"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "u",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_4"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "i",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_5"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "o",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_6"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "7",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_7"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "8",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_8"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "9",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_9"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "0",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_0"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "m",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_0"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "comma",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_0"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "period",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_period"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "hyphen",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_hyphen"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "equal_sign",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_plus"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "slash",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_slash"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "semicolon",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_asterisk"
					}
					]
				},
				{
				"type": "basic",
					"from": {
					"key_code": "return_or_enter",
					"modifiers": {
						"mandatory": [
							"fn"
						]
					}
					},
					"to": [
					{
						"key_code": "keypad_enter"
					}
					]
				}
			]
		},
		{
			"description": "🔢 Insert or  Option + Command + Command + Option ⇨ Toggle Numpad Layer",
			"manipulators": [
				{
					"from": {
						"key_code": "insert",
						"modifiers": {
							"optional": ["any"]
							}
					},
					"type": "basic",
					"to": {
						"set_variable": {
							"name": "numeric_keypad_mode",
							"value": 1
						}
					},
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 0
						}
					]
				},
				{
					"from": {
						"key_code": "insert",
						"modifiers": {
							"optional": ["any"]
							}
					},
					"type": "basic",
					"to": {
						"set_variable": {
							"name": "numeric_keypad_mode",
							"value": 0
						}
					},
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"from": {
						"key_code": "right_option",
						"modifiers": {
							"mandatory": ["left_option",
										  "left_command",
										  "right_command"]
						}
					},
					"type": "basic",
					"to": {
						"set_variable": {
							"name": "numeric_keypad_mode",
							"value": 1
						}
					},
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 0
						}
					]
				},
				{
					"from": {
						"key_code": "right_option",
						"modifiers": {
							"mandatory": ["left_option",
										  "left_command",
										  "right_command"]
						}
					},
					"type": "basic",
					"to": {
						"set_variable": {
							"name": "numeric_keypad_mode",
							"value": 0
						}
					},
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "j"
					},
					"to": [
						{
							"key_code": "keypad_1"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "k"
					},
					"to": [
						{
							"key_code": "keypad_2"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "l"
					},
					"to": [
						{
							"key_code": "keypad_3"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "u"
					},
					"to": [
						{
							"key_code": "keypad_4"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "i"
					},
					"to": [
						{
							"key_code": "keypad_5"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "o"
					},
					"to": [
						{
							"key_code": "keypad_6"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "7"
					},
					"to": [
						{
							"key_code": "keypad_7"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "8"
					},
					"to": [
						{
							"key_code": "keypad_8"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "9"
					},
					"to": [
						{
							"key_code": "keypad_9"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "0"
					},
					"to": [
						{
							"key_code": "keypad_0"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "m"
					},
					"to": [
						{
							"key_code": "keypad_0"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "comma"
					},
					"to": [
						{
							"key_code": "keypad_0"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "period"
					},
					"to": [
						{
							"key_code": "keypad_period"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "hyphen"
					},
					"to": [
						{
							"key_code": "keypad_hyphen"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "equal_sign"
					},
					"to": [
						{
							"key_code": "keypad_plus"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "slash"
					},
					"to": [
						{
							"key_code": "keypad_slash"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "semicolon"
					},
					"to": [
						{
							"key_code": "keypad_asterisk"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "return_or_enter"
					},
					"to": [
						{
							"key_code": "keypad_enter"
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "numeric_keypad_mode",
							"value": 1
						}
					]
				}
			]
		}
	]
}
These ones are extra complex, as they store state. That's what all the variable_if stuff is about. It is essentially a soft numlock, as the Mac has no such mode.

Something I'm still not settled on is the perfect "Num Lock" toggle key. I've thrown it on Insert for my external keyboards, just because they all have that (they're mostly TKLs) and it's easily found. On my Mac's built in keyboard, however, it's a trickier call. I put it on Option + Option for a while, but acc5denta3 presses are rea33y q45te d5sr4pt5ve0, so I hid it behind a bigger combo I'm less likely to trigger falsely. Guess my fingers are lazier on those mods than I think!

Anyway, a few months into having this Air now, and I'm well pleased. Karabiner's patched this pretty wee keyboard to the point it mostly stays off my tits—what a relief!—and my external keyboards are all getting some new tricks now too. I haven't even started using app-specific logic yet, something only a host-run software like Karabiner can even dream to do. That vortex awaits me, should I dare.

(If you want to complain about my sloppy, inconsistent formatting, feel free. I am not a programmer! This JSON stuff is all new to me, and I did a lot of trial and copypasta. That's a spicy meatball!)
Last edited by Muirium on 27 Apr 2021, 10:35, edited 2 times in total.

User avatar
XMIT
[ XMIT ]

23 Mar 2021, 13:17

Great write up Mu. I am all for Karabiner on the macOS. I did a deep dive a while ago when working with a vendor to develop a Mac specific keyboard. The Apple keyboard driver stack is a weird thing, giving preferential treatment to keyboards with an Apple dev ID. Karabiner has an actual kernel module and is the best - possibly only - way to do complex mods on the Mac.

Think of it as a Soarer’s Converter running on your Mac. :)

User avatar
Muirium
µ

24 Mar 2021, 09:46

Thanks.

I’m usually one for running stock, as best I can. But Apple’s oh so pretty ISO UK was just bugging me too much. ‘who’s idea was it to shorten ‘shift of all keys in the first place/ ‘bloody maddening1 ‘what the actual duck/ Image

ISO and me aren’t exactly close friends, but Karabiner helps us make do together. And once I got used to that, I embraced its fruity powers.

User avatar
Muirium
µ

27 Apr 2021, 10:11

Update to Shift + Backspace ⇨ Delete rule:

Code: Select all

	    {
	        "description": "Shift + Backspace ⇨ Delete",
	        "manipulators": [
	            {
	            	"conditions": [
						{
							"type": "frontmost_application_if",
							"bundle_identifiers": [
								"com.apple.finder"
							]
						}
					],
	                "from": {
	                    "key_code": "delete_or_backspace",
	                    "modifiers": {
	                        "mandatory": [
	                            "shift"
	                        ],
	                        "optional": [
	                            "option"
	                        ]
	                    }
	                },
	                "to": [
	                    {
	                        "key_code": "delete_forward"
	                    }
	                ],
	                "type": "basic"
	            },
	         	{
					"conditions": [
						{
							"type": "frontmost_application_unless",
							"bundle_identifiers": [
								"com.apple.finder"
							]
						}
					],
	                "from": {
	                    "key_code": "delete_or_backspace",
	                    "modifiers": {
	                        "mandatory": [
	                            "shift"
	                        ],
	                        "optional": [
	                            "any"
	                        ]
	                    }
	                },
	                "to": [
	                    {
	                        "key_code": "delete_forward"
	                    }
	                ],
	                "type": "basic"
	            }

	        ]
	    },
This gives it the full chording capabilities of a Delete key. Specifically:

Shift + Option + Backspace ⇨ Option + Delete ⇨ delete word to the right
Shift + Command + Backspace ⇨ Command + Delete ⇨ delete line to the right

The last one is also the Empty Trash shortcut in the Finder, which works again now I spotted it and created the Finder specific exception. :P

micmil

28 Apr 2021, 02:08

Tiny Left Shift should not exist. You know what Tiny Left Shift is? Tiny Left Shift is Hitler's Mustache. It sprang to life, ran off to Brazil, and has been popping out clones of itself every since. One day all of the Tiny Left Shifts will rise up and try to take over the world, but then realize they're non-sentient inanimate objects and go back to being useless.

We will never know how close we came to destruction.

User avatar
kbdfr
The Tiproman

28 Apr 2021, 08:22

Funny how millions and millions of ISO users have no problem at all with the short left Shift.
Might be due to the simple fact that they are used to it because it is ISO standard.

Or do the millions of drivers in countries with left-hand traffic drive on the wrong side of the road?

User avatar
Muirium
µ

28 Apr 2021, 10:17

We all drive on the wrong side of the road, if you really think about it. Especially when you’re on a narrow Scottish country road and there’s a bloody tour bus sauntering around in front that you’re really needing past, preferably today. :lol:

How are you at typing on a mischievously small Right Shift I wonder? The good thing about computers is we can program our way around these obstacles when they present themselves.

My Left Shift extender and Shift + Backspace for reversing Delete are second nature to me now. Use them both countless times a day.

User avatar
kbdfr
The Tiproman

28 Apr 2021, 10:34

Muirium wrote:
28 Apr 2021, 10:17
We all drive on the wrong side of the road, if you really think about it. Especially when you’re on a narrow Scottish country road and there’s a bloody tour bus sauntering around in front that you’re really needing past, preferably today. :lol:
I must confess I did not know there are tour buses in Scotland. Is an ox cart not enough for the two and a half tourists? :lol:
How are you at typing on a mischievously small Right Shift I wonder? The good thing about computers is we can program our way around these obstacles when they present themselves. […]
Correct, I was glad I could reprogram that irritatingly huge 2u Backspace to the 1u it deserves (particularly regarding how rarely it is used).

User avatar
Muirium
µ

28 Apr 2021, 10:37

1u Backspace? Now that’s fighting talk, sonny!

User avatar
XMIT
[ XMIT ]

28 Apr 2021, 13:40

Are we surprised that a Frenchman never makes mistakes and doesn’t need a Backspace key?

Beware the angry Scotsman, lest he come at you with his caber.


I personally never use Left Shift. On some space constrained keyboards I will remap it to something else.

</soapbox>

User avatar
zrrion

28 Apr 2021, 14:15

I am the opposite way myself, never use right shift and on unfriendly layouts it normally gets sacrificed for something more valuable

User avatar
fohat
Elder Messenger

28 Apr 2021, 14:57

kbdfr wrote:
28 Apr 2021, 08:22

millions of ISO users have no problem at all with the short left Shift
Muirium wrote:
28 Apr 2021, 10:17

How are you at typing on a mischievously small Right Shift I wonder?
For me, the problem is muscle memory. After decades of ANSI keyboard use, and after doing some experimentation with odd vintage layouts, I understand that I customarily tap the inside (right end) of Left Shift, the outside (right end) of Right Shift.

Also, tangentially, I now know that usually touch the inside (left end) of Backspace and use my right thumb on the space bar 2/3 of the time and the left thumb 1/3 of the time.

I also love the Enter on the numpad and use it regularly.
Last edited by fohat on 28 Apr 2021, 16:03, edited 1 time in total.

User avatar
Muirium
µ

28 Apr 2021, 15:36

This is where ABS shine helps out. My laptops always get worn pretty quick, and this one here says my usual pattern still applies:
  • Spacebar heavily worn on the right, under NM with a much lighter secondary patch (my left hand) under CV.
  • ISO Return pressed exclusively on its lower deck, where ANSI Return should be!
  • Left Shift (and its sneaky extension) well worn, Right Shift not so much, but dead centre on its long, long length.
  • Backspace well used, again hit dead centre.
  • Both Tab and Caps Lock(!) getting a good deal of shine. The latter because I map it to Control! Fscking worse than useless to me otherwise.
  • Bottom row mods all showing shine, especially the right Option key, which I'm using for Enter as I described in the OP.
As for the rest of you nutjobs: a board without two Shifts ain't worth none to me. Are you seriously hunt and pecking me? :lol:

xxhellfirexx

29 Apr 2021, 08:20

Since we are sharing Karabiner scripts, here are a few I use with my IBM AT and 5251.

Image



Pressing and holding a key in the number row will trigger the corresponding function key. That way I do not have to press numlock to switch to the second layer, which I sometimes forget to turn off as there is no indicator light.

Code: Select all

{
  "title": "Trigger corresponding F1-F12 key when num row key is held down",
  "rules": [
    {
      "description": "Trigger corresponding F1-F12 key when num row key is held down",
      "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "1"
            },
            "to_after_key_up": [
                {
                    "key_code": "1"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f1",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "2"
            },
            "to_after_key_up": [
                {
                    "key_code": "2"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f2",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "3"
            },
            "to_after_key_up": [
                {
                    "key_code": "3"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f3",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "4"
            },
            "to_after_key_up": [
                {
                    "key_code": "4"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f4",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "5"
            },
            "to_after_key_up": [
                {
                    "key_code": "5"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f5",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "6"
            },
            "to_after_key_up": [
                {
                    "key_code": "6"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f6",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "7"
            },
            "to_after_key_up": [
                {
                    "key_code": "7"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f7",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "8"
            },
            "to_after_key_up": [
                {
                    "key_code": "8"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f8",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "9"
            },
            "to_after_key_up": [
                {
                    "key_code": "9"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f9",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "0"
            },
            "to_after_key_up": [
                {
                    "key_code": "0"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f10",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "hyphen"
            },
            "to_after_key_up": [
                {
                    "key_code": "hyphen"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f11",
                    "halt": true
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "equal_sign"
            },
            "to_after_key_up": [
                {
                    "key_code": "equal_sign"
                }
            ],
            "to_if_held_down": [
                {
                    "key_code": "f12",
                    "halt": true
                }
            ]
        }
      ]
    }
  ]
}
I doubled up the left control and caps lock key on the IBM AT as there are not enough modifier keys. If the left control key is pressed by itself, I get caps lock. If the left control key is press with another key, I get control.

Code: Select all

{
  "title": "Change caps_lock key (rev 4)",
  "rules": [
    {
      "description": "Change left_control to caps_lock unless pressed with other keys.",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "left_control",
            "modifiers": {
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "left_control"
            }
          ],
          "to_if_alone": [
            {
              "key_code": "caps_lock",
              "hold_down_milliseconds": 500
            }
          ]
        }
      ]
    },
    {
      "description": "Disable caps_lock delay",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "caps_lock",
            "modifiers": {
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "caps_lock",
              "hold_down_milliseconds": 200
            },
            {
              "key_code": "vk_none"
            }
          ]
        }
      ]
    }
  ]
}
To deal with the single unit backspace, I use the following macro. It allows me to press and hold either shift key and tap the other shift key to backspace.

Code: Select all

{
  "title": "Both shift = backspace.",
  "rules": [
    {
      "description": "Both shift = backspace.",
      "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "left_shift",
                "modifiers": {
                    "mandatory": ["right_shift"]
                }
            },
            "to": [
                {
                    "key_code": "delete_or_backspace",
                    "lazy": true
                }
            ],
            "to_if_alone": [
                {
                    "key_code": "left_shift"
                }
            ]
        },
        {
            "type": "basic",
            "from": {
                "key_code": "right_shift",
                "modifiers": {
                    "mandatory": ["left_shift"]
                }
            },
            "to": [
                {
                    "key_code": "delete_or_backspace",
                    "lazy": true
                }
            ],
            "to_if_alone": [
                {
                    "key_code": "right_shift"
                }
            ]
        }
      ]
    }
  ]
}
If I tap both shifts simultaneously twice, I can delete one word.

Code: Select all

{
	"title": "Both shift 2x = delete word.",
	"rules": [
	{
		"description": "Both shift 2x = delete word.",
		"manipulators": [
		{
		    "type": "basic",
			"from": {
				"simultaneous": [
					{
						"key_code": "left_shift"
					},
					{
						"key_code": "right_shift"
					}
				],
				"modifiers": {
					"optional": [
						"any"
					]
				}
			},
		    "to": [
		        {
		            "key_code": "delete_or_backspace",
					"modifiers":[
						"right_option"
					]
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "both_shift pressed",
		            "value": 1
		        }
		    ]
		},

		{
		    "type": "basic",
			"from": {
				"simultaneous": [
					{
						"key_code": "left_shift"
					},
					{
						"key_code": "right_shift"
					}
				],
				"modifiers": {
					"optional": [
						"any"
					]
				}
			},
		    "to": [
		        {
		            "set_variable": {
		                "name": "both_shift pressed",
		                "value": 1
		            }
		        }
		    ],
		    "to_delayed_action": {
		        "to_if_invoked": [
		            {
		                "set_variable": {
		                    "name": "both_shift pressed",
		                    "value": 0
		                }
		            }
		        ],
		        "to_if_canceled": [
		            {
		                "set_variable": {
		                    "name": "both_shift pressed",
		                    "value": 0
		                }
		            }
		        ]
		    }
		}
		]
    }
	]
}
Thanks Muirium for the Shift + Backspace = Delete macro as I usually use the numpad period, which is inaccessible with numlock enabled.

Code: Select all

{
  "title": "Shift + Backspace = Delete",
  "rules": [
    {
      "description": "Shift + Backspace = Delete",
      "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "delete_or_backspace",
                "modifiers": {
                    "mandatory": ["shift"]
                }
            },
            "to": [
                {
                    "key_code": "delete_forward"
                }
            ]
        }
      ]
    }
  ]
}
Last edited by xxhellfirexx on 30 Apr 2021, 06:13, edited 1 time in total.

User avatar
Muirium
µ

29 Apr 2021, 11:08

Always pleased to spread the remap + macro love! Some inventive thinking at work in your collection. Might steal one or two myself. :D

Big Ass Enter is the mighty AT's most prominent flaw, far as I'm concerned. I took another approach to remapping that PAR-TIC-ULAR key. I did away with it in the physical hardware! Here's my µAT as she is right now:

IMG_9060.jpg
IMG_9060.jpg (1.01 MiB) Viewed 456 times
A few modifications on show here. I've not the stones to attempt a full ANSI mod, and I actually quite like the vintage weighted spacebar anyway. So that stays. I just took off Big Ass, swapped in some harvested flippers, and split it into a real ANSI Return and 1.5u HHKB style Backspace key. Well, a Tab key, but my fingers don't mind! I completed the HHKB top row, with matching legends, and played around with the Numpad, giving it navigation keys. Oh, and installed a Fn' Lenin.

Here's the actual layout, in QMK:

Screenshot 2021-04-29 at 9.43.58 am.jpg
Screenshot 2021-04-29 at 9.43.58 am.jpg (191.99 KiB) Viewed 456 times
I used my ancient approach with Model Fs and spread the full suite of modern modifiers along the bottom row of the function columns. No need to twiddle them on shared keys when you've hardware down there to map them on, already.

(Though I do agree that combining a real mod and Caps Lock with one-touch logic is smart, especially on tiny boards.)

The pochled numpad was originally just to fill out the block, once I'd added the arrow keys I really wanted. But I find it's actually quite useful. Especially that Numpad Enter in the corner. I habitually assume that key is Enter on larger boards. It's a nice quick one to always have.

I threw my regular HHKB navigation layer on Layer 1, as I always do. For a long time, I used the one key right of the spacebar as my HHKB style Fn, that's why it's an icon legend Shift: an upwards pointing arrow to remind me it shifts up a layer! But this arrow-keyed AT has less need for all that than my Kishsaver. So I switched it back to right Command—a key I really need—and let Ln handle the second layer instead. What's actually useful up there is the mouse keys I put on the numpad. Hit Vladimir, and you toggle into mouse mode: handy when typing with the AT on your lap and need to go hit something quick.

Yes, there's a Caps Lock up on Ln + Tab but that's just a fallback for the iPad or any other machine not running Karabiner. What I really use is Shift + Shift for Caps Lock; but I've not figured out how to code up macros in QMK.

Last but not least: where's the cable? Ah, well, I added a USB C port in the original opening on the back. This µAT has a more modern connector than those damn Unicomp SSKs! :lol:
Last edited by Muirium on 29 Apr 2021, 11:31, edited 1 time in total.

User avatar
Bjerrk

29 Apr 2021, 11:30

Muirium wrote:
23 Mar 2021, 12:52
The legends… they're all true?
Until you remap.

User avatar
Muirium
µ

29 Apr 2021, 11:42

Indeed! Always a risk when you're getting fancy.

The legends on my Mac's built in keyboard are, in fact, all still true. Well, okay Caps Lock may be Control now, but its LED indicator is still faithful to its icon! Really, I just happened to add some extra functions. Some of them were simply lost in time. Prime example: the missing numeric layer from my PowerBook, now also present on the M1 thanks to Karabiner.

PowerBook embedded numpad.gif
PowerBook embedded numpad.gif (97.12 KiB) Viewed 436 times
I usually just hold Fn to type numbers with my right hand, which worked back then as well, as shown in Apple's long forgottendiagram. No way to restore the old PowerBooks' little yellow-green Num Lock LED on F6 though.

Now yes, my vintage keyboards like the Kishsaver and especially the AT are another matter! That's why I prize consistency in my screwing around. If I can remember all my monkey business well enough, then I don't need to go look at what the lying keys say. :roll:

User avatar
Muirium
µ

01 May 2021, 11:11

Thanks to xxhellfirexx (whose to_delayed_action-fu is well ahead of mine) I've added a bunch of extra twiddly double-tap stuff. They also clued me into why "key_code": "spotlight" doesn't work, so I've cleaned up my media keys too.

Double Tap toggles:

Code: Select all

	    {
	    	"description": "Right Command double tap ⇨ 🔍 Spotlight",
	    	"manipulators": [
	    		{
	    			"type": "basic",
	    			"from": {
	    				"key_code": "right_command",
	    				"modifiers": {
	    					"optional": [
	    						"caps_lock"
	    					]
	    				}
	    			},
	    			"to": [
	    				{
	    					"apple_vendor_keyboard_key_code": "spotlight"
	    				}
	    			],
	    			"conditions": [
	    				{
	    					"type": "variable_if",
	    					"name": "right_command pressed",
	    					"value": 1
	    				}
	    			]
	    		},
	    		{
	    			"type": "basic",
	    			"from": {
	    				"key_code": "right_command",
	    				"modifiers": {
	    					"optional": [
	    						"caps_lock"
	    					]
	    				}
	    			},
	    			"to": [
	    				{
	    					"set_variable": {
	    						"name": "right_command pressed",
	    						"value": 1
	    					}
	    				},
	    				{
	    					"key_code": "right_command"
	    				}
	    			],
	    			"to_delayed_action": {
	    				"to_if_invoked": [
	    					{
	    						"set_variable": {
	    							"name": "right_command pressed",
	    							"value": 0
	    						}
	    					}
	    				],
	    				"to_if_canceled": [
	    					{
	    						"set_variable": {
	    							"name": "right_command pressed",
	    							"value": 0
	    						}
	    					}
	    				]
	    			}
	    		}
	    	]
	    },
	    {
	    	"description": "Right Shift double tap ⇨ ⇪ Caps Lock",
	    	"manipulators": [
	    		{
	    			"type": "basic",
	    			"from": {
	    				"key_code": "right_shift",
	    				"modifiers": {
	    					"optional": [
	    						"caps_lock"
	    					]
	    				}
	    			},
	    			"to": [
	    				{
	    					"key_code": "caps_lock"
	    				}
	    			],
	    			"conditions": [
	    				{
	    					"type": "variable_if",
	    					"name": "right_shift pressed",
	    					"value": 1
	    				}
	    			]
	    		},
	    		{
	    			"type": "basic",
	    			"from": {
	    				"key_code": "right_shift",
	    				"modifiers": {
	    					"optional": [
	    						"caps_lock"
	    					]
	    				}
	    			},
	    			"to": [
	    				{
	    					"set_variable": {
	    						"name": "right_shift pressed",
	    						"value": 1
	    					}
	    				},
	    				{
	    					"key_code": "right_shift"
	    				}
	    			],
	    			"to_delayed_action": {
	    				"to_if_invoked": [
	    					{
	    						"set_variable": {
	    							"name": "right_shift pressed",
	    							"value": 0
	    						}
	    					}
	    				],
	    				"to_if_canceled": [
	    					{
	    						"set_variable": {
	    							"name": "right_shift pressed",
	    							"value": 0
	    						}
	    					}
	    				]
	    			}
	    		}
	    	]
	    }
I've been hankering after right Command x2 to trigger search ever since my old Quicksilver days. Now I've got it back! Triggering it with just one finger feels so much quicker to me than even Command + Space. Love it! You've got my thanks! 8-)

Note the rather ungainly "apple_vendor_keyboard_key_code": "spotlight". That's how Karabiner describes the dedicated Spotlight key. xxhellfirexx showed me how to do it with a Command + Space macro but I wanted to get to the bottom of this, as I was having trouble with other media keys anyway.

I also threw in right Shift x2 for Caps Lock because I wanted to see if I understand it. Kinda! This also clued me into the need to treat Caps Lock as a modifier in other definitions. My first attempt actually disabled Command x2 whenever Caps Lock was engaged! Good to know to look for it.

So, about those media keys:

Code: Select all

		{
			"description": "Navigation Sixpack lock row ⇨ 🔉 Volume keys",
			"manipulators": [
				{
					"from": {
						"key_code": "print_screen",
						"modifiers": {
							"optional": ["any"]
						}
					},
					"to": [
						{
							"consumer_key_code": "mute",
							"repeat": "true"
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "keypad_num_lock",
						"modifiers": {
							"optional": ["any"]
						}
					},
					"to": [
						{
							"consumer_key_code": "mute",
							"repeat": "true"
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "scroll_lock",
						"modifiers": {
							"optional": ["any"]
						}
					},
					"to": [
						{
							"key_code": "volume_decrement",
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "pause",
						"modifiers": {
							"optional": ["any"]
						}
					},
					"to": [
						{
							"key_code": "volume_increment",
							"repeat": true
						}
					],
					"type": "basic"
				}
			]
		},
		{
			"description": "Fine Volume: Command ± 🔉 ⇨ Shift + Option ± 🔉",
			"manipulators": [
				{
					"from": {
						"key_code": "volume_decrement",
						"modifiers": {
							"mandatory": ["command"]
						}
					},
					"to": [
							{
								"key_code": "volume_decrement",
								"modifiers": [
									"left_shift",
									"left_alt"
								],
								"repeat": true
							}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f11",
						"modifiers": {
							"mandatory": ["command"]
						}
					},
					"to": [
							{
								"key_code": "volume_decrement",
								"modifiers": [
									"left_shift",
									"left_alt"
								],
								"repeat": true
							}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "volume_increment",
						"modifiers": {
							"mandatory": ["command"]
						}
					},
					"to": [
						{
							"key_code": "volume_increment",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f12",
						"modifiers": {
							"mandatory": ["command"]
						}
					},
					"to": [
						{
							"key_code": "volume_increment",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				}
			]
		},
		{
			"description": "Fine Brightness: Command ± 🔅 ⇨ Shift + Option ± 🔅",
			"manipulators": [
				{
					"from": {
						"key_code": "display_brightness_decrement",
						"modifiers": {
							"mandatory": [
								"command"
							]
						}
					},
					"to": [
						{
							"key_code": "display_brightness_decrement",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f1",
						"modifiers": {
							"mandatory": [
								"command"
							]
						}
					},
					"to": [
						{
							"key_code": "display_brightness_decrement",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "display_brightness_increment",
						"modifiers": {
							"mandatory": [
								"command"
							]
						}
					},
					"to": [
						{
							"key_code": "display_brightness_increment",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f2",
						"modifiers": {
							"mandatory": [
								"command"
							]
						}
					},
					"to": [
						{
							"key_code": "display_brightness_increment",
							"modifiers": [
								"left_shift",
								"left_alt"
							],
							"repeat": true
						}
					],
					"type": "basic"
				}
			]
		},
		{
			"description": "Contrast: Control ± 🔅 ⇨ Control + Option + Command ± .",
			"manipulators": [
				{
					"from": {
						"consumer_key_code": "display_brightness_decrement",
						"modifiers": {
							"mandatory": [
								"control"
							]
						}
					},
					"to": [
						{
							"key_code": "period",
							"modifiers": [
								"left_control",
								"left_option",
								"left_command"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f1",
						"modifiers": {
							"mandatory": [
								"control"
							]
						}
					},
					"to": [
						{
							"key_code": "period",
							"modifiers": [
								"left_control",
								"left_option",
								"left_command"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"consumer_key_code": "display_brightness_increment",
						"modifiers": {
							"mandatory": [
								"control"
							]
						}
					},
					"to": [
						{
							"key_code": "comma",
							"modifiers": [
								"left_control",
								"left_option",
								"left_command"
							],
							"repeat": true
						}
					],
					"type": "basic"
				},
				{
					"from": {
						"key_code": "f2",
						"modifiers": {
							"mandatory": [
								"control"
							]
						}
					},
					"to": [
						{
							"key_code": "comma",
							"modifiers": [
								"left_control",
								"left_option",
								"left_command"
							],
							"repeat": true
						}
					],
					"type": "basic"
				}
			]
		}
Still need to test these media shortcuts with the usual suspects: my Realforce (with its misplaced Num Lock key where Print Screen usually lies), the Filco and the Novatouch. But I reckon they're right now, supporting Mute everywhere, thanks to now knowing its true name: "consumer_key_code": "mute" :roll:

I'll wrap these into the OP rules once they're tested.

Believe it or not, I'm trying to make things cleaner to use. My goal is to have no fiddly, mousy per-keyboard "Simple Modifications" at all, and let rule logic figure all this stuff out, whenever I hook up a different board. We'll see. It's either this or a bunch of Hasu USB to USB converters! Nooo! :lol:

Oh, and then there's the unfinished business of trying to use right Option x2 as my soft Num Lock layer lock, which involves monkeying around with its added Enter function *and* twiddling two state variables at once. Maybe I could put it on one of those hold triggers of yours, like your function row. I'll, uh, come back to that…

User avatar
Muirium
µ

01 May 2021, 15:30

Here's just a little fruity something I'm playing with:

Code: Select all

{
	"title": "🖱 Mouse Keys",
	"rules": [
		{
			"description": "Press and hold HHKB style 🖱 keys",
			"manipulators": [
				{
					"type": "basic",
					"from": {
						"key_code": "semicolon"
					},
					"to_after_key_up": [
						{
							"key_code": "semicolon"
						}
					],
					"to_if_held_down": [
						{
							"mouse_key": {
								"x": -1536
							},
							"halt": true
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "quote"
					},
					"to_after_key_up": [
						{
							"key_code": "quote"
						}
					],
					"to_if_held_down": [
						{
							"mouse_key": {
								"x": 1536
							},
							"halt": true
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "open_bracket"
					},
					"to_after_key_up": [
						{
							"key_code": "open_bracket"
						}
					],
					"to_if_held_down": [
						{
							"mouse_key": {
								"y": -1536
							},
							"halt": true
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "slash"
					},
					"to_after_key_up": [
						{
							"key_code": "slash"
						}
					],
					"to_if_held_down": [
						{
							"mouse_key": {
								"y": 1536
							},
							"halt": true
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "l"
					},
					"to_after_key_up": [
						{
							"key_code": "l"
						}
					],
					"to_if_held_down": [
						{
							"mouse_key": {
								"vertical_wheel": -32
							},
							"halt": true
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "period"
					},
					"to_after_key_up": [
						{
							"key_code": "period"
						}
					],
					"to_if_held_down": [
						{
							"mouse_key": {
								"vertical_wheel": 32
							},
							"halt": true
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "p"
					},
					"to_after_key_up": [
						{
							"key_code": "p"
						}
					],
					"to_if_held_down": [
						{
							"pointing_button": "button1",
							"halt": true
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "close_bracket"
					},
					"to_after_key_up": [
						{
							"key_code": "close_bracket"
						}
					],
					"to_if_held_down": [
						{
							"pointing_button": "button2",
							"halt": true
						}
					]
				}
			]
		}
	]
}
Handy so far! Let's see how long they take to trip me ass over teakettle. :lol:

Edit: Actually, that did not take long! Just typing kettel kettel, damn it kett…le is affected by just enough key up delay I'm out typing it myself and getting the wrong order. Rats! Shame, because mouse keys (namely keyboard on lap keys!) are really nice without needing to hodl (<< dodgy L key!) some other key down with them, or needing to remember where the mode lock lives. Lemme see what I can do.

User avatar
Muirium
µ

04 May 2021, 10:59

Okay, no amount of fiddling with to_if_held_down_threshold fixed those lazy keys. So I'm trying something different. How about a mousing mode, toggled by double tapping right Shift? That key's on all my keyboards, and I kinda sorta know how to do double taps and layers now. So let's mix them both! What could possibly go wrong? (Spoiler: something went wrong…)

My current attempt:

Code: Select all

{
	"title": "🖱 Mouse Keys",
	"rules": [
		{
	    	"description": "Right Shift double tap ⇨ 🖱 keys layer lock",
	    	"manipulators": [
	    		{
	    			"type": "basic",
	    			"from": {
	    				"key_code": "right_shift",
	    				"modifiers": {
	    					"optional": [
	    						"caps_lock"
	    					]
	    				}
	    			},
	    			"to": {
						"set_variable": {
							"name": "mouse_keys_mode",
							"value": 1
						}
					},
	    			"conditions": [
	    				{
	    					"type": "variable_if",
	    					"name": "right_shift pressed",
	    					"value": 1
	    				},
	    				{
	    					"type": "variable_if",
	    					"name": "mouse_keys_mode",
	    					"value": 0
	    				}
	    			]
	    		},
	    		{
	    			"type": "basic",
	    			"from": {
	    				"key_code": "right_shift",
	    				"modifiers": {
	    					"optional": [
	    						"caps_lock"
	    					]
	    				}
	    			},
	    			"to": [
	    				{
	    					"set_variable": {
	    						"name": "right_shift pressed",
	    						"value": 1
	    					}
	    				},
	    				{
	    					"key_code": "right_shift"
	    				}
	    			],
	    			"to_delayed_action": {
	    				"to_if_invoked": [
	    					{
	    						"set_variable": {
	    							"name": "right_shift pressed",
	    							"value": 0
	    						}
	    					}
	    				],
	    				"to_if_canceled": [
	    					{
	    						"set_variable": {
	    							"name": "right_shift pressed",
	    							"value": 0
	    						}
	    					}
	    				]
	    			}
	    		},
	    		{
	    			"type": "basic",
	    			"from": {
	    				"key_code": "right_shift",
	    				"modifiers": {
	    					"optional": [
	    						"caps_lock"
	    					]
	    				}
	    			},
	    			"to": {
						"set_variable": {
							"name": "mouse_keys_mode",
							"value": 0
						}
					},
	    			"conditions": [
	    				{
	    					"type": "variable_if",
	    					"name": "right_shift pressed",
	    					"value": 1
	    				},
	    				{
	    					"type": "variable_if",
	    					"name": "mouse_keys_mode",
	    					"value": 1
	    				}
	    			]
	    		},
	    		{
	    			"type": "basic",
	    			"from": {
	    				"key_code": "right_shift",
	    				"modifiers": {
	    					"optional": [
	    						"caps_lock"
	    					]
	    				}
	    			},
	    			"to": [
	    				{
	    					"set_variable": {
	    						"name": "right_shift pressed",
	    						"value": 1
	    					}
	    				},
	    				{
	    					"key_code": "right_shift"
	    				}
	    			],
	    			"to_delayed_action": {
	    				"to_if_invoked": [
	    					{
	    						"set_variable": {
	    							"name": "right_shift pressed",
	    							"value": 0
	    						}
	    					}
	    				],
	    				"to_if_canceled": [
	    					{
	    						"set_variable": {
	    							"name": "right_shift pressed",
	    							"value": 0
	    						}
	    					}
	    				]
	    			}
	    		},
	    		{
					"type": "basic",
					"from": {
						"key_code": "semicolon"
					},
					"to": [
						{
							"mouse_key": {
								"x": -1536
							}
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "mouse_keys_mode",
							"value": 1
						}
					]
				},
	    		{
					"type": "basic",
					"from": {
						"key_code": "quote"
					},
					"to": [
						{
							"mouse_key": {
								"x": 1536
							}
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "mouse_keys_mode",
							"value": 1
						}
					]
				},
	    		{
					"type": "basic",
					"from": {
						"key_code": "open_bracket"
					},
					"to": [
						{
							"mouse_key": {
								"y": -1536
							}
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "mouse_keys_mode",
							"value": 1
						}
					]
				},
	    		{
					"type": "basic",
					"from": {
						"key_code": "slash"
					},
					"to": [
						{
							"mouse_key": {
								"y": 1536
							}
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "mouse_keys_mode",
							"value": 1
						}
					]
				},
	    		{
					"type": "basic",
					"from": {
						"key_code": "l"
					},
					"to": [
						{
							"mouse_key": {
								"vertical_wheel": -32
							}
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "mouse_keys_mode",
							"value": 1
						}
					]
				},
	    		{
					"type": "basic",
					"from": {
						"key_code": "period"
					},
					"to": [
						{
							"mouse_key": {
								"vertical_wheel": 32
							}
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "mouse_keys_mode",
							"value": 1
						}
					]
				},
	    		{
					"type": "basic",
					"from": {
						"key_code": "p"
					},
					"to": [
						{
							"pointing_button": "button1",
							"halt": true
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "mouse_keys_mode",
							"value": 1
						}
					]
				},
				{
					"type": "basic",
					"from": {
						"key_code": "close_bracket"
					},
					"to": [
						{
							"pointing_button": "button2",
							"halt": true
						}
					],
					"conditions": [
						{
							"type": "variable_if",
							"name": "mouse_keys_mode",
							"value": 1
						}
					]
				}
			]
		}
	]
}
Almost there now! Just one problem: I can't toggle back out of Mouse Keys mode. Anyone know what I'm doing wrong with the latch?


Edit: Much to my continued amusement, it really doesn't work how I think it should. Check this out. I thought "hey, for now let's just copy paste the set variable mouse_keys_mode = 0 exit stuff on my known good old Shift + Shift ⇨ Caps Lock instead. That way I can at least get back out again quick and dirty style. What could possibly…” So I did this:

Code: Select all

	    {
	        "description": "Shift + Shift ⇨ ⇪ Caps Lock",
	        "manipulators": [
	            {
	                "from": {
	                    "key_code": "left_shift",
	                    "modifiers": {
	                        "mandatory": [
	                            "right_shift"
	                        ],
	                        "optional": [
	                            "any"
	                        ]
	                    }
	                },
	                "to": [
	                    {
	                        "key_code": "caps_lock",
	                        "set_variable": {
								"name": "mouse_keys_mode",
								"value": 0
							}
	                    }
	                ],
	                "type": "basic"
	            },
	            {
	                "from": {
	                    "key_code": "right_shift",
	                    "modifiers": {
	                        "mandatory": [
	                            "left_shift"
	                        ],
	                        "optional": [
	                            "any"
	                        ]
	                    }
	                },
	                "to": [
	                    {
	                        "key_code": "caps_lock",
	                        "set_variable": {
								"name": "mouse_keys_mode",
								"value": 0
							}
	                    }
	                ],
	                "type": "basic"
	            }
	        ]
	    },
And what actually happens? Mouse keys layer successfully deactivated when I engage Caps Lock, but now Caps Lock itself is broken, and toggling both then gets me stuck in mouse keys again. :roll:

What that even mean!? Well, besides I clearly don't know what I'm doin' rong. :P

xxhellfirexx

Yesterday, 07:03

Muirium wrote:
04 May 2021, 10:59
And what actually happens? Mouse keys layer successfully deactivated when I engage Caps Lock, but now Caps Lock itself is broken, and toggling both then gets me stuck in mouse keys again. :roll:

What that even mean!? Well, besides I clearly don't know what I'm doin' rong. :P
Here is a fixed version of the mouse keys toggle.

Code: Select all

{
	"title": "Right Shift x2 = Mouse keys mode",
	"description": "semicolon = left, quote = right, open_bracket = up, slash = down, l = scroll up, period = scroll down, p = left click, close_bracket = right click",
	"rules": [
	{
		"description": "Right Shift x2 = Mouse keys mode",
		"manipulators": [
		{
		    "type": "basic",
				"description": "semicolon (;) = Move pointer left",
				"from": {
		        "key_code": "semicolon",
						"modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
							"mouse_key": {
								"x": -1536
							}
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "mouse_keys enabled",
		            "value": 1
		        }
		    ]
		},

		{
		    "type": "basic",
				"description": "quote (\") = Move pointer right",
				"from": {
		        "key_code": "quote",
						"modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
							"mouse_key": {
								"x": 1536
							}
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "mouse_keys enabled",
		            "value": 1
		        }
		    ]
		},

		{
		    "type": "basic",
				"description": "open_bracket ([) = Move pointer up",
				"from": {
		        "key_code": "open_bracket",
						"modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
							"mouse_key": {
								"y": -1536
							}
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "mouse_keys enabled",
		            "value": 1
		        }
		    ]
		},

		{
		    "type": "basic",
				"description": "slash (/) = Move pointer down",
				"from": {
		        "key_code": "slash",
						"modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
							"mouse_key": {
								"y": 1536
							}
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "mouse_keys enabled",
		            "value": 1
		        }
		    ]
		},

		{
		    "type": "basic",
				"description": "L (l) = Scroll up",
				"from": {
		        "key_code": "l",
						"modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
							"mouse_key": {
								"vertical_wheel": -32
							}
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "mouse_keys enabled",
		            "value": 1
		        }
		    ]
		},

		{
		    "type": "basic",
				"description": "period (.) = Scroll down",
				"from": {
		        "key_code": "period",
						"modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
							"mouse_key": {
								"vertical_wheel": 32
							}
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "mouse_keys enabled",
		            "value": 1
		        }
		    ]
		},

		{
		    "type": "basic",
				"description": "P (p) = Left click",
				"from": {
		        "key_code": "p",
						"modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
							"pointing_button": "button1",
							"halt": true
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "mouse_keys enabled",
		            "value": 1
		        }
		    ]
		},

		{
		    "type": "basic",
				"description": "close_bracket (]) = Right click",
				"from": {
		        "key_code": "close_bracket",
						"modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
							"pointing_button": "button2",
							"halt": true
		        }
		    ],
		    "conditions": [
		        {
		            "type": "variable_if",
		            "name": "mouse_keys enabled",
		            "value": 1
		        }
		    ]
		},




		{
				"type": "basic",
				"description": "After right shift pressed the second time, enable mouse keys if not enabled yet.",
				"from": {
		        "key_code": "right_shift",
		        "modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
		            "set_variable": {
		                "name": "mouse_keys enabled",
		                "value": 1
		            }
		        },
						{
								"key_code": "right_shift"
						}
		    ],
				"conditions": [
						{
								"type": "variable_if",
								"name": "right_shift pressed",
								"value": 1
						},
						{
								"type": "variable_if",
								"name": "mouse_keys enabled",
								"value": 0
						}
				]
		},


		{
				"type": "basic",
				"description": "After right shift pressed the second time, disable mouse keys if it is enabled.",
				"from": {
		        "key_code": "right_shift",
		        "modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
				"to": [
		        {
		            "set_variable": {
		                "name": "mouse_keys enabled",
		                "value": 0
		            }
		        },
						{
								"key_code": "right_shift"
						}
		    ],
				"conditions": [
						{
								"type": "variable_if",
								"name": "right_shift pressed",
								"value": 1
						},
						{
								"type": "variable_if",
								"name": "mouse_keys enabled",
								"value": 1
						}
				]
		},


		{
		    "type": "basic",
				"description": "Set right shift pressed to 1 when right shift is pressed. If time out in 500 ms (if invoked) or another key pressed (if canceled), set back to 0.",
				"from": {
		        "key_code": "right_shift",
		        "modifiers": {
		            "optional": [
		                "any"
		            ]
		        }
		    },
		    "to": [
		        {
		            "set_variable": {
		                "name": "right_shift pressed",
		                "value": 1
		            }
		        },
						{
								"key_code": "right_shift"
						}
		    ],
		    "to_delayed_action": {
		        "to_if_invoked": [
		            {
		                "set_variable": {
		                    "name": "right_shift pressed",
		                    "value": 0
		                }
		            }
		        ],
		        "to_if_canceled": [
		            {
		                "set_variable": {
		                    "name": "right_shift pressed",
		                    "value": 0
		                }
		            }
		        ]
		    }
		}
		]
    }
	]
}
Your caps lock script does not work well with the mouse keys script. So I replaced it with my version. The only difference is your script allows you to press and hold one shift then press the other shift to toggle caps lock. My script requires both shifts to be pressed together at the same time.

Code: Select all

{
	"title": "Both Shift = Caps Lock",
	"rules": [
	{
		"description": "Both Shift = Caps Lock",
		"manipulators": [
		{
		    "type": "basic",
			"from": {
				"simultaneous": [
					{
						"key_code": "left_shift"
					},
					{
						"key_code": "right_shift"
					}
				],
				"modifiers": {
					"optional": [
						"any"
					]
				}
			},
		    "to": [
		        {
		            "key_code": "caps_lock"
		        }
		    ]
		}
		
		]
    }
	]
}
Have fun and be careful to not put too many macros for the same keys (like shift in this case) or commonly used ones (like L and P) or you might accidentally fall into your own trapdoor.

User avatar
Muirium
µ

Yesterday, 09:39

Fall into trap? Who, me? I’m just here for tasty, tasty doh…
Spoiler:
Image
Thanks for the edits! I’ll give them a shot.

Edit: So far, so good. I integrated your double tap Shift logic into my own and it's working a beaut. Thanks!

Shift + Shift > Caps Lock doesn't need modification, it still works well, unmodified. (And lets me be slower at engaging them without punishment.) I was tangling them together as a sanity check earlier, which had the opposite to its intended effect… :lol:

I'm also trialling a slight delay on my "Caps Lock" Control key, seeing as I keep hitting it in glancing, when typing A on my laptop, and getting taken to the beginning of paragraphs thanks to instantaneous Ctrl+A. A little damping does the trick. Just need to tune the exact delay so it never catches me out when I really mean Control.

Post Reply

Return to “Workshop”