<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Justin Tanner</title>
    <description>The latest articles on DEV Community by Justin Tanner (@justintanner).</description>
    <link>https://dev.to/justintanner</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F57967%2Feb15cc29-20b8-475f-a509-4cdfbe02f7cc.jpg</url>
      <title>DEV Community: Justin Tanner</title>
      <link>https://dev.to/justintanner</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/justintanner"/>
    <language>en</language>
    <item>
      <title>Emacs keybindings to rule them all</title>
      <dc:creator>Justin Tanner</dc:creator>
      <pubDate>Sat, 06 Apr 2019 19:38:02 +0000</pubDate>
      <link>https://dev.to/justintanner/emacs-keybindings-to-rule-them-all-380b</link>
      <guid>https://dev.to/justintanner/emacs-keybindings-to-rule-them-all-380b</guid>
      <description>&lt;p&gt;When Microsoft released &lt;a href="https://www.microsoft.com/en-ca/store/p/ubuntu/9nblggh4msv6"&gt;Ubuntu for Windows 10&lt;/a&gt; I took the opportunity to try web development on Windows after 8 years on a Mac. I was pleasantly surprised with Ubuntu on Windows 10. Having Ubuntu in your terminal is handy because it more closely resembles the servers I deploy my code to. But there was one frustrating aspect of switching back to Windows, keyboard shortcuts.&lt;/p&gt;

&lt;p&gt;Some differences are easy to workaround such as &lt;code&gt;Ctrl+c&lt;/code&gt; and &lt;code&gt;Cmd+c&lt;/code&gt; (copy). Copy and paste can be dealt with by changing settings in the OS, but other shortcuts are quite different such as &lt;code&gt;Cmd+q&lt;/code&gt; and &lt;code&gt;Alt+F4&lt;/code&gt; (quit an app). Instead of memorizing these differences I wondered if there was a better solution.&lt;/p&gt;

&lt;p&gt;My text editor of choice is Emacs. Once inside Emacs you enter another world of keyboard shortcuts. Goodbye &lt;code&gt;Ctrl+c&lt;/code&gt; and hello &lt;code&gt;Ctrl+y&lt;/code&gt;. Navigating text starts by holding down a modifier key such as &lt;code&gt;Ctrl&lt;/code&gt; or &lt;code&gt;Alt&lt;/code&gt; and your hands never leave the home row. Would it be possible to use Emacs shortcuts to control both operating systems in the same way?&lt;/p&gt;

&lt;h2&gt;
  
  
  Are there any apps that already do this?
&lt;/h2&gt;

&lt;p&gt;I started by looking for something I could download or buy to solve the problem. For Windows I found &lt;a href="http://www.cam.hi-ho.ne.jp/oishi/indexen.html"&gt;XKeymacs&lt;/a&gt; which described it self as "a keyboard utility to realize Emacs like-usability on all windows applications".&lt;/p&gt;

&lt;p&gt;On Mac I couldn't find any app to solve the problem, but OSX supports &lt;strong&gt;most&lt;/strong&gt; Emacs shortcuts out of the box. For example &lt;code&gt;Ctrl+a&lt;/code&gt; is mapped to the start of the line character just like Emacs.&lt;/p&gt;

&lt;p&gt;Both XKeymacs and the default shortcuts for Mac failed to support two important Emacs features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Selecting text with &lt;code&gt;Ctrl+Space&lt;/code&gt; (start mark), move down a few lines to expand the text selection and &lt;code&gt;Ctrl+Space&lt;/code&gt; (end mark)&lt;/li&gt;
&lt;li&gt;Prefix keys or chords shortcuts involving a modifier key and &lt;strong&gt;two&lt;/strong&gt; other keystrokes such as &lt;code&gt;Ctrl+xs&lt;/code&gt; (save)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Are there any scripts that do this?
&lt;/h2&gt;

&lt;p&gt;Next I searched Github for solutions and I found some &lt;a href="https://gist.github.com/dulm/ee5ec47cfd2a71ded0e3841ee04e6ea3"&gt;interesting&lt;/a&gt;, &lt;a href="https://github.com/usi3/emacs.ahk"&gt;scripts&lt;/a&gt;. These scripts didn't solve the problems of selecting text or chord keys, but they were written in two apps / frameworks that were new to me.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.hammerspoon.org/"&gt;Hammerspoon&lt;/a&gt; A Lua based scripting language to intercept keystroke and mouse events (Mac)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://autohotkey.com/"&gt;AutoHotkey&lt;/a&gt; A scripting language that intercepts keystrokes and mouse events (Windows)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hammerspoon and AutoHotkey had potential, but I needed to make sure they could do what I wanted, so I wrote some experimental code in these new environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Text selection in AutoHotkey
&lt;/h2&gt;

