AHK 和 US-INT 键盘:为什么不再吞下 "dead" 键?

AHK and US-INT keyboard: Why are "dead" keys no longer swallowed?

我通常使用美国-国际键盘布局。此布局有几个键设置为变音符号的“死”键 - 例如,按 ^ 是死键;在按下下一个键之前它似乎什么都不做;如果该键是一个音调符号是允许的变音符号,它将用标记的键替换它 - 也就是说,如果我按 ^ 然后 a ,我会得到 â - 但是如果我按下一个不允许使用变音符号的键,我会得到抑扬符后跟字母,例如 ^ 后面跟着 h 给我 ^h.

我写了一个 AHK 脚本,它添加了世界语的变音字符(见下文)。它曾经“透明地”工作并符合上述行为。但是,最近,行为似乎发生了变化:它不再“吞下”变音符号,而是在插入所需字符之前插入一个后退space。

换句话说,如果我输入“The Esperanto character that sounds like English 'ch' is” 然后输入 ^ 然后 c,它 后面的 space 替换为 ĉ,并且在下一次击键时,无论它是什么,就像我按下 ^ 然后那个键一样。

为什么?以及如何解决这个问题?

#Hotstring ? C * 

; Esperanto diacriticalized characters

::^c::ĉ
::^C::Ĉ
::^g::ĝ
::^G::Ĝ
::^h::ĥ
::^H::Ĥ
::^j::ĵ
::^J::Ĵ
::^s::ŝ
::^S::Ŝ
::~u::ŭ
::~U::Ŭ

不知道我是否可能错过了一些简单的热字串,但如果不尝试做一些更进一步的诡计,我无法真正让它工作。

我认为 InputHook(docs) 实现可以很好地工作。
不过它可能是 overkill/stupid,因为它基本上只是为热字串创建自定义实现。但是好吧,至少它有效。

key_map := { "c": "ĉ"
           , "g": "ĝ"
           , "h": "ĥ"
           , "j": "ĵ"
           , "s": "ŝ"
           , "u": "ŭ" }

ih := InputHook("V")
ih.OnChar := Func("OnChar")
ih.Start()

OnChar(_, char)
{
    if (StrLen(char) != 2 || SubStr(char, 1, 1) != "^" || !(key := diacriticalize(SubStr(char, 2))))
        return
    fObj := Func("SendReplacement").Bind(key)
    SetTimer, % fObj, -0
}

diacriticalize(key)
{
    global key_map
    if key is upper
        return Format("{:U}", key_map[key])
    else
        return key_map[key]
}

SendReplacement(key)
{
    SendInput, % "{BS 2}" key
}

发生了什么事?

首先定义密钥替换映射。
^ 添加任何额外的死键组合都可以正常工作。

输入挂钩仅使用 V(docs) 选项创建。
这使得它在处理输入时不会消耗输入。

然后,使用 .OnChar(docs) 我们定义一个函数,每次输入接收到一个新字符时 运行s。
这些函数总是只接收一个字符,除非使用死键时它会接收例如 ^c.
这就是为什么我们检查输入长度是否为二以及为什么我们使用 SubStr()(docs)^c 转换为 c 的原因。
SubStr(char, 1, 1) != "^" 还确保按下的死键是 ^,而不是 ¨。否则 ¨c 会产生 ĉ.

然后在用户定义的函数 diacriticalize() 中,我们 return 来自 key_map 的相应变音键(如果可能)。如果输入键是大写的,return 变音键也是大写的。
如果 key_map 中没有匹配的键,则不会 returned。如果输入键无效,这使得 || !(key := ...) 部分也会 return 发挥作用。

然后计时器(docs) 欺骗只是为了在另一个线程中执行 OnChar() 函数之外的替换以避免发送命令出现问题 运行太早了。
基本上句号 -0 只是意味着立即 运行 一次。
定时器将被定义为一个函数对象,它有一个参数(键)绑定到它 .Bind()(docs).

好的,我不确定为什么它以这种方式工作,但我可以通过关闭自动退格并手动添加我自己的来让它工作。修改后的AHK脚本如下:

#Hotstring ? C * B0
; Acts only as a supplement to a keyboard that (a) does not
; have these characters defined _and_ uses ^ and ~ as "dead"
; keys to apply accents.

::^c::{bs 2}ĉ
::^C::{bs 2}Ĉ
::^g::{bs 2}ĝ
::^G::{bs 2}Ĝ
::^h::{bs 2}ĥ
::^H::{bs 2}Ĥ
::^j::{bs 2}ĵ
::^J::{bs 2}Ĵ
::^s::{bs 2}ŝ
::^S::{bs 2}Ŝ
::~u::{bs 2}ŭ
::~U::{bs 2}Ŭ
::^::^
::~::~

#Hotstring 指令中的 B0 关闭自动退格。如果该选项在原始脚本中生效,键入 ^c 将导致 ^cĉ,因此通过向后插入两个 spaces 在它之前 ({bs 2}),我在插入 ĉ.

之前去掉了多余的 ^c

最后两行,将插入符和代字号替换为它们自己,对于需要它们的原因没有明显的解释,但它们确保行为与标准死键用法一致,因此如果我输入 ^spacec 我得到预期的 ^c意想不到的 ĉ.