概要
AutoHotkey を用いて、SandSしてみようという試みです。
前の記事から切り出しました。
AutoHotkeyでどこでもVimっぽくカーソル移動したい(モードレス版)
環境
- windows10 Home 1909
- AutHotkey v.1.1.33.02
SandS とは
スペースバーにスペースバー以外の働きを持たせようという考え方です。
スペースバーを単体で押して離した場合は、単なるスペースバーとして作用するようにしておくため、スペースを入力することができなくなってしまうわけではありません。
スペースバーを押し下げている間に、他のキーを同時に押した場合、異なった作用をさせよう。という趣旨です。
元々は SandS (Space and Shift) の名の通り、スペースバーにシフトキー(小文字→大文字)の機能を持たせる物です。
具体的に説明をすると・・・
-
キーボードの「a」を打つと画面には「a」と出る。コレは当たり前です。。
-
シフトキーを押し下げても何も起こりません。
シフトキーを押したまま、キー「a」を打つと、画面には「A」と出る。
その後、シフトキーを離しても何も起きない。コレもまだ当たり前です。 -
キーボードのスペースバーを押し下げると、空白文字がキーリピートによりドバーと入り始めます。
スペースバーを押したまま、キー「a」を打つと、空白文字のリピートが止まり、画面には「a」と出ます。
その後、スペースバーを離しても何も起きません。コレもまだまだ当たり前です。
ここまでが、いつもの当たり前の世界です。
それが、SandS では以下のようになります。
- スペースバーを押し下げても何も起こりません。(普通じゃない!)
スペースバーを押したまま「a」を打つと、「A」と出る。(何それ便利!?)
ちなみに、何もせずにスペースバーを離したときには1文字分だけの空白文字が画面に出力されます。
代償として、空白文字のキーリピートによる連続入力が行えなくなります。
SKK、とか、新JISカナ入力、とか、英文タイプといった方面などでは、重宝する人もいるとかいないとか。
ちなみに、元SKK使いですが、確かに便利でした。さらに、元新JISカナ使いでもありますが、確かに便利でした。
日本語入力をしている上では、スペースバーは仮名漢字変換の機能に用いることが多いと思います。
スペースバーを押し下げて変換を開始、そのまま次の文章の入力を続けたつもりが、スペースバーから指が離れる前に文字の入力をしてしまっていて、変なところに大文字アルファベットが?とかいうこともあると聞き及んでいます。
個人的には、「、」「。」を入力するときに、その直前の文章を変換した時のスペースが残ってしまって「>」や「<」が入力される事がありました。
AutoHotkey で SandS
修飾キーと同時にスペースが状態で押された場合は、素直に「修飾キー+スペース」として働いてほしいため、*Space::
ではなく、Space::
を対象に実装しています。
#InstallKeybdHook
$Space::
if SandS_guard = True ;スペースキーガード
return
SandS_guard = True ;スペースキーにガードをかける
Send,{Shift Down} ;シフトキーを仮想的に押し下げる
ifNotEqual SandS_key ;既に入力済みの場合は抜ける
return
SandS_key=
Input,SandS_key,L1 V ;1文字入力を受け付け(入力有無判定用)
return
$Space up:: ;スペース解放時
input ;既存のInputコマンドの終了
if SandS_guard = False ;ガードがかかってなかった場合(修飾キー+Spaceのリリース)
return
SandS_guard = False ;スペースキーガードを外す
Send,{Shift Up} ;シフトキー解放
ifEqual SandS_key ;SandS文字入力なし
Send,{Space} ;スペースを発射
SandS_key=
return
解説
修飾キー同時の押しについて
修飾キーを優先させたいため、あえて*Space::
ではなくSpace::
を使用しています。
そのため Shif+Space によるスペースの入力はキーリピートが効くという利点(?)もあります。
また、<^Space::
や>+Space::
等のように、個別に定義しなおすこともできます。
以下、失敗例
修飾キー同時押し時も含めて SandS にしたいとき(失敗例)
修飾キーと Space 同時押しした時にも、Space を Shift キーとして使いたい、という場合―――あまり考えられない状況ですが、Shift 以外の修飾キー、例えば Ctrl+Space を Ctrl+Shift として扱いたい、と言う感じでしょうか?―――もし、上記スクリプトを単純に*Space::
に置き換えてしまうと、ALT+Space や Shift+Space や Ctrl+Space Win+Space 等もすべて該当ルーチン内で処理されてしまい、シフト押し下げ相当の事しかしてくれなくなってしまいます。
コントロールメニューにフォーカスを移すことも、Excel で行選択や列選択をすることも、できなくなってしまいます。
(Win+Space による IME の切り替えもできなくなりますが、それはあまり使わないので問題ない。)
そこで出てくるのが Send コマンドの 「{Blind}」というキーワードです。
通常、Send コマンドでは、修飾キーは仮想的に離された状態として処理されますが、「{Blind}」をキー名の前につけることで、修飾キーの自動復元を行ってくれます。
一応書いてみると、こんな感じになりますか。
ついでに、up::
時のinput
の空打ちがないと、%SandS_key%
に半角空白が入ってきてしまうので、%A_Space%
との比較が必要になってしまうという例も盛り込んでおきます。
#InstallKeybdHook
$*Space:: ;スペース押下時
if SandS_guard = True ;スペースキーガード
Return
SandS_guard = True ;スペースキーにガードをかける
Send,{Shift Down} ;シフトキーを仮想的に押し下げる
ifNotEqual SandS_key ;文字入力済みの場合は終わり
return
SandS_key=
Input,SandS_key,L1 V ;1文字入力を受け付け(入力有無判定用)
Return
$*Space up:: ;スペース解放時
;input ;既存のInputコマンドの終了
SandS_guard = False ;スペースキーガードを外す
Send,{Shift Up} ;シフトキー解放
ifEqual SandS_key ;SandS文字入力なし
Send,{Blind}{Space} ;修飾を復元しながらスペースを発射
ifEqual SandS_key,%A_Space% ;空白文字(Inputに、Sendした{Space}が詰まるため)
Send,{Blind}{Space} ;修飾を復元しながらスペースを発射
SandS_key=
Return
Shift+Space を入力してもリピートもされないのは良いとしても、Ctrl+Space を入力すると、私の環境ではなぜか、IME の切り替えが暴発したりしますね。謎です。
IME の切り替えが暴発する時点でお話になりませんが、もう一つ、使い物にならない理由があります。
IME が全角入力になっている最中に、 Shift → Space の順で押下します。その後、Shift → Space という順番で指を離してみてください。半角空白を期待していたのに、全角空白が入ってしまうのです。
Shift → Space と押された時点で*Space::
が動き出しますが、Space を離すまで空白文字はまだ入力されません。Shift → Space と離された時点で*Space up::
が動き出しますが、この時点ではもうShiftは押されておらず、Send コマンドの Blind 指定もむなしく、IME の状態に従って全角空白が入力されてしまうのです。嗚呼、残念無念。
修飾キー同時押し時も含めて SandS にしたいとき(押下、解放の順序問題へ対応)
上記の失敗を回避するために、*Space::
の中で、Space が押された瞬間に、どの修飾キーが押されていたのか覚えておけば良いじゃん!というアプローチもあります。
もはや、あまりする必要の無い苦労ですが、どうしても Shift+Space がリピートしてしまうのが嫌だ! とか、Ctrl+Space+a の場合には Ctrl+A として振舞ってほしいんだ! いう場合にはもう少し迷走してみるのもよいでしょう。
こうなりました。
#InstallKeybdHook
$*Space:: ;スペース押下時
;tooltip,"%SandS_mod%" "%SandS_key%" %SandS_guard% ;debug
if SandS_guard = True ;スペースキーガード
Return
SandS_guard = True ;スペースキーにガードをかける
Send,{Shift Down} ;シフトキーを仮想的に押し下げる
SandS_mod= ;装飾キー退避
GetKeyState, state, Shift,P
if state=D
SandS_mod=%SandS_mod%+
GetKeyState, state, Ctrl,P
if state=D
SandS_mod=%SandS_mod%^
GetKeyState, state, Alt,P
if state=D
SandS_mod=%SandS_mod%!
GetKeyState, state, LWin,P
if state=D
SandS_mod=%SandS_mod%#
GetKeyState, state, RWin,P
if state=D
SandS_mod=%SandS_mod%#
ifNotEqual SandS_key ;文字入力済みの場合は終わり
return
SandS_key=
Input,SandS_key,L1 V ;1文字入力を受け付け(入力有無判定用)
Return
$*Space up:: ;スペース解放時
;tooltip,"%SandS_mod%" "%SandS_key%" %SandS_guard% ;debug
input ;既存のInputコマンドの終了
SandS_guard = False ;スペースキーガードを外す
Send,{Shift Up} ;シフトキー解放
ifNotEqual SandS_mod ;修飾キーありの場合
Send,%SandS_mod%{Space} ;自前で修飾しながらスペースを発射!
else ;修飾キー同時押しではなかった場合
ifEqual SandS_key ;SandS文字入力なし
Send,{Space} ;単打のスペースを発射
SandS_key=
Return
Shift+Spaceを長押ししても、Spaceを離すまで何も入力されず、キーリピートも抑止されています。
問題だった、Shift → Space の順で押し下げて、Shift → Space の順で離してみても、全角空白は出ませんね!成功です。
でも 私の端末では、相変わらず Ctrl 同時押し時の IME 切り替えが暴発します。