diff --git a/README.md b/README.md index 6de16c23..c96cc3fe 100644 --- a/README.md +++ b/README.md @@ -43,133 +43,159 @@ While I find that these customizations yield a more-useful keyboard for me, they These customizations currently provide a fraction of what I want from my more-useful keyboard. I find it to be a very useful fraction, but I don't consider it complete by any means. -Here's what it provides so far: +## Features -![Karabiner Change Key Configuration - 01](screenshots/karabiner-change-key-config-01.png) +- [Access **control** and **escape** on the home row](#a-more-useful-caps-lock-key) +- [Navigate (up/down/left/right) via the home row](#super-duper-mode) +- [Navigate to previous/next word via the home row](#super-duper-mode) +- [Arrange windows via the home row](#window-layout-mode) +- [Enable other commonly-used actions on or near the home row](#miscellaneous-goodness) +- [Format text as Markdown](#markdown-mode) +- [Launch commonly-used apps via global keyboard shortcuts](#hyper-key-for-quickly-launching-apps) +- [And more...](#miscellaneous-goodness) -![Karabiner Change Key Configuration - 02](screenshots/karabiner-change-key-config-02.png) +### A more useful caps lock key -![Karabiner Change Key Configuration - 03](screenshots/karabiner-change-key-config-03.png) +By repurposing the anachronistic **caps lock** key, we can make **control** and **escape** accessible via the home row. -![Karabiner Change Key Configuration - 04](screenshots/karabiner-change-key-config-04.png) +- Tap **caps lock** for **escape** +- Hold **caps lock** for **control** -## Dependencies +### (S)uper (D)uper Mode -This setup is honed and tested with the following dependencies. +To activate, push the **s** and **d** keys simultaneously and hold them down. Now you're in (S)uper (D)uper Mode. It's like a secret keyboard _inside_ your keyboard. (Whoa.) It's optimized for keeping you on the home row, or very close to it. Now you can: -- OS X El Capitan, 10.11 -- [Seil 12.1][seil] -- [Karabiner 10.21][karabiner] -- [SizeUp 1.7][sizeup] (optional) +- Use **h**/**j**/**k**/**l** for **up**/**down**/**left**/**right** respectively +- Use **a** for **option** (AKA **alt**) +- Use **f** for **command** +- Use **space** for **shift** +- Use **a** + **j**/**k** for **page down**/**page up** +- Use **i**/**o** to move to the previous/next tab +- Use **u**/**p** to go to the first/last tab (in most apps) +- Use **a** + **h**/**l** to move to previous/next word (in most apps) -## The Setup +[(S)uper (D)uper Mode Keybindings](https://cloud.githubusercontent.com/assets/2988/22397420/f2b3e346-e53e-11e6-97bb-9db71f86994b.png) -### Grab the bits +### Window Layout Mode -```sh -git clone https://github.com/jasonrudolph/keyboard.git +Quickly arrange and resize windows in common configurations, using keyboard shortcuts that are on or near the home row. -cd keyboard +Use **control** + **s** to turn on Window Layout Mode. Then, use any shortcut below to make windows do your bidding. For example, to send the window left, hit **control** + **s**, and then hit **h**. -mkdir -p ~/Library/Application\ Support/Karabiner +- Use **h** to send window left (left half of screen) +- Use **j** to send window down (bottom half of screen) +- Use **k** to send window up (top half of screen) +- Use **l** to send window right (right half of screen) +- Use **i** to send window to upper left quarter of screen +- Use **o** to send window to upper right quarter of screen +- Use **,** to send window to lower left quarter of screen +- Use **.** to send window to lower right quarter of screen +- Use **space** to send window to center of screen +- Use **enter**: Resize window to fill the screen +- Use **n** to send window to next monitor +- Use **control** + **s** to exit Window Layout Mode without moving any windows -# Prepare custom settings for Karabiner -ln -s $PWD/karabiner/private.xml \ - ~/Library/Application\ Support/Karabiner/private.xml +[Window Layout Mode Keybindings (1)](https://cloud.githubusercontent.com/assets/2988/22397114/715cc12e-e538-11e6-9dcd-b3447af0d9dd.png) [Window Layout Mode Keybindings (2)](https://cloud.githubusercontent.com/assets/2988/22397111/45672fe6-e538-11e6-905d-5b0234e290bb.png) -ln -s $PWD/karabiner/ext \ - ~/Library/Application\ Support/Karabiner/ext -``` +### Markdown Mode -### Install the apps +Perform common Markdown-formatting tasks anywhere that you're editing text (e.g. in a GitHub comment, in your editor, in your email client). -- Install [Seil][seil] -- Install [Karabiner][karabiner] -- Install [SizeUp][sizeup] (optional) +Use **control** + **m** to turn on Markdown Mode. Then, use any shortcut below to perform an action. For example, to wrap the selected text in double asterisks, hit **control** + **m**, and then **b**. -### Put _control_ and _escape_ on the home row +- Use **b** to wrap the currently-selected text in double asterisks ("B" for "Bold") -#### Goals + Example: `**selection**` -- Tap **caps lock** for **escape** -- Hold **caps lock** for **control** -- Access the default **caps lock** behavior in those rare cases where it's helpful +- Use **i** to wrap the currently-selected text in single asterisks ("I" for "Italic") -#### Making it happen + Example: `**selection**` -1. Launch Seil. -2. Enable the "Change Caps Lock" option, and map **caps lock** to keycode 80. - (80 is **F19**. I don't have a physical **F19** key, so this setting will not - conflict with any existing keys.) - [[screenshot][seil-screenshot]] -3. Launch Karabiner. -4. In the "Change Key" tab, enable the "F19 to Escape/Control" option. - [[screenshot][karabiner-change-key-screenshot-01]] -5. In the "Change Key" tab, enable the "Double-tap Left Shift for CapsLock" option. -6. In the "Key Repeat" tab, change the "[Key Overlaid Modifier] Timeout" to - 300ms. (As [recommended][modern-space-cadet-key-repeat] by Steve Losh, I find - that this avoids accidentally triggering **escape** when you meant to trigger - **control**.) - [[screenshot][karabiner-key-repeat-screenshot]] +- Use **s** to wrap the currently-selected text in double tildes ("S" for "Strikethrough") -### Unleash (S)uper (D)uper mode + Example: `~~selection~~` -#### Goals +- Use **l** to convert the currently-selected text to an inline link, using a URL from the clipboard ("L" for "Link") -- Enable navigation (up/down/left/right) via the home row -- Enable word navigation (option+left/right) via the home row -- Enable other commonly-used actions on or near the home row + Example: `[selection](clipboard)` -#### Making it happen +- Use **control** + **m** to exit Markdown Mode without performing any actions -1. Launch Karabiner. -2. In the "Change Key" tab, enable the "(S)uper (D)uper Mode" option. - [[screenshot][karabiner-change-key-screenshot-02]] +### Hyper key for quickly launching apps -### Control SizeUp from the home row +macOS doesn't have a native **hyper** key. But thanks to Karabiner-Elements, we can [create our own](karabiner/karabiner.json). -#### Goals +In this setup, we'll use the **right option** key as our **hyper** key. With a new modifier key defined, we open a whole world of possibilities. I find it especially useful for providing global shortcuts for launching apps: -- Quickly arrange and resize windows in common configurations, using keyboard - shortcuts that are on or near the home row +- **hyper** + **a** to open iTunes ("A" for "Apple Music") +- **hyper** + **b** to open Google Chrome ("B" for "Browser") +- **hyper** + **c** to open [Hackable Slack Client](https://github.com/bhuga/hackable-slack-client) ("C for "Chat") +- **hyper** + **d** to open [Remember The Milk](https://www.rememberthemilk.com/) ("D" for "Do!" ... or "Done!") +- **hyper** + **e** to open [Atom Beta](https://atom.io/beta) ("E" for "Editor") +- **hyper** + **f** to open Finder ("F" for "Finder") +- **hyper** + **g** to open [Mailplane](http://mailplaneapp.com/) ("G" for "Gmail") +- **hyper** + **t** to open [iTerm2](https://www.iterm2.com/) ("T" for "Terminal") -#### Making it happen +Edit [`hammerspoon/hyper.lua`](hammerspoon/hyper.lua) to configure shortcuts to launch your most commonly-used apps. -1. Launch Karabiner. -2. In the "Change Key" tab, enable the "SizeUp Mode" option. - [[screenshot][karabiner-change-key-screenshot-03]] +### Miscellaneous goodness -### Format text as Markdown +- Use **control** + **-** (dash) to split iTerm2 panes horizontally +- Use **control** + **|** (pipe) split iTerm2 panes vertically +- Use **control** + **h**/**j**/**k**/**l** to move left/down/up/right by one pane in iTerm2 +- Use **control** + **u** to delete to the start of the line +- Use **control** + **;** to delete to the end of the line +- Use **option** + **h**/**l** to delete the previous/next word -#### Goals +## Dependencies -- Perform common Markdown-formatting tasks anywhere that you're editing text - (e.g. in a GitHub comment, in your editor, in your email client) +This setup is honed and tested with the following dependencies. -#### Making it happen +- macOS Sierra, 10.12 +- [Karabiner-Elements 0.90.83][karabiner] +- [Hammerspoon 0.9.52][hammerspoon] -1. Launch Karabiner. -2. In the "Change Key" tab, enable the "Markdown Mode" option. - [[screenshot][karabiner-change-key-screenshot-04]] +## Installation -## TODO +1. Grab the bits + + ```sh + git clone https://github.com/jasonrudolph/keyboard.git -- Document usage of "Hyper" key -- Incorporate [Keyboard Maestro][keyboard-maestro] configuration -- Add `./script/setup` command to automate the manual setup steps + cd keyboard + + # Prepare custom settings for Karabiner-Elements + mkdir -p ~/.config/karabiner/ + ln -s $PWD/karabiner/karabiner.json ~/.config/karabiner/karabiner.json + + # Prepare custom settings for Hammerspoon + ln -s $PWD/hammerspoon ~/.hammerspoon + + # Prepare custom settings for navigating between words in iTerm2 + cat $PWD/inputrc >> ~/.inputrc + ``` + +2. Install [Karabiner-Elements][karabiner] + + 1. Install it + 2. Launch it + 3. Configure it to launch at login [[screenshot](screenshots/login-items-for-karabiner-and-hammerspoon.png)] + +3. Install [Hammerspoon][hammerspoon-releases] + + 1. Install it + 2. Launch it + 3. Configure it to launch at login [[screenshot](screenshots/login-items-for-karabiner-and-hammerspoon.png)] + 4. Enable accessibility to allow Hammerspoon to do its thing [[screenshot]](screenshots/accessibility-permissions-for-hammerspoon.png) + +## TODO +- [ ] Add `./script/setup` command to automate the manual setup steps [customize]: http://dictionary.reference.com/browse/customize [don't-make-me-think]: http://en.wikipedia.org/wiki/Don't_Make_Me_Think -[keyboard-maestro]: http://keyboardmaestro.com -[karabiner]: http://pqrs.org/macosx/karabiner/ -[karabiner-change-key-screenshot-01]: screenshots/karabiner-change-key-config-01.png -[karabiner-change-key-screenshot-02]: screenshots/karabiner-change-key-config-02.png -[karabiner-change-key-screenshot-03]: screenshots/karabiner-change-key-config-03.png -[karabiner-change-key-screenshot-04]: screenshots/karabiner-change-key-config-04.png -[karabiner-key-repeat-screenshot]: screenshots/karabiner-key-repeat-config.png +[karabiner]: https://github.com/tekezo/Karabiner-Elements +[hammerspoon]: http://www.hammerspoon.org +[hammerspoon-releases]: https://github.com/Hammerspoon/hammerspoon/releases [modern-space-cadet]: http://stevelosh.com/blog/2012/10/a-modern-space-cadet [modern-space-cadet-key-repeat]: http://stevelosh.com/blog/2012/10/a-modern-space-cadet/#controlescape -[seil]: https://pqrs.org/macosx/keyremap4macbook/seil.html.en -[seil-screenshot]: screenshots/seil-config.png -[sizeup]: http://www.irradiatedsoftware.com/sizeup/ diff --git a/hammerspoon/control-escape.lua b/hammerspoon/control-escape.lua new file mode 100644 index 00000000..e91f1c4b --- /dev/null +++ b/hammerspoon/control-escape.lua @@ -0,0 +1,43 @@ +-- Credit for this implementation goes to @arbelt and @jasoncodes 🙇⚡️😻 +-- +-- https://gist.github.com/arbelt/b91e1f38a0880afb316dd5b5732759f1 +-- https://github.com/jasoncodes/dotfiles/blob/ac9f3ac/hammerspoon/control_escape.lua + +send_escape = false +last_mods = {} + +control_key_handler = function() + send_escape = false +end + +control_key_timer = hs.timer.delayed.new(0.15, control_key_handler) + +control_handler = function(evt) + local new_mods = evt:getFlags() + if last_mods["ctrl"] == new_mods["ctrl"] then + return false + end + if not last_mods["ctrl"] then + last_mods = new_mods + send_escape = true + control_key_timer:start() + else + if send_escape then + keyUpDown({}, 'escape') + end + last_mods = new_mods + control_key_timer:stop() + end + return false +end + +control_tap = hs.eventtap.new({hs.eventtap.event.types.flagsChanged}, control_handler) +control_tap:start() + +other_handler = function(evt) + send_escape = false + return false +end + +other_tap = hs.eventtap.new({hs.eventtap.event.types.keyDown}, other_handler) +other_tap:start() diff --git a/hammerspoon/delete-words.lua b/hammerspoon/delete-words.lua new file mode 100644 index 00000000..c43a5bd0 --- /dev/null +++ b/hammerspoon/delete-words.lua @@ -0,0 +1,70 @@ +local log = hs.logger.new('delete-words.lua', 'debug') + +local isInTerminal = function() + app = hs.application.frontmostApplication():name() + return app == 'iTerm2' or app == 'Terminal' +end + +-- Use option + h to delete previous word +hs.hotkey.bind({'alt'}, 'h', function() + if isInTerminal() then + keyUpDown({'ctrl'}, 'w') + else + keyUpDown({'alt'}, 'delete') + end +end) + +-- Use option + l to delete next word +hs.hotkey.bind({'alt'}, 'l', function() + if isInTerminal() then + keyUpDown({}, 'escape') + keyUpDown({}, 'd') + else + keyUpDown({'alt'}, 'forwarddelete') + end +end) + +-- Use control + u to delete to beginning of line +-- +-- In bash, control + u automatically deletes to the beginning of the line, so +-- we don't need (or want) this hotkey in the terminal. If this hotkey was +-- enabled in the terminal, it would break the standard control + u behavior. +-- Therefore, we only enable this hotkey for non-terminal apps. +local wf = hs.window.filter.new():setFilters({iTerm2 = false, Terminal = false}) +enableHotkeyForWindowsMatchingFilter(wf, hs.hotkey.new({'ctrl'}, 'u', function() + keyUpDown({'cmd'}, 'delete') +end)) + +-- Use control + ; to delete to end of line +-- +-- I prefer to use control+h/j/k/l to move left/down/up/right by one pane in all +-- multi-pane apps (e.g., iTerm, various editors). That's convenient and +-- consistent, but it conflicts with the default macOS binding for deleting to +-- the end of the line (i.e., control+k). To maintain that very useful +-- functionality, and to keep it on the home row, this hotkey binds control+; to +-- delete to the end of the line. +hs.hotkey.bind({'ctrl'}, ';', function() + -- If we're in the terminal, then temporarily disable our custom control+k + -- hotkey used for pane navigation, then fire control+k to delete to the end + -- of the line, and then renable the control+k hotkey. + -- + -- If we're not in the terminal, then just select to the end of the line and + -- then delete the selected text. + if isInTerminal() then + hotkeyForControlK = hs.fnutils.find(hs.hotkey.getHotkeys(), function(hotkey) + return hotkey.idx == '⌃K' + end) + if hotkeyForControlK then hotkeyForControlK:disable() end + + keyUpDown({'ctrl'}, 'k') + + -- Allow some time for the control+k keystroke to fire asynchronously before + -- we re-enable our custom control+k hotkey. + hs.timer.doAfter(0.2, function() + if hotkeyForControlK then hotkeyForControlK:enable() end + end) + else + keyUpDown({'cmd', 'shift'}, 'right') + keyUpDown({}, 'forwarddelete') + end +end) diff --git a/hammerspoon/hyper.lua b/hammerspoon/hyper.lua new file mode 100644 index 00000000..2b9f106b --- /dev/null +++ b/hammerspoon/hyper.lua @@ -0,0 +1,33 @@ +-- A global variable for Hyper Mode +hyperMode = hs.hotkey.modal.new({}, 'F18') + +-- Keybindings for launching apps in Hyper Mode +hyperModeAppMappings = { + { 'a', 'iTunes' }, -- "A" for "Apple Music" + { 'b', 'Google Chrome' }, -- "B" for "Browser" + { 'c', 'Hackable Slack Client' }, -- "C for "Chat" + { 'd', 'Remember The Milk' }, -- "D" for "Do!" ... or "Done!" + { 'e', 'Atom Beta' }, -- "E" for "Editor" + { 'f', 'Finder' }, -- "F" for "Finder" + { 'g', 'Mailplane 3' }, -- "G" for "Gmail" + { 't', 'iTerm' }, -- "T" for "Terminal" +} + +for i, mapping in ipairs(hyperModeAppMappings) do + hyperMode:bind({}, mapping[1], function() + hs.application.launchOrFocus(mapping[2]) + end) +end + +-- Enter Hyper Mode when F17 (right option key) is pressed +pressedF17 = function() + hyperMode:enter() +end + +-- Leave Hyper Mode when F17 (right option key) is released. +releasedF17 = function() + hyperMode:exit() +end + +-- Bind the Hyper key +f17 = hs.hotkey.bind({}, 'F17', pressedF17, releasedF17) diff --git a/hammerspoon/init.lua b/hammerspoon/init.lua new file mode 100644 index 00000000..9be6a3e3 --- /dev/null +++ b/hammerspoon/init.lua @@ -0,0 +1,41 @@ +local log = hs.logger.new('init.lua', 'debug') + +-- Use Control+` to reload Hammerspoon config +hs.hotkey.bind({'ctrl'}, '`', nil, function() + hs.reload() +end) + +keyUpDown = function(modifiers, key) + -- Un-comment & reload config to log each keystroke that we're triggering + -- log.d('Sending keystroke:', hs.inspect(modifiers), key) + hs.eventtap.keyStroke(modifiers, key, 0) +end + +-- Subscribe to the necessary events on the given window filter such that the +-- given hotkey is enabled for windows that match the window filter and disabled +-- for windows that don't match the window filter. +-- +-- windowFilter - An hs.window.filter object describing the windows for which +-- the hotkey should be enabled. +-- hotkey - The hs.hotkey object to enable/disable. +-- +-- Returns nothing. +enableHotkeyForWindowsMatchingFilter = function(windowFilter, hotkey) + windowFilter:subscribe(hs.window.filter.windowFocused, function() + hotkey:enable() + end) + + windowFilter:subscribe(hs.window.filter.windowUnfocused, function() + hotkey:disable() + end) +end + +require('control-escape') +require('delete-words') +require('hyper') +require('markdown') +require('panes') +require('super') +require('windows') + +hs.notify.new({title='Hammerspoon', informativeText='Ready to rock 🤘'}):send() diff --git a/hammerspoon/markdown.lua b/hammerspoon/markdown.lua new file mode 100644 index 00000000..1945b22b --- /dev/null +++ b/hammerspoon/markdown.lua @@ -0,0 +1,107 @@ +function wrapSelectedText(wrapCharacters) + -- Preserve the current contents of the system clipboard + local originalClipboardContents = hs.pasteboard.getContents() + + -- Copy the currently-selected text to the system clipboard + keyUpDown('cmd', 'c') + + -- Allow some time for the command+c keystroke to fire asynchronously before + -- we try to read from the clipboard + hs.timer.doAfter(0.2, function() + -- Construct the formatted output and paste it over top of the + -- currently-selected text + local selectedText = hs.pasteboard.getContents() + local wrappedText = wrapCharacters .. selectedText .. wrapCharacters + hs.pasteboard.setContents(wrappedText) + keyUpDown('cmd', 'v') + + -- Allow some time for the command+v keystroke to fire asynchronously before + -- we restore the original clipboard + hs.timer.doAfter(0.2, function() + hs.pasteboard.setContents(originalClipboardContents) + end) + end) +end + +function inlineLink() + -- Fetch URL from the system clipboard + local linkUrl = hs.pasteboard.getContents() + + -- Copy the currently-selected text to use as the link text + keyUpDown('cmd', 'c') + + -- Allow some time for the command+c keystroke to fire asynchronously before + -- we try to read from the clipboard + hs.timer.doAfter(0.2, function() + -- Construct the formatted output and paste it over top of the + -- currently-selected text + local linkText = hs.pasteboard.getContents() + local markdown = '[' .. linkText .. '](' .. linkUrl .. ')' + hs.pasteboard.setContents(markdown) + keyUpDown('cmd', 'v') + + -- Allow some time for the command+v keystroke to fire asynchronously before + -- we restore the original clipboard + hs.timer.doAfter(0.2, function() + hs.pasteboard.setContents(originalClipboardContents) + end) + end) +end + +-------------------------------------------------------------------------------- +-- Define Markdown Mode +-- +-- Markdown Mode allows you to perform common Markdown-formatting tasks anywhere +-- that you're editing text. Use Control+m to turn on Markdown mode. Then, use +-- any shortcut below to perform a formatting action. For example, to wrap the +-- selected text in double asterisks, hit Control+m, and then b. +-- +-- b => wrap the selected text in double asterisks ("b" for "bold") +-- i => wrap the selected text in single asterisks ("i" for "italic") +-- s => wrap the selected text in double tildes ("s" for "strikethrough") +-- l => convert the currently-selected text to an inline link, using a URL +-- from the clipboard ("l" for "link") +-------------------------------------------------------------------------------- + +markdownMode = hs.hotkey.modal.new({}, 'F20') + +local message = require('status-message') +markdownMode.statusMessage = message.new('Markdown Mode (control-m)') +markdownMode.entered = function() + markdownMode.statusMessage:show() +end +markdownMode.exited = function() + markdownMode.statusMessage:hide() +end + +-- Bind the given key to call the given function and exit Markdown mode +function markdownMode.bindWithAutomaticExit(mode, key, fn) + mode:bind({}, key, function() + mode:exit() + fn() + end) +end + +markdownMode:bindWithAutomaticExit('b', function() + wrapSelectedText('**') +end) + +markdownMode:bindWithAutomaticExit('i', function() + wrapSelectedText('*') +end) + +markdownMode:bindWithAutomaticExit('s', function() + wrapSelectedText('~~') +end) + +markdownMode:bindWithAutomaticExit('l', function() + inlineLink() +end) + +-- Use Control+m to toggle Markdown Mode +hs.hotkey.bind({'ctrl'}, 'm', function() + markdownMode:enter() +end) +markdownMode:bind({'ctrl'}, 'm', function() + markdownMode:exit() +end) diff --git a/hammerspoon/panes.lua b/hammerspoon/panes.lua new file mode 100644 index 00000000..cc31ffe6 --- /dev/null +++ b/hammerspoon/panes.lua @@ -0,0 +1,43 @@ +local itermHotkeyMappings = { + -- Use control + dash to split panes horizontally + { + from = {{'ctrl'}, '-'}, + to = {{'cmd', 'shift'}, 'd'} + }, + + -- Use control + pipe to split panes vertically + { + from = {{'ctrl', 'shift'}, '\\'}, + to = {{'cmd'}, 'd'} + }, + + -- Use control + h/j/k/l to move left/down/up/right by one pane + { + from = {{'ctrl'}, 'h'}, + to = {{'cmd', 'alt'}, 'left'} + }, + { + from = {{'ctrl'}, 'j'}, + to = {{'cmd', 'alt'}, 'down'} + }, + { + from = {{'ctrl'}, 'k'}, + to = {{'cmd', 'alt'}, 'up'} + }, + { + from = {{'ctrl'}, 'l'}, + to = {{'cmd', 'alt'}, 'right'} + }, +} + +local terminalWindowFilter = hs.window.filter.new('iTerm2') +local itermHotkeys = hs.fnutils.each(itermHotkeyMappings, function(mapping) + local fromMods = mapping['from'][1] + local fromKey = mapping['from'][2] + local toMods = mapping['to'][1] + local toKey = mapping['to'][2] + local hotkey = hs.hotkey.new(fromMods, fromKey, function() + keyUpDown(toMods, toKey) + end) + enableHotkeyForWindowsMatchingFilter(terminalWindowFilter, hotkey) +end) diff --git a/hammerspoon/status-message.lua b/hammerspoon/status-message.lua new file mode 100644 index 00000000..f317de8b --- /dev/null +++ b/hammerspoon/status-message.lua @@ -0,0 +1,62 @@ +local drawing = require 'hs.drawing' +local geometry = require 'hs.geometry' +local screen = require 'hs.screen' +local styledtext = require 'hs.styledtext' + +local statusmessage = {} +statusmessage.new = function(messageText) + local buildParts = function(messageText) + local frame = screen.primaryScreen():frame() + + local styledTextAttributes = { + font = { name = 'Monaco', size = 24 }, + } + + local styledText = styledtext.new('🔨 ' .. messageText, styledTextAttributes) + + local styledTextSize = drawing.getTextDrawingSize(styledText) + local textRect = { + x = frame.w - styledTextSize.w - 40, + y = frame.h - styledTextSize.h, + w = styledTextSize.w + 40, + h = styledTextSize.h + 40, + } + local text = drawing.text(textRect, styledText):setAlpha(0.7) + + local background = drawing.rectangle( + { + x = frame.w - styledTextSize.w - 45, + y = frame.h - styledTextSize.h - 3, + w = styledTextSize.w + 15, + h = styledTextSize.h + 6 + } + ) + background:setRoundedRectRadii(10, 10) + background:setFillColor({ red = 0, green = 0, blue = 0, alpha=0.6 }) + + return background, text + end + + return { + _buildParts = buildParts, + show = function(self) + self:hide() + + self.background, self.text = self._buildParts(messageText) + self.background:show() + self.text:show() + end, + hide = function(self) + if self.background then + self.background:delete() + self.background = nil + end + if self.text then + self.text:delete() + self.text = nil + end + end + } +end + +return statusmessage diff --git a/hammerspoon/super.lua b/hammerspoon/super.lua new file mode 100644 index 00000000..5d0cdd89 --- /dev/null +++ b/hammerspoon/super.lua @@ -0,0 +1,164 @@ +local eventtap = hs.eventtap +local eventTypes = hs.eventtap.event.types +local message = require('status-message') + +-- If 's' and 'd' are *both* pressed within this time period, consider this to +-- mean that they've been pressed simultaneously, and therefore we should enter +-- Super Duper Mode. +local MAX_TIME_BETWEEN_SIMULTANEOUS_KEY_PRESSES = 0.02 -- 20 milliseconds + +local superDuperMode = { + statusMessage = message.new('(S)uper (D)uper Mode'), + enter = function(self) + if not self.active then self.statusMessage:show() end + self.active = true + end, + reset = function(self) + self.active = false + self.isSDown = false + self.isDDown = false + self.ignoreNextS = false + self.ignoreNextD = false + self.modifiers = {} + self.statusMessage:hide() + end, +} +superDuperMode:reset() + +superDuperModeActivationListener = eventtap.new({ eventTypes.keyDown }, function(event) + -- If 's' or 'd' is pressed in conjuction with any modifier keys + -- (e.g., command+s), then we're not activating Super Duper Mode. + if not (next(event:getFlags()) == nil) then + return false + end + + local characters = event:getCharacters() + + if characters == 's' then + if superDuperMode.ignoreNextS then + superDuperMode.ignoreNextS = false + return false + end + -- Temporarily suppress this 's' keystroke. At this point, we're not sure if + -- the user intends to type an 's', or if the user is attempting to activate + -- Super Duper Mode. If 'd' is pressed by the time the following function + -- executes, then activate Super Duper Mode. Otherwise, trigger an ordinary + -- 's' keystroke. + superDuperMode.isSDown = true + hs.timer.doAfter(MAX_TIME_BETWEEN_SIMULTANEOUS_KEY_PRESSES, function() + if superDuperMode.isDDown then + superDuperMode:enter() + else + superDuperMode.ignoreNextS = true + keyUpDown({}, 's') + return false + end + end) + return true + elseif characters == 'd' then + if superDuperMode.ignoreNextD then + superDuperMode.ignoreNextD = false + return false + end + -- Temporarily suppress this 'd' keystroke. At this point, we're not sure if + -- the user intends to type a 'd', or if the user is attempting to activate + -- Super Duper Mode. If 's' is pressed by the time the following function + -- executes, then activate Super Duper Mode. Otherwise, trigger an ordinary + -- 'd' keystroke. + superDuperMode.isDDown = true + hs.timer.doAfter(MAX_TIME_BETWEEN_SIMULTANEOUS_KEY_PRESSES, function() + if superDuperMode.isSDown then + superDuperMode:enter() + else + superDuperMode.ignoreNextD = true + keyUpDown({}, 'd') + return false + end + end) + return true + end +end):start() + +superDuperModeDeactivationListener = eventtap.new({ eventTypes.keyUp }, function(event) + local characters = event:getCharacters() + if characters == 's' or characters == 'd' then + superDuperMode:reset() + end +end):start() + +-------------------------------------------------------------------------------- +-- Watch for key down/up events that represent modifiers in Super Duper Mode +-------------------------------------------------------------------------------- +superDuperModeModifierKeyListener = eventtap.new({ eventTypes.keyDown, eventTypes.keyUp }, function(event) + if not superDuperMode.active then + return false + end + + local charactersToModifers = {} + charactersToModifers['a'] = 'alt' + charactersToModifers['f'] = 'cmd' + charactersToModifers[' '] = 'shift' + + local modifier = charactersToModifers[event:getCharacters()] + if modifier then + if (event:getType() == eventTypes.keyDown) then + superDuperMode.modifiers[modifier] = true + else + superDuperMode.modifiers[modifier] = nil + end + return true + end +end):start() + +-------------------------------------------------------------------------------- +-- Watch for h/j/k/l key down events in Super Duper Mode, and trigger the +-- corresponding arrow key events +-------------------------------------------------------------------------------- +superDuperModeNavListener = eventtap.new({ eventTypes.keyDown }, function(event) + if not superDuperMode.active then + return false + end + + local charactersToKeystrokes = { + h = 'left', + j = 'down', + k = 'up', + l = 'right', + } + + local keystroke = charactersToKeystrokes[event:getCharacters()] + if keystroke then + local modifiers = {} + n = 0 + for k, v in pairs(superDuperMode.modifiers) do + n = n + 1 + modifiers[n] = k + end + + keyUpDown(modifiers, keystroke) + return true + end +end):start() + +-------------------------------------------------------------------------------- +-- Watch for i/o key down events in Super Duper Mode, and trigger the +-- corresponding key events to navigate to the previous/next tab respectively +-------------------------------------------------------------------------------- +superDuperModeTabNavKeyListener = eventtap.new({ eventTypes.keyDown }, function(event) + if not superDuperMode.active then + return false + end + + local charactersToKeystrokes = { + u = { {'cmd'}, '1' }, -- go to first tab + i = { {'cmd', 'shift'}, '[' }, -- go to previous tab + o = { {'cmd', 'shift'}, ']' }, -- go to next tab + p = { {'cmd'}, '9' }, -- go to last tab + } + local keystroke = charactersToKeystrokes[event:getCharacters()] + + if keystroke then + keyUpDown(table.unpack(keystroke)) + return true + end +end):start() diff --git a/hammerspoon/windows.lua b/hammerspoon/windows.lua new file mode 100644 index 00000000..2b90ccda --- /dev/null +++ b/hammerspoon/windows.lua @@ -0,0 +1,257 @@ +hs.window.animationDuration = 0 + +-- +-----------------+ +-- | | | +-- | HERE | | +-- | | | +-- +-----------------+ +function hs.window.left(win) + local f = win:frame() + local screen = win:screen() + local max = screen:frame() + + f.x = max.x + f.y = max.y + f.w = max.w / 2 + f.h = max.h + win:setFrame(f) +end + +-- +-----------------+ +-- | | | +-- | | HERE | +-- | | | +-- +-----------------+ +function hs.window.right(win) + local f = win:frame() + local screen = win:screen() + local max = screen:frame() + + f.x = max.x + (max.w / 2) + f.y = max.y + f.w = max.w / 2 + f.h = max.h + win:setFrame(f) +end + +-- +-----------------+ +-- | HERE | +-- +-----------------+ +-- | | +-- +-----------------+ +function hs.window.up(win) + local f = win:frame() + local screen = win:screen() + local max = screen:frame() + + f.x = max.x + f.w = max.w + f.y = max.y + f.h = max.h / 2 + win:setFrame(f) +end + +-- +-----------------+ +-- | | +-- +-----------------+ +-- | HERE | +-- +-----------------+ +function hs.window.down(win) + local f = win:frame() + local screen = win:screen() + local max = screen:frame() + + f.x = max.x + f.w = max.w + f.y = max.y + (max.h / 2) + f.h = max.h / 2 + win:setFrame(f) +end + +-- +-----------------+ +-- | HERE | | +-- +--------+ | +-- | | +-- +-----------------+ +function hs.window.upLeft(win) + local f = win:frame() + local screen = win:screen() + local max = screen:fullFrame() + + f.x = 0 + f.y = 0 + f.w = max.w/2 + f.h = max.h/2 + win:setFrame(f) +end + +-- +-----------------+ +-- | | +-- +--------+ | +-- | HERE | | +-- +-----------------+ +function hs.window.downLeft(win) + local f = win:frame() + local screen = win:screen() + local max = screen:fullFrame() + + f.x = 0 + f.y = max.h/2 + f.w = max.w/2 + f.h = max.h/2 + win:setFrame(f) +end + +-- +-----------------+ +-- | | +-- | +--------| +-- | | HERE | +-- +-----------------+ +function hs.window.downRight(win) + local f = win:frame() + local screen = win:screen() + local max = screen:fullFrame() + + f.x = max.w/2 + f.y = max.h/2 + f.w = max.w/2 + f.h = max.h/2 + + win:setFrame(f) +end + +-- +-----------------+ +-- | | HERE | +-- | +--------| +-- | | +-- +-----------------+ +function hs.window.upRight(win) + local f = win:frame() + local screen = win:screen() + local max = screen:fullFrame() + + f.x = max.w/2 + f.y = 0 + f.w = max.w/2 + f.h = max.h/2 + win:setFrame(f) +end + +-- +--------------+ +-- | | | | +-- | | HERE | | +-- | | | | +-- +---------------+ +function hs.window.centerWithFullHeight(win) + local f = win:frame() + local screen = win:screen() + local max = screen:fullFrame() + + f.x = max.w * 1/5 + f.w = max.w * 3/5 + f.y = max.y + f.h = max.h + win:setFrame(f) +end + +function hs.window.nextScreen(win) + local currentScreen = win:screen() + local allScreens = hs.screen.allScreens() + currentScreenIndex = hs.fnutils.indexOf(allScreens, currentScreen) + nextScreenIndex = currentScreenIndex + 1 + + if allScreens[nextScreenIndex] then + win:moveToScreen(allScreens[nextScreenIndex]) + else + win:moveToScreen(allScreens[1]) + end +end + +-------------------------------------------------------------------------------- +-- Define WindowLayout Mode +-- +-- WindowLayout Mode allows you to manage window layout using keyboard shortcuts +-- that are on the home row, or very close to it. Use Control+s to turn +-- on WindowLayout mode. Then, use any shortcut below to perform a window layout +-- action. For example, to send the window left, press and release +-- Control+s, and then press h. +-- +-- h/j/k/l => send window to the left/bottom/top/right half of the screen +-- i => send window to the upper left quarter of the screen +-- o => send window to the upper right quarter of the screen +-- , => send window to the lower left quarter of the screen +-- . => send window to the lower right quarter of the screen +-- return => make window full screen +-- n => send window to the next monitor +-------------------------------------------------------------------------------- + +windowLayoutMode = hs.hotkey.modal.new({}, 'F16') + +local message = require('status-message') +windowLayoutMode.statusMessage = message.new('Window Layout Mode (control-s)') +windowLayoutMode.entered = function() + windowLayoutMode.statusMessage:show() +end +windowLayoutMode.exited = function() + windowLayoutMode.statusMessage:hide() +end + +-- Bind the given key to call the given function and exit WindowLayout mode +function windowLayoutMode.bindWithAutomaticExit(mode, key, fn) + mode:bind({}, key, function() + mode:exit() + fn() + end) +end + +windowLayoutMode:bindWithAutomaticExit('return', function() + hs.window.focusedWindow():maximize() +end) + +windowLayoutMode:bindWithAutomaticExit('space', function() + hs.window.focusedWindow():centerWithFullHeight() +end) + +windowLayoutMode:bindWithAutomaticExit('h', function() + hs.window.focusedWindow():left() +end) + +windowLayoutMode:bindWithAutomaticExit('j', function() + hs.window.focusedWindow():down() +end) + +windowLayoutMode:bindWithAutomaticExit('k', function() + hs.window.focusedWindow():up() +end) + +windowLayoutMode:bindWithAutomaticExit('l', function() + hs.window.focusedWindow():right() +end) + +windowLayoutMode:bindWithAutomaticExit('i', function() + hs.window.focusedWindow():upLeft() +end) + +windowLayoutMode:bindWithAutomaticExit('o', function() + hs.window.focusedWindow():upRight() +end) + +windowLayoutMode:bindWithAutomaticExit(',', function() + hs.window.focusedWindow():downLeft() +end) + +windowLayoutMode:bindWithAutomaticExit('.', function() + hs.window.focusedWindow():downRight() +end) + +windowLayoutMode:bindWithAutomaticExit('n', function() + hs.window.focusedWindow():nextScreen() +end) + +-- Use Control+s to toggle WindowLayout Mode +hs.hotkey.bind({'ctrl'}, 's', function() + windowLayoutMode:enter() +end) +windowLayoutMode:bind({'ctrl'}, 's', function() + windowLayoutMode:exit() +end) diff --git a/inputrc b/inputrc new file mode 100644 index 00000000..d5b7efad --- /dev/null +++ b/inputrc @@ -0,0 +1,7 @@ +# Configure option + right arrow to move forward one word in iTerm2 +# https://www.gnu.org/software/bash/manual/bashref.html#Commands-For-Moving +"\e\e[C": forward-word + +# Configure option + left arrow to move backward one word in iTerm2 +# https://www.gnu.org/software/bash/manual/bashref.html#Commands-For-Moving +"\e\e[D": backward-word diff --git a/karabiner/ext/markdown_inline_link b/karabiner/ext/markdown_inline_link deleted file mode 100755 index 1863a3c0..00000000 --- a/karabiner/ext/markdown_inline_link +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -# Get URL from clipboard -LINK_URL=`/usr/bin/pbpaste` - -# Copy currently-selected text to use as the link text -osascript -e 'tell application "System Events" to keystroke "c" using command down' -sleep 0.1 # allow some time for async applescript to complete -LINK_TEXT=`/usr/bin/pbpaste` - -# Construct the formatted link and paste it over top of the currently-selected text -/bin/echo -n "[${LINK_TEXT}](${LINK_URL})" | /usr/bin/pbcopy -osascript -e 'tell application "System Events" to keystroke "v" using command down' -sleep 0.1 # allow some time for async applescript to complete - -# Restore the clipboard to its original state -echo $LINK_URL | /usr/bin/pbcopy diff --git a/karabiner/ext/markdown_reference_link b/karabiner/ext/markdown_reference_link deleted file mode 100755 index 39220a07..00000000 --- a/karabiner/ext/markdown_reference_link +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -LINK_LABEL=$1 - -# Get URL from clipboard -LINK_URL=`/usr/bin/pbpaste` - -# Copy currently-selected text to use as the link text -osascript -e 'tell application "System Events" to keystroke "c" using command down' -sleep 0.1 # allow some time for async applescript to complete -LINK_TEXT=`/usr/bin/pbpaste` - -# Construct the formatted link and paste it over top of the currently-selected text -/bin/echo -n "[${LINK_TEXT}][${LINK_LABEL}]" | /usr/bin/pbcopy -osascript -e 'tell application "System Events" to keystroke "v" using command down' -sleep 0.1 # allow some time for async applescript to complete - -# Construct the link definition and paste it at the bottom of the document -/bin/echo -n "[${LINK_LABEL}]: ${LINK_URL}" | /usr/bin/pbcopy -osascript \ - -e 'tell application "System Events"' \ - -e 'keystroke (ASCII character 31) using command down' \ - -e 'keystroke return' \ - -e 'keystroke "v" using command down' \ - -e 'end tell' -sleep 0.1 # allow some time for async applescript to complete - -# Restore the clipboard to its original state -echo $LINK_URL | /usr/bin/pbcopy diff --git a/karabiner/ext/open_selected_url b/karabiner/ext/open_selected_url deleted file mode 100755 index 27e8caff..00000000 --- a/karabiner/ext/open_selected_url +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -ORIGINAL_CLIPBOARD=`/usr/bin/pbpaste` - -# Copy currently-selected URL -osascript -e 'tell application "System Events" to keystroke "c" using command down' -sleep 0.1 # allow some time for async applescript to complete -URL=`/usr/bin/pbpaste` - -open $URL - -# Restore the clipboard to its original state -echo $ORIGINAL_CLIPBOARD | /usr/bin/pbcopy diff --git a/karabiner/ext/wrap_selected_text b/karabiner/ext/wrap_selected_text deleted file mode 100755 index 10b1ecf0..00000000 --- a/karabiner/ext/wrap_selected_text +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -WRAP_CHARACTERS=$1 - -ORIGINAL_CLIPBOARD=`/usr/bin/pbpaste` - -# Copy currently-selected text -osascript -e 'tell application "System Events" to keystroke "c" using command down' -sleep 0.1 # allow some time for async applescript to complete -TEXT=`/usr/bin/pbpaste` - -# Construct the formatted output and paste it over top of the currently-selected text -/bin/echo -n "${WRAP_CHARACTERS}${TEXT}${WRAP_CHARACTERS}" | /usr/bin/pbcopy -osascript -e 'tell application "System Events" to keystroke "v" using command down' -sleep 0.1 # allow some time for async applescript to complete - -echo $ORIGINAL_CLIPBOARD | /usr/bin/pbcopy diff --git a/karabiner/karabiner.json b/karabiner/karabiner.json new file mode 100644 index 00000000..e196c217 --- /dev/null +++ b/karabiner/karabiner.json @@ -0,0 +1,42 @@ +{ + "profiles": [ + { + "devices": [ + { + "disable_built_in_keyboard_if_exists": false, + "identifiers": { + "is_keyboard": true, + "is_pointing_device": false, + "product_id": 276, + "vendor_id": 4176 + }, + "ignore": true + } + ], + "fn_function_keys": { + "f1": "vk_consumer_brightness_down", + "f10": "mute", + "f11": "volume_down", + "f12": "volume_up", + "f2": "vk_consumer_brightness_up", + "f3": "vk_mission_control", + "f4": "vk_launchpad", + "f5": "vk_consumer_illumination_down", + "f6": "vk_consumer_illumination_up", + "f7": "vk_consumer_previous", + "f8": "vk_consumer_play", + "f9": "vk_consumer_next" + }, + "name": "Default profile", + "selected": true, + "simple_modifications": { + "caps_lock": "left_control", + "right_option": "f17" + }, + "virtual_hid_keyboard": { + "caps_lock_delay_milliseconds": 0, + "keyboard_type": "ansi" + } + } + ] +} diff --git a/karabiner/private.xml b/karabiner/private.xml deleted file mode 100644 index 91b49b0c..00000000 --- a/karabiner/private.xml +++ /dev/null @@ -1,742 +0,0 @@ - - - - - KeyCode::VK_OPEN_URL_APP_Atom - /Applications/Atom Beta.app - - - KeyCode::VK_OPEN_URL_APP_Chrome - /Applications/Google Chrome.app - - - KeyCode::VK_OPEN_URL_APP_iTerm - /Applications/iTerm.app - - - KeyCode::VK_OPEN_URL_APP_Mailplane - /Applications/Mailplane 3.app - - - KeyCode::VK_OPEN_URL_APP_Slack - /Applications/Slack.app - - - KeyCode::VK_OPEN_URL_APP_Remember_The_Milk - /Applications/Remember The Milk.app - - - - KEYBOARD_KARABINER_EXT_PATH - {{ ENV_HOME }}/Library/Application\ Support/Karabiner/ext - - - VERIFY_AND_EXECUTE_EXTENSION - - - - - - - - F19 to Escape/Control - Tap F19 for Escape; Hold F19 for Control - (Recommendation: Use Seil to remap Caps Lock to F19.) - com.jasonrudolph.f192f19_escape_or_control - - --KeyOverlaidModifier-- - KeyCode::F19, - KeyCode::CONTROL_L, - KeyCode::ESCAPE - - - - - Double-tap Left Shift for CapsLock - com.jasonrudolph.double_lshift_to_caps - __DoublePressModifier__ KeyCode::SHIFT_L, KeyCode::SHIFT_L, KeyCode::CAPSLOCK - - - - - Hyper Mode - - OS X doesn't have a native Hyper key. Let's define Hyper as Control+Shift+Option+Command. - With a new modifier key defined, we open a whole world of possibilities. - - - - - Right Option to Hyper - com.jasonrudolph.right_option_hyper - - __KeyToKey__ - KeyCode::OPTION_R, ModifierFlag::OPTION_R | ModifierFlag::NONE, - KeyCode::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L - - - - - Hyper+A to open iTunes ("A" for "Apple Music") - com.jasonrudolph.hyper_a - - __KeyToKey__ - KeyCode::A, ModifierFlag::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::VK_OPEN_URL_APP_iTunes, - - - - - Hyper+B to open Chrome ("B" for "Browser") - com.jasonrudolph.hyper_b - - __KeyToKey__ - KeyCode::B, ModifierFlag::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::VK_OPEN_URL_APP_Chrome, - - - - - Hyper+C to open Slack ("C" for "Chat") - com.jasonrudolph.hyper_c - - __KeyToKey__ - KeyCode::C, ModifierFlag::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::VK_OPEN_URL_APP_Slack, - - - - - Hyper+D to open Remember The Milk ("D" for "Do!" ... or Done!") - com.jasonrudolph.hyper_d - - __KeyToKey__ - KeyCode::D, ModifierFlag::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::VK_OPEN_URL_APP_Remember_The_Milk, - - - - - Hyper+E to open Atom ("E" for "Editor") - com.jasonrudolph.hyper_e - - __KeyToKey__ - KeyCode::E, ModifierFlag::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::VK_OPEN_URL_APP_Atom, - - - - - Hyper+F to open Finder ("F" for "Finder") - com.jasonrudolph.hyper_f - - __KeyToKey__ - KeyCode::F, ModifierFlag::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::VK_OPEN_URL_APP_Finder, - - - - - Hyper+G to open Mailplane ("G" for "Gmail") - com.jasonrudolph.hyper_g - - __KeyToKey__ - KeyCode::G, ModifierFlag::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::VK_OPEN_URL_APP_Mailplane, - - - - - Hyper+T to open iTerm ("T" for "Terminal") - com.jasonrudolph.hyper_t - - __KeyToKey__ - KeyCode::T, ModifierFlag::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::VK_OPEN_URL_APP_iTerm, - - - - - - KeyCode::VK_OPEN_URL_SHELL_open_selected_url - yy - - - - - - Option+O to open currently-selected text as URL - com.jasonrudolph.option_with_o_to_open_selected_url - - __KeyToKey__ - KeyCode::O, ModifierFlag::OPTION_L | ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_open_selected_url - - - - - - Control+; to delete to end of line - com.jasonrudolph.control_with_semicolon_to_delete_to_end_of_line - - TERMINAL - - __KeyToKey__ - KeyCode::SEMICOLON, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_CONTROL | ModifierFlag::NONE, - KeyCode::CURSOR_RIGHT, ModifierFlag::COMMAND_L | ModifierFlag::SHIFT_L, KeyCode::FORWARD_DELETE - - - - TERMINAL - - __KeyToKey__ - KeyCode::SEMICOLON, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_CONTROL | ModifierFlag::NONE, - KeyCode::K, ModifierFlag::CONTROL_L, - Option::NOREPEAT - - - - - - Option+H/L to delete previous/next word in iTerm 2 (and Terminal) - com.jasonrudolph.terminal.option_with_h_or_l_to_delete_previous_word_or_next_word - TERMINAL - - - - __KeyToKey__ - KeyCode::H, ModifierFlag::OPTION_L | ModifierFlag::NONE, - KeyCode::W, ModifierFlag::CONTROL_L - - - __KeyToKey__ - KeyCode::L, ModifierFlag::OPTION_L | ModifierFlag::NONE, - KeyCode::ESCAPE, - KeyCode::D - - - - - Option+H/L to delete previous/next word - com.jasonrudolph.option_with_h_or_l_to_delete_previous_word_or_next_word - - - - __KeyToKey__ - KeyCode::H, ModifierFlag::OPTION_L | ModifierFlag::NONE, - KeyCode::DELETE, ModifierFlag::OPTION_L - - - __KeyToKey__ - KeyCode::L, ModifierFlag::OPTION_L | ModifierFlag::NONE, - KeyCode::FORWARD_DELETE, ModifierFlag::OPTION_L - - - - - Control+dash/pipe to split iTerm2 panes horizontally/vertically - com.jasonrudolph.iterm.control_with_dash_or_pipe_to_split_pane - TERMINAL - - __KeyToKey__ - KeyCode::MINUS, ModifierFlag::CONTROL_L, - KeyCode::D, ModifierFlag::COMMAND_L | ModifierFlag::SHIFT_L - - - __KeyToKey__ - KeyCode::BACKSLASH, ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L, - KeyCode::D, ModifierFlag::COMMAND_L | ModifierFlag::NONE - - - - - Control+H/J/K/L to move left/up/down/right by one pane in iTerm 2 - com.jasonrudolph.iterm.control_with_h_or_j_or_k_or_l_to_move_between_panes - TERMINAL - - __KeyToKey__ - KeyCode::H, ModifierFlag::CONTROL_L, - KeyCode::CURSOR_LEFT, ModifierFlag::COMMAND_L | ModifierFlag::OPTION_L - - - __KeyToKey__ - KeyCode::J, ModifierFlag::CONTROL_L, - KeyCode::CURSOR_DOWN, ModifierFlag::COMMAND_L | ModifierFlag::OPTION_L - - - __KeyToKey__ - KeyCode::K, ModifierFlag::CONTROL_L, - KeyCode::CURSOR_UP, ModifierFlag::COMMAND_L | ModifierFlag::OPTION_L - - - __KeyToKey__ - KeyCode::L, ModifierFlag::CONTROL_L, - KeyCode::CURSOR_RIGHT, ModifierFlag::COMMAND_L | ModifierFlag::OPTION_L - - - - - - (S)uper (D)uper Mode - - What's (S)uper (D)uper Mode? - notsave.com.jasonrudolph.simultaneouskeypresses_vimode - __ShowStatusMessage__ (S)uper (D)uper Mode - - To activate, push S and D keys simultaneously and hold them down. - Now you're in (S)uper (D)uper mode. It's like a secret keyboard _inside_ your keyboard. (Whoa.) - It's optimized for keeping you on the home row, or very close to it. - --- - Now you can: - - Use H/J/K/L for Left/Down/Up/Right - - Use F for Command - - Use A for Option (AKA Alt) - - Use Space for Shift - - Use M to copy - - Use , to paste - - Use MM to copy current line - - Use A+J/K for Page Down/Up - - Use I/O to move left/right between tabs - - Use U/P to go to the first/last tab (in most apps) - - Use A+H/L to move to previous/next word in all apps (including iTerm 2) - - __KeyToKey__ KeyCode::A, KeyCode::OPTION_L - - - TERMINAL - - --KeyToKey-- - {{VI_H}}, VK_OPTION | ModifierFlag::NONE, - KeyCode::ESCAPE, - KeyCode::B - - - --KeyToKey-- - {{VI_L}}, VK_OPTION | ModifierFlag::NONE, - KeyCode::ESCAPE, - KeyCode::F - - - - - - com.jasonrudolph.simultaneouskeypresses_vimode.option.slack_jk - Slack - - __KeyToKey__ - {{VI_J}}, VK_OPTION | ModifierFlag::NONE, - KeyCode::CURSOR_DOWN, ModifierFlag::OPTION_L, - - - --KeyToKey-- - {{VI_K}}, VK_OPTION | ModifierFlag::NONE, - KeyCode::CURSOR_UP, ModifierFlag::OPTION_L, - - - - - __KeyToKey__ - {{VI_J}}, VK_OPTION | ModifierFlag::NONE, - KeyCode::PAGEDOWN - - - __KeyToKey__ - {{VI_K}}, VK_OPTION | ModifierFlag::NONE, - KeyCode::PAGEUP - - - __KeyToKey__ {{VI_H}}, KeyCode::CURSOR_LEFT - __KeyToKey__ {{VI_J}}, KeyCode::CURSOR_DOWN - __KeyToKey__ {{VI_K}}, KeyCode::CURSOR_UP - __KeyToKey__ {{VI_L}}, KeyCode::CURSOR_RIGHT - - __KeyToKey__ KeyCode::F, KeyCode::COMMAND_L - - __KeyToKey__ KeyCode::SPACE, KeyCode::SHIFT_L - - - KeyCode::M - Millisecond::RawValue::200 - - __KeyToKey__ - KeyCode::M, - KeyCode::CURSOR_LEFT, ModifierFlag::COMMAND_L, - KeyCode::CURSOR_DOWN, ModifierFlag::SHIFT_L, - KeyCode::C, ModifierFlag::COMMAND_L - - - - __KeyToKey__ - KeyCode::M, - KeyCode::C, ModifierFlag::COMMAND_L - - - - __KeyToKey__ - KeyCode::COMMA, - KeyCode::V, ModifierFlag::COMMAND_L - - - - __KeyToKey__ - KeyCode::I, - KeyCode::BRACKET_LEFT, ModifierFlag::COMMAND_L | ModifierFlag::SHIFT_L - - - __KeyToKey__ - KeyCode::O, - KeyCode::BRACKET_RIGHT, ModifierFlag::COMMAND_L | ModifierFlag::SHIFT_L - - - - __KeyToKey__ - KeyCode::U, - KeyCode::KEY_1, ModifierFlag::COMMAND_L - - - __KeyToKey__ - KeyCode::P, - KeyCode::KEY_9, ModifierFlag::COMMAND_L - - - - Simultaneous Key Presses [S+D] turns on "(S)uper (D)uper mode" - remap.com_jasonrudolph_simultaneouskeypresses_vimode_sd - - __SimultaneousKeyPresses__ - KeyCode::D, KeyCode::S, - KeyCode::VK_CONFIG_SYNC_KEYDOWNUP_notsave_com_jasonrudolph_simultaneouskeypresses_vimode - - - ────────────────────────────── - - [Option] Use A+J/K to move to previous/next channel in Slack - com.jasonrudolph.simultaneouskeypresses_vimode.option.slack_jk - - - - - SizeUp Mode - - Control SizeUp using keyboard shortcuts that are on the home row, or very close to it. - Use Control+S to turn on SizeUp mode. Then, use any shortcut below to perform a SizeUp action. - For example, to send the window left, hit Control+S, and then H. - --- - Note: These settings assume that SizeUp is configured with its default keyboard shortcuts. - Before enabling this mode, you should click "Restore Defaults" in SizeUp's Shortcuts tab. - --- - notsave.com_jasonrudolph_sizeup_prefix_mode_core - __ShowStatusMessage__ SizeUp Mode (Control-s) - - - Use H/J/K/L to send window left/down/up/right - - __KeyToKey__ - KeyCode::H, ModifierFlag::NONE, - KeyCode::CURSOR_LEFT, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::COMMAND_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - __KeyToKey__ - KeyCode::J, ModifierFlag::NONE, - KeyCode::CURSOR_DOWN, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::COMMAND_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - __KeyToKey__ - KeyCode::K, ModifierFlag::NONE, - KeyCode::CURSOR_UP, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::COMMAND_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - __KeyToKey__ - KeyCode::L, ModifierFlag::NONE, - KeyCode::CURSOR_RIGHT, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::COMMAND_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - Use I to send window upper right - - __KeyToKey__ - KeyCode::I, ModifierFlag::NONE, - KeyCode::CURSOR_LEFT, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - Use O to send window upper right - - __KeyToKey__ - KeyCode::O, ModifierFlag::NONE, - KeyCode::CURSOR_UP, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - Use , to send window lower left - - __KeyToKey__ - KeyCode::COMMA, ModifierFlag::NONE, - KeyCode::CURSOR_DOWN, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - Use . to send window lower right - - __KeyToKey__ - KeyCode::DOT, ModifierFlag::NONE, - KeyCode::CURSOR_RIGHT, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - Use Space to send window center - - __KeyToKey__ - KeyCode::SPACE, ModifierFlag::NONE, - KeyCode::C, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::COMMAND_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - Use Return to make window full screen - - __KeyToKey__ - KeyCode::RETURN, ModifierFlag::NONE, - KeyCode::M, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::COMMAND_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - Use Control+H to send window to the previous monitor - - __KeyToKey__ - KeyCode::H, ModifierFlag::CONTROL_L | ModifierFlag::NONE, - KeyCode::CURSOR_LEFT, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core, - Option::NOREPEAT - - - - Use Control+L to send window to the next monitor - - __KeyToKey__ - KeyCode::L, ModifierFlag::CONTROL_L | ModifierFlag::NONE, - KeyCode::CURSOR_RIGHT, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L, KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core, - Option::NOREPEAT - - - - Use Control+S to turn off SizeUp Mode - - __KeyToKey__ - KeyCode::S, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_CONTROL | ModifierFlag::NONE, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - Control+S turns on SizeUp mode - option.com_jasonrudolph_sizeup_prefix_mode - - __KeyToKey__ - KeyCode::S, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_CONTROL | ModifierFlag::NONE, - KeyCode::VK_CONFIG_FORCE_ON_notsave_com_jasonrudolph_sizeup_prefix_mode_core - - - - - - KeyCode::VK_OPEN_URL_SHELL_markdown_em - - - - - - KeyCode::VK_OPEN_URL_SHELL_markdown_strong - - - - - - KeyCode::VK_OPEN_URL_SHELL_markdown_strikethrough - - - - - - KeyCode::VK_OPEN_URL_SHELL_markdown_inline_link - - - - - - KeyCode::VK_OPEN_URL_SHELL_markdown_reference_link_label_1 - - - - - - KeyCode::VK_OPEN_URL_SHELL_markdown_reference_link_label_2 - - - - - - KeyCode::VK_OPEN_URL_SHELL_markdown_reference_link_label_3 - - - - - - KeyCode::VK_OPEN_URL_SHELL_markdown_reference_link_label_4 - - - - - - - Markdown Mode - - Perform common Markdown-formatting tasks anywhere that you're editing text. - Use Control+M to turn on Markdown mode. Then, use any shortcut to perform an action. - For example, to wrap the selected text in double asterisks, hit Control+M, and then B. - --- - notsave.com_jasonrudolph_markdown_prefix_mode_core - __ShowStatusMessage__ Markdown Mode (Control-m) - - - Use I to wrap the currently-selected text in single asterisks ("I" for "Italic") - : Example => *selection* - - __KeyToKey__ - KeyCode::I, ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_markdown_em, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core, - - - - Use B to wrap the currently-selected text in double asterisks ("B" for "Bold") - : Example => **selection** - - __KeyToKey__ - KeyCode::B, ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_markdown_strong, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core, - - - - Use S to wrap the currently-selected text in double tildas ("S" for "Strikethrough") - : Example => ~~selection~~ - - __KeyToKey__ - KeyCode::S, ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_markdown_strikethrough, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core, - - - - Use L to convert the currently-selected text to an inline link, using a URL from the clipboard - : Example => [selection](clipboard) - - __KeyToKey__ - KeyCode::L, ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_markdown_inline_link, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core, - - - - Use 1 to convert the currently-selected text to a reference link, using a URL from the clipboard - : Also works with 2, 3, or 4 - : Example => [selection][1] - - __KeyToKey__ - KeyCode::KEY_1, ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_markdown_reference_link_label_1, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core, - - - __KeyToKey__ - KeyCode::KEY_2, ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_markdown_reference_link_label_2, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core, - - - __KeyToKey__ - KeyCode::KEY_3, ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_markdown_reference_link_label_3, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core, - - - __KeyToKey__ - KeyCode::KEY_4, ModifierFlag::NONE, - KeyCode::VK_OPEN_URL_SHELL_markdown_reference_link_label_4, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core, - - - - Use Control+M to turn off Markdown Mode - - __KeyToKey__ - KeyCode::M, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_CONTROL | ModifierFlag::NONE, - KeyCode::VK_CONFIG_FORCE_OFF_notsave_com_jasonrudolph_markdown_prefix_mode_core - - - - Control+M turns on Markdown mode - option.com_jasonrudolph_markdown_prefix_mode - - __KeyToKey__ - KeyCode::M, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_CONTROL | ModifierFlag::NONE, - KeyCode::VK_CONFIG_FORCE_ON_notsave_com_jasonrudolph_markdown_prefix_mode_core - - - - - diff --git a/screenshots/accessibility-permissions-for-hammerspoon.png b/screenshots/accessibility-permissions-for-hammerspoon.png new file mode 100644 index 00000000..2a06ba42 Binary files /dev/null and b/screenshots/accessibility-permissions-for-hammerspoon.png differ diff --git a/screenshots/karabiner-change-key-config-01.png b/screenshots/karabiner-change-key-config-01.png deleted file mode 100644 index 976fe918..00000000 Binary files a/screenshots/karabiner-change-key-config-01.png and /dev/null differ diff --git a/screenshots/karabiner-change-key-config-02.png b/screenshots/karabiner-change-key-config-02.png deleted file mode 100644 index a475eef7..00000000 Binary files a/screenshots/karabiner-change-key-config-02.png and /dev/null differ diff --git a/screenshots/karabiner-change-key-config-03.png b/screenshots/karabiner-change-key-config-03.png deleted file mode 100644 index b9b63326..00000000 Binary files a/screenshots/karabiner-change-key-config-03.png and /dev/null differ diff --git a/screenshots/karabiner-change-key-config-04.png b/screenshots/karabiner-change-key-config-04.png deleted file mode 100644 index a5038f0f..00000000 Binary files a/screenshots/karabiner-change-key-config-04.png and /dev/null differ diff --git a/screenshots/karabiner-key-repeat-config.png b/screenshots/karabiner-key-repeat-config.png deleted file mode 100644 index 639d0cf1..00000000 Binary files a/screenshots/karabiner-key-repeat-config.png and /dev/null differ diff --git a/screenshots/login-items-for-karabiner-and-hammerspoon.png b/screenshots/login-items-for-karabiner-and-hammerspoon.png new file mode 100644 index 00000000..3022bd1e Binary files /dev/null and b/screenshots/login-items-for-karabiner-and-hammerspoon.png differ diff --git a/screenshots/seil-config.png b/screenshots/seil-config.png deleted file mode 100644 index ce8b2a1b..00000000 Binary files a/screenshots/seil-config.png and /dev/null differ diff --git a/script/karabiner-export b/script/karabiner-export deleted file mode 100755 index d7484b64..00000000 --- a/script/karabiner-export +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# Exports all the settings that are configured in the Karabiner UI (e.g., which -# remappings are enabled, key repeat settings, etc.). - -# Get path to the directory where this script resides -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Export Karabiner configuration -PATH_TO_IMPORT_SCRIPT=$DIR/karabiner-import -/Applications/Karabiner.app/Contents/Library/bin/karabiner export > $PATH_TO_IMPORT_SCRIPT diff --git a/script/karabiner-import b/script/karabiner-import deleted file mode 100755 index fa2f8fdf..00000000 --- a/script/karabiner-import +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/sh - -cli=/Applications/Karabiner.app/Contents/Library/bin/karabiner - -$cli set com.jasonrudolph.hyper_f 1 -/bin/echo -n . -$cli set com.jasonrudolph.simultaneouskeypresses_vimode.terminal.previous_next_word 1 -/bin/echo -n . -$cli set com.jasonrudolph.iterm.control_with_h_or_j_or_k_or_l_to_move_between_panes 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_g 1 -/bin/echo -n . -$cli set parameter.keyoverlaidmodifier_timeout 300 -/bin/echo -n . -$cli set com.jasonrudolph.control_with_semicolon_to_delete_to_end_of_line 1 -/bin/echo -n . -$cli set private.option.simultaneouskeypresses_vimode_commadot_to_optionleftright 1 -/bin/echo -n . -$cli set com.jasonrudolph.f192f19_escape_or_control 1 -/bin/echo -n . -$cli set repeat.initial_wait 400 -/bin/echo -n . -$cli set com.jasonrudolph.slack.shift_and_command_with_left_or_right_bracket_to_go_to_previous_or_next_channel 1 -/bin/echo -n . -$cli set com.jasonrudolph.terminal.option_with_h_or_l_to_delete_previous_word_or_next_word 1 -/bin/echo -n . -$cli set private.double_lshift_to_caps 1 -/bin/echo -n . -$cli set repeat.wait 40 -/bin/echo -n . -$cli set option.com_jasonrudolph_sizeup_prefix_mode 1 -/bin/echo -n . -$cli set space_cadet.fix_opt_arrows 1 -/bin/echo -n . -$cli set option.com_jasonrudolph_markdown_prefix_mode 1 -/bin/echo -n . -$cli set remap.com_jasonrudolph_simultaneouskeypresses_vimode_sd 1 -/bin/echo -n . -$cli set com.jasonrudolph.right_option_hyper 1 -/bin/echo -n . -$cli set com.jasonrudolph.size_up.left 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_m 1 -/bin/echo -n . -$cli set private.remap.simultaneouskeypresses_vimode_sd 1 -/bin/echo -n . -$cli set option.jremacsmode_ex_controlX 1 -/bin/echo -n . -$cli set private.appdef 1 -/bin/echo -n . -$cli set remap.simultaneouskeypresses_jvimode_sd 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_c_hyper_c 1 -/bin/echo -n . -$cli set com.jasonrudolph.option_with_o_to_open_selected_url 1 -/bin/echo -n . -$cli set com.jasonrudolph.iterm.control_with_dash_or_pipe_to_split_pane 1 -/bin/echo -n . -$cli set passthrough.escapetab 1 -/bin/echo -n . -$cli set option.jasonrudolph_sizeup_prefix_mode 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_a 1 -/bin/echo -n . -$cli set com.jasonrudolph.option_up_down_to_pageup_pagedown 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_b 1 -/bin/echo -n . -$cli set remap.simultaneouskeypresses_custom_vimode_sd 1 -/bin/echo -n . -$cli set com.jasonrudolph.option_with_h_or_l_to_delete_previous_word_or_next_word 1 -/bin/echo -n . -$cli set option.emacsmode_ex_controlU_forwarddelete 1 -/bin/echo -n . -$cli set private.optionDtoescapeD_term 1 -/bin/echo -n . -$cli set private.right_command_d 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_c 1 -/bin/echo -n . -$cli set remap.launchpad2dashboard 1 -/bin/echo -n . -$cli set com.jasonrudolph.double_lshift_to_caps 1 -/bin/echo -n . -$cli set option.simultaneouskeypresses_jvimode_commadot_to_optionleftright 1 -/bin/echo -n . -$cli set com.jasonrudolph.simultaneouskeypresses_vimode.previous_next_work_in_terminal 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_r 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_d 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_e 1 -/bin/echo -n . -$cli set private.f192f19_escape_or_control 1 -/bin/echo -n . -$cli set com.jasonrudolph.hyper_t 1 -/bin/echo -n . -$cli set com.jasonrudolph.simultaneouskeypresses_vimode.option.slack_io 1 -/bin/echo -n . -/bin/echo