&lt;p&gt;First I set out to see if AutoHotkey could &lt;a href="https://gist.github.com/justintanner/272aa3a9b5834a1e4027aaaa3702efbe"&gt;emulate Emacs style text selection&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#SingleInstance&lt;/span&gt;
&lt;span class="c1"&gt;#Installkeybdhook&lt;/span&gt;
&lt;span class="c1"&gt;#UseHook&lt;/span&gt;
&lt;span class="nv"&gt;SetKeyDelay&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="nv"&gt;global&lt;/span&gt; &lt;span class="nv"&gt;selecting&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;False&lt;/span&gt;

&lt;span class="nv"&gt;SendWithShift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;If&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;selecting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;Send&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;%keys&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nv"&gt;Else&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;Send&lt;/span&gt; &lt;span class="nv"&gt;%keys&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="nn"&gt;Space::&lt;/span&gt;
&lt;span class="nv"&gt;selecting&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;selecting&lt;/span&gt;
&lt;span class="nv"&gt;Return&lt;/span&gt;

&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="nn"&gt;n::&lt;/span&gt;
&lt;span class="nv"&gt;SendWithShift&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;{Down}&lt;/span&gt;&lt;span class="p"&gt;")&lt;/span&gt;
&lt;span class="nv"&gt;Return&lt;/span&gt;

&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="nn"&gt;p::&lt;/span&gt;
&lt;span class="nv"&gt;SendWithShift&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;{Up}&lt;/span&gt;&lt;span class="p"&gt;")&lt;/span&gt;
&lt;span class="nv"&gt;Return&lt;/span&gt;

&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="nn"&gt;f::&lt;/span&gt;
&lt;span class="nv"&gt;SendWithShift&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;{Right}&lt;/span&gt;&lt;span class="p"&gt;")&lt;/span&gt;
&lt;span class="nv"&gt;Return&lt;/span&gt;

&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="nn"&gt;b::&lt;/span&gt;
&lt;span class="nv"&gt;SendWithShift&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;{Left}&lt;/span&gt;&lt;span class="p"&gt;")&lt;/span&gt;
&lt;span class="nv"&gt;Return&lt;/span&gt;

&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="nn"&gt;a::&lt;/span&gt;
&lt;span class="nv"&gt;SendWithShift&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;{Home}&lt;/span&gt;&lt;span class="p"&gt;")&lt;/span&gt;
&lt;span class="nv"&gt;Return&lt;/span&gt;

&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="nn"&gt;e::&lt;/span&gt;
&lt;span class="nv"&gt;SendWithShift&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;{End}&lt;/span&gt;&lt;span class="p"&gt;")&lt;/span&gt;
&lt;span class="nv"&gt;Return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Chords in Hammerspoon
&lt;/h2&gt;

&lt;p&gt;Next I checked if Hammerspoon could &lt;a href="https://gist.github.com/justintanner/272aa3a9b5834a1e4027aaaa3702efbe"&gt;execute chord keys&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;ctrlXActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;hotkeyModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hotkey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startCtrlX&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;ctrlXActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clearCtrlX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;clearCtrlX&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Clearing ctrlXActive flag.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;ctrlXActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;forwardOrOpen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;hotkeyModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ctrlXActive&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Opening file.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventtap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keyStroke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cmd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'o'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Moving cursor forward.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventtap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keyStroke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'right'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;hotkeyModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="n"&gt;clearCtrlX&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;hotkeyModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;'ctrl'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;startCtrlX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;hotkeyModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;'ctrl'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forwardOrOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;hotkeyModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  I need data structure
&lt;/h2&gt;

&lt;p&gt;Success! The experiments showed me that Hammerspoon and AutoHotkey could emulate Emacs in the way I wanted. Next I needed a data structure to store all the information needed to translate keystrokes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tables in Lua
&lt;/h3&gt;

&lt;p&gt;Hammerspoon is scripted in &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; a dynamic language similar to Ruby. Associative arrays in Ruby are called hashes and in Lua they are called &lt;a href="https://www.lua.org/pil/2.5.html"&gt;tables&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Yuval'&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'job'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Author'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is an equivalent Hash in Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Yuval'&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:job&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Author'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately Lua does not use the nice JSON style syntax for defining multiple properties such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Yuval'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Author'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Lua that would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Yuval'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'job'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Author'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="ow"&gt;or&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Yuval'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Author'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lua also uses tables to create arrays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;fruits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'Apple'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Banana'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Orange'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;-- Prints 'Apple' because Lua indexes arrays by 1 not 0.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Ruby that might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;fruits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Apple'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Banana'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Orange'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tables appeared to be the data structure I needed to store the keystrokes I wanted to translate. &lt;/p&gt;

