• Stars
    star
    600
  • Rank 73,980 (Top 2 %)
  • Language
    Lua
  • Created about 6 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Adds vim keybindings to all OS X inputs

VimMode.spoon

Build Status

🚀 This library will add Vim motions and operators to all your input fields on OS X. Why should Emacs users have all the fun?

Example of VimMode.spoon

This uses Hammerspoon, but don't worry - the [quick installer](#quick-installation) is a 1-line bash command to get everything setup.

Not all motions or operators are implemented, but you can open an issue if you're missing something.

The plugin will not work with system inputs marked as secure, such as password fields or anything in 1Password, as it can't read those fields!

Table of Contents

Quick Installation

Run this command in Terminal:

bash <(curl -s https://raw.githubusercontent.com/dbalatero/VimMode.spoon/master/bin/installer)

then read the post-install info printed at the end and follow the instructions.

  • If you prefer, follow the Manual Instructions instead.
  • If you don't trust the script, please audit it. It should be pretty straight-forward to read, and doesn't require root/sudo.
  • It is safe to run this script multiple times.
  • It will not break your existing Hammerspoon setup if you have one.
  • It is progressive - it only sets up what is missing.

Usage

Once installed:

  • To enter normal mode, hit whichever key you bind to it (see below for key bind instructions)
  • To exit normal mode, press i and you're back to a normal OS X input.

Staying up to date

To update the plugin, run:

cd ~/.hammerspoon/Spoons/VimMode.spoon && git pull

Current Support

Flavors of VimMode.

There are two flavors of Vim mode that we try to enable using feature detection.

Advanced Mode

Advanced mode gets turned on when we detect the accessibility features we need to make it work. If the field you are focused in:

  • Supports the OS X accessibility API
  • Is not a rich field with images, embeds, etc
  • Is not a contentEditable rich field in the web browser, I'm not touching that with a 10-foot pole
  • Is not one of these applications that don't completely implement the Accessibility API:
    • Slack.app (Electron)
    • See this file for reasons why these apps are broken and disabled out of the box.

In advanced mode, we actually can read in the value of the focused field and modify cursor position/selection with theoretical perfect accuracy. In this mode, I strive to make sure all Vim motions are as accurate as the editor. I'm sure they are not, though, and would appreciate bug reports!

Fallback mode

In fallback mode, we just map Vim motions/operators to built-in text keyboard shortcuts in OS X, and fire them blindly. This works pretty well, and is how the original version of this plugin worked. There is some behavior that doesn't match Vim however, which we cannot emulate without having the context that Advanced Mode gives.

Motions

  • A - jump to end of line
  • G - jump to last line of input
  • I - jump to beginning of line
  • 0 - beginning of line
  • $ - end of line
  • f<char>
  • F<char>
  • t<char>
  • T<char>
  • a - move right and enter insert
  • b - back by word
  • B - back by big word (:h WORD)
  • e - fwd to end of word
  • E - fwd to end of big word (:h WORD)
  • gg - top of buffer
  • hjkl - arrow keys
  • w fwd by word
  • W fwd by big word (:h WORD)
  • iw - in word
  • i' - in single quotes
  • i( - in parens
  • i{ - in braces
  • i< - in angle brackets
  • i` - in backticks
  • i" - in double quotes

Operators

  • shift + c - delete to end of line, exit normal mode
  • shift + d delete to end of line
  • c - delete and exit normal mode
  • d - delete
  • cc - delete line and enter insert mode
  • dd - delete line
  • r<char> to replace - currently broken
  • x to delete char under cursor

Other

  • i to go back to insert mode
  • o - add new line below, exit normal mode
  • shift + o - add new line above, exit normal mode
  • p to paste
  • s to delete under cursor, exit normal mode
  • ^r to redo
  • u to undo
  • y to yank to clipboard
  • / to trigger cmd+f search (when cmd+f is supported in app)
  • visual mode with v
  • UTF-8 support
  • ^d - page down
  • ^u - page down
  • support prefixing commands with numbers to repeat them (e.g. 2dw)

Configuration

Here are all the configuration options available for you. Add/edit your config in ~/.hammerspoon/init.lua.

Binding jk to enter normal mode

local VimMode = hs.loadSpoon('VimMode')
local vim = VimMode:new()

vim:enterWithSequence('jk')

This sequence only watches for simple characters - it can't handle uppercase (enterWithSequence('JK')) or any other modifier keys (ctrl, shift). This is meant to handle the popularity of people binding jj, jk, or kj to entering normal mode in Vim.

The sequence also times out by default after 140ms - if you type a j and wait for the timeout, it will type the j for you. You can control the timeout like so:

-- timeout after 100ms instead. this is a nicer default for `jk`, but needs to
-- be more like 140ms for `jj` to be caught quickly enough.

vim:enterWithSequence('jk', 100)

If you have a sequence of jk and you go to type ja it will immediately pass through the ja keys without any latency either. I wanted this to work close to inoremap jk <esc>.

Binding a single keystroke to enter normal mode

-- Basic key binding to ctrl+;
-- You can choose any key binding you want here, see:
--   https://www.hammerspoon.org/docs/hs.hotkey.html#bind

vim:bindHotKeys({ enter = {{'ctrl'}, ';'} })

Forcing fallback mode for certain apps

Some apps work best in fallback mode. To force fallback mode for these apps, do:

local VimMode = hs.loadSpoon('VimMode')
local vim = VimMode:new()

-- Dwarf Fortress needs to use fallback mode :)j
vim:useFallbackMode('dwarfort.exe')

-- same w/ Chrome
vim:useFallbackMode('Google Chrome')

Disabling vim mode for certain apps

You probably want to disable this Vim mode in the terminal, or any actual instance of Vim. Calling vim:disableForApp(...) allows you to disable or enable Vim mode depending on which window is in focus.

local VimMode = hs.loadSpoon('VimMode')
local vim = VimMode:new()

-- sometimes you need to check Activity Monitor to get the app's
-- real name
vim:disableForApp('Code')
vim:disableForApp('iTerm')
vim:disableForApp('MacVim')
vim:disableForApp('Terminal')

Disabling the floating alert when you enter Vim mode(s)

local VimMode = hs.loadSpoon('VimMode')
local vim = VimMode:new()

vim:shouldShowAlertInNormalMode(false)

Enabling screen dim when you enter normal mode

This turns on a Flux-style dim when you enter normal mode.

local VimMode = hs.loadSpoon('VimMode')
local vim = VimMode:new()

vim:shouldDimScreenInNormalMode(true)

Beta Features

There are a few beta features you can try out right now and give feedback on:

Block cursor mode

This adds an experimental block cursor on top of the current character, to emulate what it looks like in Vim. This only works in fields that support Advanced Mode.

To enable:

vim:enableBetaFeature('block_cursor_overlay')

Discussed in: #63

Enforce fallback mode with URL patterns

Some websites just really need to be forced into fallback mode at all times, and the detection we have isn't good enough to do so. This may be deprecated going forward in favor of getting better field detection or handling rich fields better.

This currently only works for Chrome and Safari, as Firefox has a trash AppleScript interface.

To enable:

vim:enableBetaFeature('fallback_only_urls')

-- When entering normal mode on any URL that matches any of the patterns below,
-- we will enforce fallback mode.
vim:setFallbackOnlyUrlPatterns({
  "docs.google.com",
})

Discussed in: #71

Manual Installation

Install Hammerspoon

Next, run this in your Terminal:

mkdir -p ~/.hammerspoon/Spoons
git clone https://github.com/dbalatero/VimMode.spoon \
  ~/.hammerspoon/Spoons/VimMode.spoon

Modify your ~/.hammerspoon/init.lua file to contain the following:

local VimMode = hs.loadSpoon('VimMode')
local vim = VimMode:new()

vim
  :disableForApp('Code')
  :disableForApp('MacVim')
  :disableForApp('zoom.us')
  :enterWithSequence('jk')

Testing

There are unit tests and integration tests!

To run the unit tests:

cd VimMode.spoon

bin/dev-setup
busted spec

To run the integration tests, there is a bit of setup, which you can read about in the docs/Integration_Tests.md document. However, once you setup, it should just be:

bundle exec rspec spec

More Repositories

1

monster_mash

Provides a fun interface to quickly build API libraries using Typhoeus.
Ruby
106
star
2

dotfiles

💻dotfiles for: tmux, neovim, git, zsh, osx
Shell
57
star
3

capybara-chromedriver-logger

Enables console.log/error/info output from Javascript feature specs running with Chromedriver
Ruby
54
star
4

lingua

This is a GitHub hosted version of the Ruby lingua library.
Ruby
38
star
5

SkyRocket.spoon

Resize and move windows using the mouse and modifier keys. A Hammerspoon clone of Zooom/2 functionality.
Lua
38
star
6

cypress-plugin-stripe-elements

A small Cypress plugin that assists you in filling in Stripe Elements inputs
JavaScript
34
star
7

alchemy_api

Provides a client API library for AlchemyAPI's awesome NLP services. Allows you to make parallel or serial requests.
Ruby
31
star
8

musician_analytics

Provides tools for programmer/musicians to quickly collect stats about their band.
Ruby
21
star
9

evri_rpx

This is an API wrapper for the RPXNow.com login service (canonical repo).
Ruby
20
star
10

work-cli

Awesome command line tools for managing the lifecycle of Github pull requests.
Shell
18
star
11

HyperKey.spoon

This library allows you to bind keys to a modifier, and shows you a popup overlay of all your key binds when you hold down the modifier key.
Lua
18
star
12

light-phone-sms-gateway

A basic SMS gateway that a Light Phone 2 can text useful commands to and get responses!
Ruby
14
star
13

cirklon

Instrument definitions for the Sequentix Cirklon
Shell
10
star
14

horse

Ruby
7
star
15

signal-native

Builds a wrapped native Signal client for Mac 64-bit
JavaScript
7
star
16

musician_analytics_app

App for collecting band stats, designed to push to Heroku.
Ruby
6
star
17

queue_stick

This library allows you to write the minimal amount of code to process queue messages. Supports SQS out of the box, but it's trivial to support other queues.
Ruby
6
star
18

mac-vim-mode

Quick installer for adding Vim motions/operators to every input in OS X
Shell
5
star
19

signed_request

A simple gem that allows you to sign HTTP requests between two parties with a shared secret key.
Ruby
5
star
20

transcriptions

WHERE THE TABZ AT?!?!
4
star
21

GoogleDocsCodePaste.spoon

Hammerspoon plugin to paste syntax highlighted code into Google Docs
Lua
4
star
22

pitchspork

Right on, brotha.
3
star
23

drinking_games

Various executable drinking games.
3
star
24

uwrake

Ruby UW extension implementation of Rake
Ruby
3
star
25

uwweek5

Week 5 homework
Ruby
2
star
26

deadlinez

Makes it easy to handle After the Deadline AJAX proxying and their API.
Ruby
2
star
27

hubot-poplife

CoffeeScript
2
star
28

simple_client

Simple tcp server/client
Ruby
2
star
29

html5-metronome

A quick and dirty html5 metronome.
2
star
30

uw_log_processor

Week 4 homework for Advanced Ruby
2
star
31

fixiebotbot

Retweets fixiebot.
2
star
32

audioinfo

Quick repo for playing around with synths + MIDI.
C++
2
star
33

typhoeus_spec_cache

A plugin to help you dynamically manage HTTP caching for your specs.
Ruby
2
star
34

resume

Ohwillie's resume, not yours! Will not respond to pull requests (unless they're really good)
Ruby
1
star
35

yarr

Yarr finds album art quickly and politely and is your friend to extend.
Ruby
1
star
36

typescript-interview

JavaScript
1
star
37

fpswax

A library for interfacing with Amazon FPS, without any "cleverness".
Ruby
1
star
38

patchbay

JavaScript
1
star
39

bald-eagle-chef

The Bald Eagle Chef game.
1
star
40

opid-rotation

the op id rotations
Ruby
1
star
41

poser

A Ruby gem to assist working with the POS-IM point-of-sale system.
Ruby
1
star
42

upswax

UPS shipping wrappers.
Ruby
1
star
43

try_git

1
star
44

aid

Ruby
1
star
45

vim_fu

Vim exercises for Vim-fu.
1
star
46

kexp

A KEXP stats crawler.
Ruby
1
star
47

sqswax

An up-to-date (API version 2009-02-01) implementation of Amazon SQS.
Ruby
1
star
48

Ethan-Test

1
star