Dyota's blog

Keyboard rebindings with AutoHotKey

CapsLock as modifier!

This describes my keyboard remapping setup for Windows with AutoHotKey. The great enabler of this is using CapsLock as a modifier.

What about CapsLock then? Well, that function is now toggled when I press both Shift keys together.

Right hand

The whole philosophy behind the remappings for the right hand is so that:

NumPad

This was actually the instigator of the whole thing. I work on a laptop every day, and the external keyboard that I use (a Logitech K580) is also very laptop-like. It has a numpad, but the arrow keys are small, and tucked under the right Shift key.

The way I normally use the numpad is as the alternate function, with NumLock off, as the arrow keys and Home/End/PgUp/PgDn. However, sometimes I do need to type out numbers in sequence, and I miss having a dedicated numpad.

I wanted to have a toggle so that I can hold down a key to activate NumLock while the button is held down. I don't like tapping on the NumLock key to turn it on and off temporarily.

My first choice was to use the left Alt key, but that didn't work, because Alt+NumPad on Windows generates special characters.

I landed on Caps Lock as the toggle key. When it is held down, it will force the Numpad keys to send numbers and operators. On release, it returns the numpad to its arrow keys functions.

This purposely does not turn on NumLock. The reason is that, in the Excel formula bar, actually toggling NumLock causes intellisense to misbehave, and I need that. This is why I remapped the Numpad keys one by one.

Symbols

The next thing was symbols. I write a lot of code, and that means a lot of special characters. One that I use frequently, because I code in PowerShell a lot, is the dollar sign ($) for variables, and also the pound sign (#) for indicating comments. Both of these are kind of the middle, and while I'm kind of used to it now, it would be really convenient if I could reach these with my hand on the home row and without looking.

So, piggybacking of the Caps Lock alternate function, while it's being held down, it also activates another "layer", where the symbols are mapped onto the region of the home row of my right hand.

Normal mode:

  u i o p [ ]
h j k l ;
n m , . /

Symbols mode:

  ! @ # $ ( )
= % ^ & `
_ + - . ~

Some special notes:

Not listed above, there are the following rebindings:

Left hand

The whole philosophy behind the left hand remapping is so that I have good access to functions while my right hand is on a mouse.

Movement keys

The arrow keys are just fine on the numpad, but sometimes I want to reduce the hand travel just that little bit further, especially at times when I want my right hand on the mouse.

The directions are not WASD, as one might expect.

The general patten is that there are three keys: forward, back, and select.

Movement Set Forward Back Select (forward)
Line Q (Up) A {Down} Z (Down)
Character W E R
Word S D F
Row X (Home) C (End) V (End)

To select backwards/upwards, hold CapsLock + Alt + Key.

These bindings, paired with Spacebar as Enter, enables me to do a lot more operations with one hand on the mouse and the other on the keyboard.

Window Placement

Combo Function
CapsLock + 1 Snap Left
CapsLock + 3 Snap Right
CapsLock + 2 Maximise

Full script

#SingleInstance Force
+BackSpace::Send("{Delete}")
; Press both Shift keys together to toggle CapsLock
LShift & RShift::SetCapsLockState(!GetKeyState("CapsLock", "T"))
RShift & LShift::SetCapsLockState(!GetKeyState("CapsLock", "T"))

; Symbol layer - only active when CapsLock is held
#HotIf GetKeyState("CapsLock", "P")

; map symbols to right hand
u::Send("{!}")
i::Send("@")
o::Send("{#}")
p::Send("$")
j::Send("%")
k::Send("{^}")
l::Send("&")
`;::Send("*")
[::Send("(")
]::Send(")")
h::Send("=")
n::Send("_")
m::Send("{+}")
,::Send("-")
'::Send("{``}")
/::Send("~")

; map directions and text selection to left hand
q::Send("{Up}") 
!q::Send("^{Home}") 
a::Send("{Down}")
!a::Send("^{End}")

z::Send("+{Down}")
!z::Send("+{Up}")

w::Send("{Left}")
e::Send("{Right}")
r::Send("+{Right}")
!r::Send("+{Left}")

s::Send("^{Left}")
d::Send("^{Right}")

f::Send("+^{Right}")
!f::Send("+^{Left}")

x::Send("{Home}")
c::Send("{End}")
v::Send("+{End}")
!v::Send("+{Home}")

!o::Send("^{PgUp}")
!l::Send("^{PgDn}")

Enter::Send("{F5}")
NumpadEnter::Send("{Backspace}")
Space::Send("{Enter}")
BackSpace::Send("{Escape}")

; map numbers to numpad
NumpadIns::Send("0")
NumpadEnd::Send("1")
NumpadDown::Send("2")
NumpadPgdn::Send("3")
NumpadLeft::Send("4")
NumpadClear::Send("5")
NumpadRight::Send("6")
NumpadHome::Send("7")
NumpadUp::Send("8")
NumpadPgup::Send("9")
NumpadDel::Send(".")
NumpadDiv::Send("/")
NumpadMult::Send("*")
NumpadAdd::Send("{+}")
NumpadSub::Send("-")

; window placement
1::Send("#{Left}")
3::Send("#{Right}")
2::Send("#{Up}")

#HotIf

A note about AI use

For this exercise, Claude AI pretty much wrote the entire thing from scratch, and all I did was tell it if it was working or not. It's odd for me to be making a post, as all of this code was not my own product. In the past, most of the code would have been written by me, especially the problem-solving aspects. It feels odd that it at once feels diminished but also still worth putting up online.