Skip to content

Instantly share code, notes, and snippets.

@sedm0784
Last active April 11, 2024 22:38
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 (http://vim.wikia.com/wiki/Map_caps_lock_to_escape_in_Windows?oldid=32281). (Plus contribs from @randy909 & @mmikeww.)
g_LastCtrlKeyDownTime := 0
g_AbortSendEsc := false
g_ControlRepeatDetected := false
*CapsLock::
if (g_ControlRepeatDetected)
{
return
}
send,{Ctrl down}
g_LastCtrlKeyDownTime := A_TickCount
g_AbortSendEsc := false
g_ControlRepeatDetected := true
return
*CapsLock Up::
send,{Ctrl up}
g_ControlRepeatDetected := false
if (g_AbortSendEsc)
{
return
}
current_time := A_TickCount
time_elapsed := current_time - g_LastCtrlKeyDownTime
if (time_elapsed <= 250)
{
SendInput {Esc}
}
return
~*^a::
~*^b::
~*^c::
~*^d::
~*^e::
~*^f::
~*^g::
~*^h::
~*^i::
~*^j::
~*^k::
~*^l::
~*^m::
~*^n::
~*^o::
~*^p::
~*^q::
~*^r::
~*^s::
~*^t::
~*^u::
~*^v::
~*^w::
~*^x::
~*^y::
~*^z::
~*^1::
~*^2::
~*^3::
~*^4::
~*^5::
~*^6::
~*^7::
~*^8::
~*^9::
~*^0::
~*^Space::
~*^Backspace::
~*^Delete::
~*^Insert::
~*^Home::
~*^End::
~*^PgUp::
~*^PgDn::
~*^Tab::
~*^Return::
~*^,::
~*^.::
~*^/::
~*^;::
~*^'::
~*^[::
~*^]::
~*^\::
~*^-::
~*^=::
~*^`::
~*^F1::
~*^F2::
~*^F3::
~*^F4::
~*^F5::
~*^F6::
~*^F7::
~*^F8::
~*^F9::
~*^F10::
~*^F11::
~*^F12::
g_AbortSendEsc := true
return
@dragon788
Copy link

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

; Author: fwompner gmail com

InstallKeybdHook

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

@jooize
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.

@salgadobreno
Copy link

<3

@dragon788
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.

@randy909
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...

@sedm0784
Copy link
Author

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

@mmikeww
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

~*^a::
   g_AbortSendEsc := true
return

~*^b::
   g_AbortSendEsc := true
return

;// etc

you could just do:

~*^a::
~*^b::
~*^c::                                   ;// etc
   g_AbortSendEsc := true
return

@nocaoper
Copy link

Forked and implemented mmikeww subroutine optimization. Thank you so much for awesome script and intelligent comments.
https://gist.github.com/nocaoper/b872f97cda29bd8f0f2617606abd9fe4

Differences:

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

@MartinLichtblau
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.

@sedm0784
Copy link
Author

sedm0784 commented Jan 3, 2018

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

@fenwar
Copy link

fenwar commented May 27, 2018

Here's my version, working in AHK 1.1.29.00, 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.

@ililim
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!

@ngharrison
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.

@pseudorandomnumber
Copy link

thank you for this!

@acccounttest
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.
https://github.com/acccounttest/Sublime-Tab-for-SublimeText-Metro-and-Windows

@robmunger
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.

@Rccustevens
Copy link

https://gist.github.com/Rccustevens/e972cb21869b81ba0b5400991de5cd85

Differences:

  1. Add a rule that maps LCtrl to CapsLock.

@darianmorat
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
*CapsLock::
    Send {Blind}{Ctrl Down}
    cDown := A_TickCount
Return

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

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