&lt;h3&gt;
  
  
  Objects in AutoHotkey
&lt;/h3&gt;

&lt;p&gt;In AuotHotKey associative arrays are called &lt;a href="https://autohotkey.com/docs/Objects.htm"&gt;Objects&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;User&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nv"&gt;User&lt;/span&gt;&lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="p"&gt;"]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Yuval&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;User&lt;/span&gt;&lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;job&lt;/span&gt;&lt;span class="p"&gt;"]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AHK can use a JSON like syntax as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;User&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;name:&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Yuval&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;job:&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to Lua AHK uses Object's to define both associative arrays and regular arrays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;Fruits&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;['&lt;/span&gt;&lt;span class="s1"&gt;Apple&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Banana&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Orange&lt;/span&gt;&lt;span class="p"&gt;']&lt;/span&gt;

&lt;span class="nv"&gt;OutputDebug&lt;/span&gt; &lt;span class="nv"&gt;%Fruits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Prints&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Apple&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="nv"&gt;because&lt;/span&gt; &lt;span class="nv"&gt;AHK&lt;/span&gt; &lt;span class="nv"&gt;also&lt;/span&gt; &lt;span class="nv"&gt;uses&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;based&lt;/span&gt; &lt;span class="nv"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;indexes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The keystroke translation data structure
&lt;/h2&gt;

&lt;p&gt;To store a look-up table for keystrokes I started with a Lua table like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ctrl'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'left'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'cmd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hitting &lt;code&gt;Ctrl+b&lt;/code&gt; would trigger the left directional keystroke which doesn't require holding a modifier key such as &lt;code&gt;Ctrl&lt;/code&gt; and hitting &lt;code&gt;Ctrl+w&lt;/code&gt; would trigger the Mac cut shortcut &lt;code&gt;Cmd+x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This config separates modifiers and regular keys into different array entries because that's how Hammerspoon's API activates keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;  &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventtap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;newKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mods&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventtap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;newKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mods&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In AutoHotkey modifiers and regular keystrokes can be intermixed. Here is the the same data structure in AHK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;global&lt;/span&gt; &lt;span class="nb"&gt;keys&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{"&lt;/span&gt;&lt;span class="s2"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="p"&gt;":&lt;/span&gt; &lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;{Left}&lt;/span&gt;&lt;span class="p"&gt;"]&lt;/span&gt;
      &lt;span class="p"&gt;,"&lt;/span&gt;&lt;span class="s2"&gt;w&lt;/span&gt;&lt;span class="p"&gt;":&lt;/span&gt; &lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;^x&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nv"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;""]}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Ctrl+w&lt;/code&gt; triggers the Windows cut shortcut &lt;code&gt;Ctrl+x&lt;/code&gt; which is &lt;code&gt;^x&lt;/code&gt; in AHK. This syntax obeys the &lt;a href="https://autohotkey.com/docs/Scripts.htm#continuation"&gt;multi-line continuation&lt;/a&gt; rules in AHK making sure to start every line with a character indicating that this data structure will span multiple lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separating the text selection keys
&lt;/h2&gt;

&lt;p&gt;After starting a text selection with &lt;code&gt;Ctrl+Space&lt;/code&gt; in Emacs you can navigate around the document to increase or decrease the size of the selection with the navigation shortcuts like &lt;code&gt;Ctrl+n&lt;/code&gt; (down). In contrast other shortcuts can't work while text is selected such as &lt;code&gt;Ctrl+k&lt;/code&gt; (delete a line of text). To support text selection my config data needed to differentiate these two types of shortcuts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ctrl'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'left'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'ctrl'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Ctrl+b&lt;/code&gt; shrinks the current text selection by moving one character backwards so it's marked with &lt;code&gt;true&lt;/code&gt; as the third config setting. &lt;code&gt;Ctrl+d&lt;/code&gt; deletes a character at the current cursor position which needs to first deselect the current text selection, so it's marked with &lt;code&gt;false&lt;/code&gt; as the third config setting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working around limitations with macros
&lt;/h2&gt;

