Introduction
Keyboard remapping can increase your productivity. Kanata is a tool which works on all platforms. It isn't too hard to setup, and is quite powerful.
JumpApp
JumpApp is a popular Linux util to run or raise an application. When triggered, it launches an application if it's not already running; if it is, it cycles through its windows. It is much faster than using Alt-Tab.
This can be configured in a specific keyboard layer using Kanata. The configuration that I have listed here is made for windows, but it can easily work on Linux if the Linux JumpApp is used instead.
Kanata configuration
Kanata comes in various editions, but for my purposes, I require the one with command support. I require something similar to JumpApp which is a command. Kanata configurations should be saved as .kbd
files.
(defcfg danger-enable-cmd yes ;; Allow commands for JumpApp
process-unmapped-keys yes ;; I do not see issues when enabling this
log-layer-changes no ;; I run this hidden, logs have no use for me
)
;; Variables
(defvar
user-profile %UserProfile%
ahk-executables-path (concat user-profile "\Documents\AutoHotKey\functions")
run-or-raise-path (concat ahk-executables-path \run-or-raise.exe)
toggle-maximize-path (concat ahk-executables-path \toggle-maximize.exe)
)
;; Defsrc contains the original unmapped keyboard layout. Often this is qwerty. Although at home I use dvorak. It is possible to only include the keys that you want to remap.
(defsrc
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ] \
caps a s d f g h j k l ; ' ret
lsft z x c v b n m , . / rsft
lctl lmet lalt spc ralt rmet rctl
)
;; The first layer defined is the layer that will be active by default when kanata starts up. I like dvorak, but it is not mandatory.
(deflayer dvorak
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
@os1 8 7 3 4 5 6 2 1 9 0 [ ] bspc
tab ' , . p y f g c r l / = \
caps a o e u i d h t n s - ret
@lsft ; q j k x b m w v z @rsft
@lctl lmet @lalt spc @ralt rmet @rctl
)
;; Notice the keys with "@" those are aliases.
;; Since other people often have to use my work laptop I have a way to quickly set the keyboard to a qwerty layer.
(deflayer qwerty
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 @dvk
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ] \
caps a s d f g h j k l ; ' ret
lsft z x c v b n m , . / rsft
lctl lmet lalt spc ralt rmet rctl
)
;; This is my layer for shortcuts. The jump prefix is given for the JumpApp functionality.
(deflayer shortcuts
esc @maximize f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 @qwr
@os1 1 2 3 4 5 6 7 8 9 0 [ ] bspc
tab ' , . p y @jump-winscp grv c lrld l / = \
caps a @jump-outlook @jump-emacs u i d h @jump-terminal n s - ret
@lsft ; q j k x @jump-brave m w v z @rsft
@lctl lmet @lalt spc @ralt rmet @rctl
)
;; lrld is a default shortcut to reload the configuration
;; Aliases
(defalias dvk (layer-switch dvorak)
qwr (layer-switch qwerty)
;; os1 switches to my shortcut layer until the next key is pressed, or until it times out
os1 (one-shot 1500 (layer-while-held shortcuts))
;; Sticky keys - You do no longer have to hold both keys, but get a little bit of time to press both, which is better for your fingers.
lsft (one-shot 1500 lsft)
rsft (one-shot 1500 rsft)
lctl (one-shot 1500 lctl)
rctl (one-shot 1500 rctl)
lalt (one-shot 1500 lalt)
ralt (one-shot 1500 ralt)
;; Windows menu does not open well, if these are sticky
;; lmet (one-shot 1500 lmet)
;; rmet (one-shot 1500 rmet)
)
;; Commands
(defalias
maximize (cmd cmd.exe /c $toggle-maximize-path)
jump-brave (cmd cmd.exe /c $run-or-raise-path "brave.exe" "%ProgramFiles%\BraveSoftware\Brave-Browser\Application\brave.exe")
jump-emacs (cmd cmd.exe /c $run-or-raise-path "emacs.exe" "%ProgramFiles%\Emacs\emacs-29.2\bin\runemacs.exe -c -n -a ''")
jump-outlook (cmd cmd.exe /c $run-or-raise-path "OUTLOOK.EXE" "%ProgramFiles(x86)%\Microsoft Office\root\Office16\OUTLOOK.EXE")
jump-terminal (cmd cmd.exe /c $run-or-raise-path "WindowsTerminal.exe" "wt.exe")
jump-winscp (cmd cmd.exe /c $run-or-raise-path "WinSCP.exe" "%LocalAppData%\Programs\WinSCP\WinSCP.exe")
)
JumpApp in AutoHotKey
The above code won't be useful without my JumpApp executables. I compiled them with AutoHotKey. On Linux JumpApp can be used instead.
JumpApp has two arguments. The first one is the window class to cycle through, and the second one is the path to launch the application. AutoHotKey comes with "Window Spy", a tool which is able to show you the window class of an application.
These are the two scripts I wrote and compiled:
; JumpApp AHK script
#Requires AutoHotkey v2.0
; Environment variables (for run or raise) - has to be at top of the file
global ProgramFilesx64 := EnvGet("ProgramFiles")
global ProgramFilesx86 := EnvGet("ProgramFiles(x86)")
global LocalAppData := EnvGet("LocalAppData")
If (A_Args.Length == 2)
{
RunOrRaise(A_Args[1], A_Args[2])
}
ReplaceEnvironmentVariables(input) {
output := StrReplace(input, "%ProgramFiles%", ProgramFilesx64)
output := StrReplace(input, "%ProgramFiles(x86)%", ProgramFilesx64)
output := StrReplace(input, "%LocalAppData%", LocalAppData)
return output
}
RunOrRaise(classInput, executablePathInput)
{
class := ReplaceEnvironmentVariables(classInput)
executablePath := ReplaceEnvironmentVariables(executablePathInput)
windowClass := "ahk_exe " . class
If WinExist(windowClass)
{
If WinActive(windowClass)
{
CurrentActive := WinGetClass("A")
Instances := WinGetCount("ahk_class " CurrentActive)
If (Instances > 1)
{
WinMoveBottom("A")
WinActivate(windowClass)
}
WinActivate("ahk_class " CurrentActive)
}
Else
{
WinActivate(windowClass)
}
}
Else {
Run executablePath
}
}
; Maximize toggle AHK
#Requires AutoHotkey v2.0
WinState := WinGetMinMax("A")
If (WinState = 1)
{
WinRestore("A")
}
Else
{
WinMaximize("A")
}
Automatically start kanata
Kanata will be set to run automatically at the next startup of your system after running this PowerShell script as an administrator. However, you can also test it locally by executing the command found in the Value
field within PowerShell.
The script assumes that you have a folder named "Kanata" located under your documents. The folder should contain the executable and the configuration file.
# $env:Temp gave me a shortened incorrect path, so I use the dotnet variant
$KanataDirectoryPath = "$env:UserProfile\Documents\Kanata"
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "Kanata" -Value "`"$KanataDirectoryPath\kanata_cmd_allowed.exe`" -ExecutionPolicy Unrestricted -WindowStyle Hidden -ArgumentList `"--cfg $KanataDirectoryPath\kanata.kbd`" >> `"$([System.IO.Path]::GetTempPath())StartupLog.txt`""
Windows Defender incorrectly reports the "cmd allowed" executable as malware. You can exclude it like this:
Add-MpPreference -ExclusionPath "$env:UserProfile\Documents\Kanata\kanata_cmd_allowed.exe"
Workflow
I often prefer to have all my windows maximized. After launching an application, I typically maximize its window. When I need to access a specific window, I use the jump shortcut, which is notably faster than using Alt-Tab or the Windows search feature.
While this method works well for me. Using grv
to toggle layers may not be the best choice. My shortcuts layer provides a way to type that character, but I need it rather often. This config should be enough to get you going.
Additionally, I have an AutoHotKey script that remaps CapsLock to Home when Emacs is open. This is necessary for my xah-fly-config setup. While simple key remapping can be accomplished with Windows PowerToys, I prefer using AutoHotKey since I already use it. You can find this script in my Xah Fly Keys and my Emacs config article.