Categories
Automations MacOS Uncategorized

Setup MacOS system-wide Vim mode

I got interested in workflow automations a while ago. With that came the understanding of Karabiner, which allows the remapping of keyboard keystrokes. Besides this I understood the benefits of using Vim: It is fast and can be used in most Unix distributions. As a result of these concepts arose the idea of a system-wide Vim mode.

The problem

When using a code editor in MacOS, the developer alters the caret position with Alt + →↑↓ ←. However, when SSH-ing into another computer, there is no visual editor, and Vim needs to be used. Vim is also fast, does not require the use of mouse, and has convenient arrow keys on the home row – hjkl.

These two separate environments create a problem where the developer needs to use different code editing systems in Vim and MacOS.

Solution

There needs to be a system wide Vim mode. To create a fast and robust experience, first the keystrokes need to be mapped into ones that simulate Vim behaviour. Secondly, an app needs to be created that displays the Vim modes. Thirdly, this app and the keystrokes need to be connected.

Capture and modify keystrokes

Karabiner needs to be installed to enable remapping of keystrokes. Enthusiasts have created different complex modifications, including Vim modes, from which a suitable one can be imported into the app.

Karabiner is a relatively heavy package, including cumbersome apps like PreferencesWindow, NotificationWindow and EventViewer. These are developer tools which are not required for Vim mode and therefore will not be installed with ti-vim.

Karabiner UI has many options and can be difficult to understand

Create an App to visualise the Vim mode.

After importing suitable complex modifications into Karabiner, a new problem arises. When switching between vim modes, there is no visual indicator. The user doesn’t know if the mode is normal, insert or visual. For this reason, there needs to exist a Vim mode indicator.

This app needs to:

  • Be always float on top: .floating
  • Have a window that switches between images of insert/normal and visual modes
  • Implements interface to Karabiner.
Vim mode indicator app

The first 2 points can be relatively straightforward to implement. For the third one, there are a few options

Karabiner to Indicator app inter-process communication

Karabiner needs to send information about what mode the Vim is to the Indicator app. The keystroke observer daemon can call shell commands after key strokes. This is enables us to use any of the inter-process communication options that are available.

Some alternatives to consider:

  • Distributed Notifications
  • Web socket / Web server
  • Cocoa Scripting Bridge
  • XPC

Once the interface is defined in the Indicator app, a shell command can be invoked in Karabiner. If it is using a Cocoa scripting bridge, an AppleScript function can be called:

"to": [
    {
        "set_variable": {
            "name": "vim_mode",
            "value": 0
        }
    },
    {
        "shell_command": "osascript -e 'tell application \"indicator-app\" to indicator 0'"
    }
]

Solution 2

The app ti-vim is a single package for MacOS that installs system-wide Vim. It bundles Karabiner and the Indicator app out of the box, with the user input needed only to choose the vim mode indicator style. The developer can choose this option if she wants to save time setting up Vim manually.

Conclusion

Vim is a fast and well known method of inputting text/code in any computer environment. MacOS implements a different text navigation system with Alt/Cmd/Shift + →↑↓ ←.If the user wants consistency, then system-wide Vim mode can be setup with Karabiner or a separate app ti-vim.