AutoHotKey 实现 CapsLock 一键双用 长按=Ctrl 短按=Esc

逛B站的时候看到
<告别腱鞘炎!Vim 党必看! CapsLock 一键双用:Ctrl + Esc 全搞定>
目的是 长按CapsLock实现 Ctrl 的效果, 短按CapsLock实现 Esc 的效果

里面的AutoHotKey代码如下:
SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

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

走读代码就能发现问题, 不管是长按还是短按, 都会发出 Ctrl Down 和 Ctrl Up 信号

在大部分环境下, 这个多余的 Ctrl 信号没关系, 但是如果某个环境对这个多余的Ctrl信号有关系的话, ...

我想到的是, 应该加个延迟来判断是短按还是长按.


准备面向GPT开发的时候, 我想到, 不如给GPT一个开放的问题.

分析这段代码有什么问题, 可以怎样改进

结果超出我的期望.


1. 首先来看加延迟的方案

SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

CapsLock::
    KeyWait, CapsLock, T0.2  ; 等待释放 等待0.2秒
    
    if (ErrorLevel)  { ; 长按超过0.2秒
        Send {Ctrl Down}
        KeyWait, CapsLock  ; 等待释放
        Send {Ctrl Up}
    }
    else  { ; 轻按(短于0.2秒)
        Send {Esc}
    }
return

完全实现了我构思的逻辑.

而且, 我没想到AHK的语法原生支持延迟的逻辑. 实现为KeyWait后面的一个参数 T0.2

实际使用的时候发现效果有问题. 经过调试, 发现需要加一行空行, 如下:

SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

CapsLock::
    KeyWait, CapsLock, T0.2  ; 等待释放 等待0.2秒
    
    if (ErrorLevel)  { ; 长按超过0.2秒
    ; 不加这个空行就有问题
        Send {Ctrl Down}
        KeyWait, CapsLock  ; 等待释放
        Send {Ctrl Up}
    }
    else  { ; 轻按(短于0.2秒)
        Send {Esc}
    }
return

没搞明白原因. https://linux.do/t/topic/1095893

这个方案的好处是, 从逻辑上实现了短按和长按的判断. 

坏处当然就是 T0.2 秒这个参数, 是否符合你的操作习惯.


2. 再来看看穷举法

SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

; CapsLock 轻按 = Esc
CapsLock::Send {Esc}

; CapsLock 与其他键组合 = Ctrl
CapsLock & a::Send ^a
CapsLock & c::Send ^c
CapsLock & v::Send ^v
CapsLock & s::Send ^s
; 可以继续添加其他组合键...

你是不是一眼看上去觉得 傻大笨粗? 一点都不优雅?

如果把这些按键组合穷举出来, 要写多长的程序/脚本啊?!

但, 实际上, 是可以通过GPT来写的.

我要实现一个 autohotkey 脚本,
请参考以下代码的格式
CapsLock & a::Send ^a
将 CapsLock 与键盘上全部按键的组合, 转化为 Ctrl 的组合

结果

SendMode Input
SetWorkingDir %A_ScriptDir%
SetCapsLockState, AlwaysOff

; CapsLock 轻按 = Esc
CapsLock::Send {Esc}

; CapsLock 组合键映射为 Ctrl 组合
CapsLock & a::Send ^a
CapsLock & b::Send ^b
; 略

; 数字键
CapsLock & 0::Send ^0
CapsLock & 1::Send ^1
; 略

; 功能键
CapsLock & F1::Send ^F1
CapsLock & F2::Send ^F2
; 略

; 符号键
CapsLock & `;::Send ^`;
CapsLock & =::Send ^=
; 略

; 其他特殊键
CapsLock & Delete::Send ^Delete
CapsLock & Insert::Send ^Insert
; 略

; 方向键
CapsLock & Up::Send ^Up
CapsLock & Down::Send ^Down
; 略

; 小键盘
CapsLock & Numpad0::Send ^Numpad0
CapsLock & Numpad1::Send ^Numpad1
; 略

实现出来的效果非常棒. 

因为从根本上排除了长按与短按的逻辑麻烦, 直接用系统级的单键和组合键逻辑.


一时间, 我想到了多年前, 在外贸公司的时候, 设置运费的问题.

对于某一个国家, 运输用的是一个奇葩公司, 没有提供计算运费的API接口. 我们一直都是要求客人通过客服手动创建订单, 因为知道客人要购买的产品后, 客服再设置订单的运费.

后来有一天, 公司请了一个IT人员, 我把这个问题沟通了一下. 我本来还想TA是不是能找到什么方式实现这个运费的自动计算. 后来, TA发现 Shopify是可以对某个国家设置多项 {重量-运费} 的设置的. 那么TA就按0.5kg一档, 一直到100kg, 每一档重量都设置了运费. 总共200项, 也不是"不可能"的任务. 就算要考虑到运费波动的因素, 直接把运费上浮一点设置进去, 这样运费波动了公司也不是亏的.


总结

能优雅的时候 还是要优雅; 默认还是要追求优雅.

但是 傻大笨粗 力大砖飞 的方案, 也不能完全排除. 该用的时候还是要用, 捏着鼻子用也要用. 

特别是现在这个时代, 重复的笨工作, 可以交给GPT来做.



评论

The Hot3 in Last 7 Days

酒馆SillyTavern 玩英文角色卡 也能以中文输出 设置世界书Lorebooks

搭 Docker版 Sub-Store 带 http-meta 实现 集合订阅 测延迟 排序 筛选 生成新订阅 定时任务上传Gist