Map CapsLock to Ctrl on Long Press and Esc on Short Press

The goal is to achieve the Ctrl effect on long press of CapsLock, and the Esc effect on short press of CapsLock

The AutoHotKey code inside is as follows:
SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

CapsLock::
  Send {Ctrl Down}
  KeyWait, CapsLock
  Send {Ctrl Up}
  if (A_PriorKey = "CapsLock")
    Send {Esc}
return

Walking through the code reveals the problem: whether long-pressed or short-pressed, it sends out Ctrl Down and Ctrl Up signals

In most environments, this extra Ctrl signal doesn't matter, but if a certain environment is sensitive to this extra Ctrl signal, ...

What I thought of is, a delay should be added to determine whether it's a short press or a long press.


While preparing to develop with GPT, I thought, it would be better to give GPT an open-ended question.

Analyze what problems this code has, and how it can be improved

The result exceeded my expectations.


1. First, let's look at the delay-added solution

SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

CapsLock::
    KeyWait, CapsLock, T0.2  ; Wait for release, wait 0.2 seconds
    if (ErrorLevel)  { ; Long press exceeds 0.2 seconds
        Send {Ctrl Down}
        KeyWait, CapsLock  ; Wait for release
        Send {Ctrl Up}
    }
    else  { ; Light press (shorter than 0.2 seconds)
        Send {Esc}
    }
return

It fully implemented the logic I conceived.

Moreover, I didn't expect AHK's syntax to natively support delay logic. It's implemented as the parameter T0.2 after KeyWait

When actually using it, I found the effect was problematic. After debugging, I found that an empty line needed to be added, as follows:

SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

CapsLock::
    KeyWait, CapsLock, T0.2  ; Wait for release, wait 0.2 seconds
    if (ErrorLevel)  { ; Long press exceeds 0.2 seconds
    ; Without this empty line there's a problem
        Send {Ctrl Down}
        KeyWait, CapsLock  ; Wait for release
        Send {Ctrl Up}
    }
    else  { ; Light press (shorter than 0.2 seconds)
        Send {Esc}
    }
return

I didn't figure out the reason. https://linux.do/t/topic/1095893

The benefit of this approach is that it logically implements the judgment between short press and long press. 

The downside, of course, is the T0.2 seconds parameter — whether it fits your operating habits.


2. Now let's look at the exhaustive method

SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

; CapsLock light press = Esc
CapsLock::Send {Esc}

; CapsLock combined with other keys = Ctrl
CapsLock & a::Send ^a
CapsLock & c::Send ^c
CapsLock & v::Send ^v
CapsLock & s::Send ^s
; More combinations can be added...

Do you take one look and think it's clumsy and inelegant? Not elegant at all?

If you enumerate all these key combinations, how long would the program/script be?!

But, in reality, it can be written with GPT.

I want to implement an autohotkey script,
Please refer to the format of the following code
CapsLock & a::Send ^a
Convert all CapsLock + key combinations on the keyboard into Ctrl combinations

Result

SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

; CapsLock light press = Esc
CapsLock::Send {Esc}

; CapsLock combination keys mapped to Ctrl combinations
CapsLock & a::Send ^a
CapsLock & b::Send ^b
; omitted

; Number keys
CapsLock & 0::Send ^0
CapsLock & 1::Send ^1
; omitted

; Function keys
CapsLock & F1::Send ^F1
CapsLock & F2::Send ^F2
; omitted

; Symbol keys
CapsLock & `;::Send ^`;
CapsLock & =::Send ^=
; omitted

; Other special keys
CapsLock & Delete::Send ^Delete
CapsLock & Insert::Send ^Insert
; omitted

; Arrow keys
CapsLock & Up::Send ^Up
CapsLock & Down::Send ^Down
; omitted

; Numeric keypad
CapsLock & Numpad0::Send ^Numpad0
CapsLock & Numpad1::Send ^Numpad1
; omitted

The implemented effect is excellent. 

Because it fundamentally eliminates the hassle of long-press vs short-press logic, directly using system-level single-key and combination-key logic.


For a moment, I thought of many years ago, when I was at a foreign trade company, setting up shipping fees.

For a certain country, the shipping used an unusual company that didn't provide an API for calculating shipping costs. We always required customers to manually create orders through customer service, because after knowing the products the customer wanted to purchase, customer service would set the shipping fee for the order.

Later one day, the company hired an IT person, and I communicated this issue. I was actually thinking whether they could find some way to automate this shipping fee calculation. Later, they found that Shopify allows setting multiple {weight-shipping fee} tiers for a certain country. So they set shipping fees for every 0.5kg tier, all the way up to 100kg, with shipping fees set for each tier. A total of 200 items, it's not an "impossible" task. Even considering shipping fee fluctuations, just set the shipping fees a bit higher, so that the company doesn't lose money when shipping fees fluctuate.


Summary

When you can be elegant, you should still be elegant; elegance should be the default pursuit.

However, clumsy, brute-force solutions cannot be entirely ruled out. When they need to be used, use them — even if you have to hold your nose. 

Especially in this day and age, repetitive brute work can be handed off to GPT.



========

Related Reading

《Tampermonkey Script to Auto-Fill Web Forms, Easing Mouse Operations for CloudCone VPS Hunting》

《Xshell Setup: Ctrl+Shift+C for Copy, Ctrl+Shift+V for Paste》

《A Collection of Development Examples with GPT》


Comments