5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AutoHotkeyでSandS

Last updated at Posted at 2020-09-03

概要

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::を対象に実装しています。

Sands.ahk
  #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%との比較が必要になってしまうという例も盛り込んでおきます。

Sands_Blind.ahk
  #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 として振舞ってほしいんだ! いう場合にはもう少し迷走してみるのもよいでしょう。

こうなりました。

SandS_Modif.ahk
  #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 切り替えが暴発します。

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?