I recently published a Karabiner trick that turned ; plus J/I/K/L into arrow keys. I’ve determined that my implementation could use some work. Here’s the redux.

More from "KeyBinding"click here to see all

The original tip used Karabiner to turn ; into a Fn key when pressed with other keys, and allowed a double tap to add additional functionality. Then the arrow keys were assigned with BetterTouchTool. This implementation ended up being a bit flaky when it came to switching directions, key repeats, and the normal functionality of the semicolon key.

I completely re-implemented this using just Karabiner, which is much smoother and solves all of the above issues. The only difference in actual usage is that instead of a double tap to get Fn+arrow functionality, it uses the quote key (to the right of semicolon). The result functions perfectly with other modifier keys like and for selections.

All of the snippets in this post are gathered into this gist.

To use this setup, you need four new rules in Karabiner. For each of the following snippets, go to Complex Modifications, select Add your own rule, and paste each snippet into its own rule.

add-your-own-rule.jpg

Obviously with a tiny bit of editing you can make any of these function with Vim-style H/J/K/L keys.

First, we make the ; function as Left-Fn+ when pressed with other keys, posting ; as usual when pressed and released alone.

semicolon-to-left-cmd-fn.json raw
{
    "description": "Change ; to Left_command + Fn if pressed with other keys (Post ; when pressed alone)",
    "manipulators": [
        {
            "from": {
                "key_code": "semicolon",
                "modifiers": { "optional": ["any"] }
            },
            "to": [
                {
                    "key_code": "fn",
                    "modifiers": ["left_command"]
                }
            ],
            "to_if_alone": [{ "key_code": "semicolon" }],
            "type": "basic"
        }
    ]
}
Copy

Next, we make the ' key function as Right-Fn+ when held with other keys, posting ' when pressed alone.

quote-to-right-cmd-fn.json raw
{
    "description": "Change ' to Right_command + Fn if pressed with other keys (Post ' when pressed alone)",
    "manipulators": [
        {
            "from": {
                "key_code": "quote",
                "modifiers": { "optional": ["any"] }
            },
            "to": [
                {
                    "key_code": "fn",
                    "modifiers": ["right_command"]
                }
            ],
            "to_if_alone": [{ "key_code": "quote" }],
            "type": "basic"
        }
    ]
}
Copy

Now we assign our J/I/K/L keys to /// when pressed along with the ; key (which is now Left-Fn+).

To make this into H/J/K/L navigation, change the "key_code": "k" lines to h, j, k, and l, in that order.

left-cmd-fn-jkil-to-arrow.json raw
{
    "description": "Change Left_command + Fn + J/K/I/L to Arrow Keys",
    "manipulators": [
        {
            "from": {
                "key_code": "j",
                "modifiers": {
                    "mandatory": ["left_command", "fn"],
                    "optional": ["any"]
                }
            },
            "to": [{ "key_code": "left_arrow" }],
            "type": "basic"
        },
        {
            "from": {
                "key_code": "k",
                "modifiers": {
                    "mandatory": ["left_command", "fn"],
                    "optional": ["any"]
                }
            },
            "to": [{ "key_code": "down_arrow" }],
            "type": "basic"
        },
        {
            "from": {
                "key_code": "i",
                "modifiers": {
                    "mandatory": ["left_command", "fn"],
                    "optional": ["any"]
                }
            },
            "to": [{ "key_code": "up_arrow" }],
            "type": "basic"
        },
        {
            "from": {
                "key_code": "l",
                "modifiers": {
                    "mandatory": ["left_command", "fn"],
                    "optional": ["any"]
                }
            },
            "to": [{ "key_code": "right_arrow" }],
            "type": "basic"
        }
    ]
}
Copy

And lastly, we assign J/I/K/L keys to /// when pressed along with the ' key.

right-cmd-fn-jkil-to-fn-arrow.json raw
{
    "description": "Change Right_command + Fn + J/K/I/L to Home / Page Down / Page Up / End",
    "manipulators": [
        {
            "from": {
                "key_code": "j",
                "modifiers": {
                    "mandatory": ["right_command", "fn"],
                    "optional": ["any"]
                }
            },
            "to": [{ "key_code": "home" }],
            "type": "basic"
        },
        {
            "from": {
                "key_code": "k",
                "modifiers": {
                    "mandatory": ["right_command", "fn"],
                    "optional": ["any"]
                }
            },
            "to": [{ "key_code": "page_down" }],
            "type": "basic"
        },
        {
            "from": {
                "key_code": "i",
                "modifiers": {
                    "mandatory": ["right_command", "fn"],
                    "optional": ["any"]
                }
            },
            "to": [{ "key_code": "page_up" }],
            "type": "basic"
        },
        {
            "from": {
                "key_code": "l",
                "modifiers": {
                    "mandatory": ["right_command", "fn"],
                    "optional": ["any"]
                }
            },
            "to": [{ "key_code": "end" }],
            "type": "basic"
        }
    ]
}
Copy

Now you can hold down ; and use J/I/K/L as arrow keys, and key repeat, switching between directions, and modifier-based selections will all work smoothly. Hold down ' and use the same keys to navigate with ///. Enjoy!