&lt;p&gt;The final additional to the data structure was an option to execute a Macro instead of a keystroke. Here is a macro written in AHK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="p"&gt;,"&lt;/span&gt;&lt;span class="s2"&gt;k&lt;/span&gt;&lt;span class="p"&gt;":&lt;/span&gt; &lt;span class="p"&gt;["",&lt;/span&gt; &lt;span class="nv"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MacroKillLine&lt;/span&gt;&lt;span class="p"&gt;"]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Macro&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;it&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;clipboard&lt;/span&gt;
&lt;span class="nv"&gt;MacroKillLine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;Send&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="nv"&gt;ShiftDown&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="nv"&gt;ShiftUp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nv"&gt;Send&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;
  &lt;span class="nv"&gt;Send&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;Del&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This macro tries to emulate how Emacs deletes lines by first selecting the entire line, cutting it and then deleting it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compromising on chords
&lt;/h2&gt;

&lt;p&gt;While I was working my way through the &lt;a href="http://wttools.sourceforge.net/emacs-stuff/emacs-keybindings.html"&gt;default Emacs keybindings&lt;/a&gt; I noticed some shortcuts in Emacs I'd never thought about.&lt;/p&gt;

&lt;p&gt;File file is bound to: &lt;code&gt;Ctrl-x Ctrl-f&lt;/code&gt; (release Ctrl between typing x and f)&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;Set fill column is bound to: &lt;code&gt;Ctrl-x f&lt;/code&gt; (hold Ctrl between typing x and f)&lt;/p&gt;

&lt;p&gt;These shortcuts preform different actions, but exploit the subtle difference of &lt;strong&gt;letting go of Ctrl&lt;/strong&gt; vs &lt;strong&gt;holding down Ctrl&lt;/strong&gt;. Should I support these shortcuts in my scripts? After reviewing the handful of Emacs shortcuts that differ in this way I decided to drop support for them in the scripts because I wasn't using them anyway. I was probably typing these shortcuts by accident in Emacs. I decided to disable those shortcuts in Emacs with an &lt;a href="https://gist.github.com/justintanner/05790ad55325408ff70632ca4ddd9f5f"&gt;elisp config script&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task switching
&lt;/h2&gt;

&lt;p&gt;One important shortcut not related editing text is &lt;code&gt;Alt+Tab&lt;/code&gt; or &lt;code&gt;Cmd+Tab&lt;/code&gt; (the task switcher). With my scripts complete I noticed that &lt;code&gt;Alt+Tab&lt;/code&gt; was the only reason my hands were leaving the home-row. Could I rebind these shortcuts to some unassigned Emacs shortcuts and keep my hands on the home-row?&lt;/p&gt;

&lt;p&gt;All of the shortcuts ranging from A to Z using &lt;code&gt;Ctrl&lt;/code&gt; were already taken. What about an unassigned chord keys like &lt;code&gt;Ctrl-xt&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;I hooked up the &lt;code&gt;Ctrl+xt&lt;/code&gt; shortcut and immediately hit a problem. On Windows &lt;code&gt;Alt+Tab&lt;/code&gt; requires holding down the &lt;code&gt;Alt&lt;/code&gt; key and tapping the &lt;code&gt;Tab&lt;/code&gt; key to step through each currently running app, but I wanted to hit &lt;code&gt;Ctrl-xt&lt;/code&gt; and then &lt;code&gt;Tab&lt;/code&gt; to step through the currently running apps. The code that handled chords in my scripts would not support this kind of shortcut.&lt;/p&gt;

&lt;p&gt;On stackoverflow I found other programmers struggling with the same problem in &lt;a href="https://stackoverflow.com/questions/35971452/what-is-the-right-way-to-send-alt-tab-in-ahk"&gt;AHK&lt;/a&gt;. One solution on Windows was to use &lt;code&gt;Alt+Esc&lt;/code&gt; instead of &lt;code&gt;Alt+Tab&lt;/code&gt;. &lt;code&gt;Alt+Esc&lt;/code&gt; switches to the &lt;strong&gt;last app&lt;/strong&gt; that was opened without a user interface. This was compatible with my script, but in practice I found it confusing to switch app with this shortcut. Trying to script &lt;code&gt;Alt+Tab&lt;/code&gt; and &lt;code&gt;Cmd+Tab&lt;/code&gt; seemed like a dead end.&lt;/p&gt;

&lt;p&gt;As a last resort I looked for alternative task switchers to the ones built into each operating system. For Windows I found a free open source project &lt;a href="http://www.switcheroo.io/"&gt;switcheroo&lt;/a&gt;. I set &lt;code&gt;Ctrl+xt&lt;/code&gt; to launch switcheroo instead of &lt;code&gt;Alt+tab&lt;/code&gt; and everything was peachy. On Mac I took the same approach and purchased a paid app called &lt;a href="https://manytricks.com/witch/"&gt;Witch 3&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;The scripts worked! I using them daily on both Windows and Mac. Switching between operating systems is no longer a pain.&lt;/p&gt;

&lt;p&gt;If you wanna give them a try for yourself checkout the &lt;a href="https://github.com/justintanner/universal-emacs-keybindings"&gt;Github repository&lt;/a&gt; and happy scripting.&lt;/p&gt;

</description>
      <category>emacs</category>
      <category>hammerspoon</category>
      <category>autohotkey</category>
      <category>lua</category>
    </item>
  </channel>
</rss>
