Skip to content

Instantly share code, notes, and snippets.

Last active May 10, 2024 23:10
Show Gist options
  • Save sedm0784/4443120 to your computer and use it in GitHub Desktop.
Save sedm0784/4443120 to your computer and use it in GitHub Desktop.
AutoHotkey script to map Caps Lock to Escape when it's pressed on its own and Ctrl when used in combination with another key, à la Steve Losh. Adapted from one that does something similar with the Ctrl Key on the Vim Tips Wiki ( (Plus contribs from @randy909 & @mmikeww.)
g_LastCtrlKeyDownTime := 0
g_AbortSendEsc := false
g_ControlRepeatDetected := false
if (g_ControlRepeatDetected)
send,{Ctrl down}
g_LastCtrlKeyDownTime := A_TickCount
g_AbortSendEsc := false
g_ControlRepeatDetected := true
*CapsLock Up::
send,{Ctrl up}
g_ControlRepeatDetected := false
if (g_AbortSendEsc)
current_time := A_TickCount
time_elapsed := current_time - g_LastCtrlKeyDownTime
if (time_elapsed <= 250)
SendInput {Esc}
g_AbortSendEsc := true
Copy link

I found this on that same page which appears to do this MUCH more concisely.

; Author: fwompner gmail com


SetCapsLockState, alwaysoff
Send {LControl Down}
KeyWait, CapsLock
Send {LControl Up}
if ( A_PriorKey = "CapsLock" )
Send {Esc}

Copy link

jooize commented Jun 27, 2015

The conciser one doesn't handle pressing Shift before the new Control (on Caps Lock) in combination with a character, i.e. Shift+Ctrl+T doesn't reopen tabs but Ctrl+Shift+T does.

Copy link


Copy link

@jooize, great to know. I typically use Vimium so I've got single key shortcuts to open a new tab and navigate, but since I just got around to putting this on another one of my machines I'm definitely going to give the more robust version a shot.

Copy link

I forked and added the remaining keys here.
I use eclipse with a vim plugin so stuff like <ctrl-1> and <ctrl-f7> were sending extra <esc>'s.
Would make it a pull request but I guess you can't do that on gists...

Copy link

@randy909 Oh cool, thanks. I've copied your extra settings into my version. (Hope you don't have any objections!)

Copy link

mmikeww commented Sep 25, 2016

In AHK, all hotkey subroutine labels fall-thru and execute code until the next return statement

so, instead of repeating

   g_AbortSendEsc := true

   g_AbortSendEsc := true

;// etc

you could just do:

~*^c::                                   ;// etc
   g_AbortSendEsc := true

Copy link

Forked and implemented mmikeww subroutine optimization. Thank you so much for awesome script and intelligent comments.


  • Shift + capsLock : enables caps lock
  • Removed the timing
    on problem simply right click on autohotkey icon and select reload script

Copy link

@nocaoper Thanks for the code
@ALL is the emulated Ctrl key also triggering your other hotkeys? In my case only a few hotkey which are triggered with a Ctrl Key combination are triggered and in those scripts that are triggered the Send Alt Key combinations also don't work.

Copy link

sedm0784 commented Jan 3, 2018

@mmikeww Thanks for the tip! I've updated the gist accordingly.

Copy link

fenwar commented May 27, 2018

Here's my version, working in AHK, which is based on the more concise approach (i.e. my main goal was to avoid the big list of keys) but doesn't have the Shift+Ctrl ordering issue of the one cited above.

Copy link

ililim commented Jul 27, 2018

Thanks for these, but unfortunately in my experience these scripts sometimes swallow inputs or get stuck. In addition, when CapsLock is pressed and held down a Ctrl KEYDOWN event is leaked, resulting in unexpected behavior in certain applications (e.g. games).

To anyone reading this in 2018+, I've written a lightweight c utility to rebind CapsLock to Ctrl/Esc (or any key to any other two keys) that can be found here. Have fun!

Copy link

Script works well for me. I added and A_PriorKey=="CapsLock" into the condition on line 27. That way it doesn't act like Ctrl and Escape when I press and release the entire key combination really quickly.

Copy link

thank you for this!

Copy link

I did a similar approach to replace the key tab by caps lock without breaking any combination, adding double tab trigger to switch windows in metro context under Windows 8 but it's mandatory, can be commented out.

Copy link

robmunger commented Feb 9, 2022

Fenwar's version, posted above (May 2018) is beautiful code. I like it because it doesn't hook every key on the keyboard. Give it a look.

Copy link


  1. Add a rule that maps LCtrl to CapsLock.

Copy link

Caps to Ctrl+Esc...
If just pressed 1 time is gonna act as ESC
If used with another key is gonna act as CTRL
Allow Shift + Ctrl combinations

#IfWinNotActive,ahk_group WorkIn
    Send {Blind}{Ctrl Down}
    cDown := A_TickCount

*CapsLock up::
    If ((A_TickCount-cDown) < 150){
        Send {Blind}{Ctrl Up}{Esc}
    Else {
        Send {Blind}{Ctrl Up}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment