2014年10月6日月曜日

[windows][emacs] Windows 8.1上で(特定ユーザーログイン時に)任意のアプリの操作をemacsキーバインドにする方法

windows 8.1上のすべての操作をemacsキーバインドにできないか、と思ってネット上の情報を探したところ、keyhacというぴったりのツールが見つかりました。カスタマイズが自由&簡単、かつクリップボード履歴機能つき!

自分としては以下の設定ができれば目的達成です。
  • CapsLockをCtrlキーに
  • IMEのon/offを変換キーで
  • カーソル移動・クリップボード関連操作などをemacsキーバインドに
  • 可能であれば特定ユーザー(自分のアカウント)ログイン時のみ限定したい・・・
こちらのブログで紹介されているpythonスクリプトを、keyhac.exeと同じディレクトリにconfig.pyという名前で保存するだけでemacsキーバインドが実現できました。感謝。

config.pyのカスタマイズ方法:

せっかくなのでkeyhacのconfig.pyによるカスタマイズ方法を簡単に紹介しておきます。
config.pyでは任意のアプリ上のオリジナルのキー操作をpythonスクリプトで記述することができ、それをkeyhac上のキー操作に割り当てることで、キーバインドを実現しています。
たとえば「ペースト」はyank()という関数で以下のように定義されています。
    
            def yank():
                keymap.command_InputKey("C-v")()
                keymap_emacs.is_mark = False
    
    
それをkeymap_emacsでCtrl-yにバインドしています。
    
            keymap_emacs["C-y"]             = reset(yank)
    
    
上記のような感じで、簡単に設定が可能です。以下、自分の環境にあわせて追加した設定を紹介しておきます。
  • IMEのon/offを変換キーに割り当てる
  • 
        keymap.replaceKey( 28, 243 )
    
    
  • config.pyの編集には秀丸を利用(※"\"はエスケープが必要)
  • 
        keymap.editor = u"C:\\Program Files\\Hidemaru\\Hidemaru.exe"
    
    
  • キーバインドを変更しないアプリにexplorerとemacs-X11を追加
  • 
        def is_emacs_target(window):
            if window.getProcessName() in (# skip...
                                           "explorer.exe",       # explorer
                                           "emacs-X11.exe",      # Emacs-X11
    
    
    
  • ついでにforward/backward wordとdelete wordの定義を追加
  • 
        def forward_word():
            keymap.command_InputKey("C-Right")()
        def backward_word():
            keymap.command_InputKey("C-Left")()
        def delete_word():
            keymap.command_InputKey("C-S-Right")()
            kill_region()
            keymap_emacs.is_mark = False
        def delete_backward_word():
            keymap.command_InputKey("C-S-Left")()
            kill_region()
            keymap_emacs.is_mark = False
    
        keymap_emacs["A-b"]             = repeat(mark(backward_word))
        keymap_emacs["A-f"]             = repeat(mark(forward_word))
        keymap_emacs["A-d"]             = reset(delete_word)
        keymap_emacs["C-Back"]          = reset(delete_backward_word)
    
    

keyhacで実現できないキーバインド:

残念ながら、[Ctrl]と[Caps Lock]の入れ替えのみ、keyhacでは実現できませんでした。これは、ドライバのレイヤで、[Caps Lock]のUPイベントを抑制しているのが原因のようです。keymap.replaceKey( "LCtrl", 240 )という設定をしても意図した動作になりません。
仕方がないのでここの情報に従いレジストリをいじって、[Caps Lock]をつぶして[Ctrl]にすることで対応しています。入れ替えではなく上書きなので、本来の[Ctrl]と[Caps Lock]の両方が[Ctrl]の役割を持っている状態です。このため[Caps Lock]に[Ctrl]に割り当てる設定だけは、特定ユーザー限定という設定ができませんでした。

(2014/10/06追記)
C-k, A-d, C-BSなど範囲選択後、切り取りをするスクリプトはタイミング依存の問題(?)があるようで、keyhacの「内部デバッグ」をOFFにしていると、期待通り動作しないようです。手元の環境ではONにしていると動作しています(が、動作がのろくなるのでOFFにしたい・・・)。

(2016/01/11追記)
Caps LockにCtrlキーを割り当てる手順

  • regeditで以下のキーにScancode Mapという名前でバイナリ値を設定
    • HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout
  • 格納するバイナリ値のデータは以下の通り
    • 00 00 00 00 00 00 00 00
    • 03 00 00 00 1D 00 3A 00
    • 3A 00 3A 00 00 00 00 00

keyhac.iniを修正しコンソールウィンドウを非表示に:

デフォルトではkeyhac起動時、コンソールウィンドウが表示されます。このウィンドウを非表示にするには、keyhac.exeが存在しているディレクトリに生成されているkeyhac.iniの[console]セクションに記述されているvisible=1をvisible=0に設定すればOKです。ただし、この設定は公式ドキュメントには記載されていないようなので、自己責任でお願いします。

参考:

ちなみにmacではKarabiner(旧KeyRemap4MacBook)をインストールすれば、簡単にemacsキーバインドが実現できます。

11 件のコメント:

  1. はじめまして。
    keyhacを検索しているとここへたどり着きました。
    可能であればおしえていただきたいことがあります。
    現状config.pyは、http://www49.atwiki.jp/ntemacs/pages/25.htmlで公開されているものを
    利用しています。
    この場合、「貼り付け」は、「c-y」となっています。
    これを「c-v」に変更したいのですが、どこをどう直したらいいのでしょうか。
    プログラミングをやったことがなく皆目わからないのです。
    突然のお願いで恐縮ですが、是非ご教授願います。
    よろしくお願いします。

    返信削除
    返信
    1. > これを「c-v」に変更したいのですが、どこをどう直したらいいのでしょうか。

      「c-v」を「c-y」と同じ挙動にしたい、ということですよね。
      keymap_emacs["LC-v"] = reset_search(reset_counter(mark(scroll_down)))
      523行目の上記の記述を以下のように書き換えればOKです。
      keymap_emacs["LC-v"] = reset_search(reset_counter(reset_mark(yank)))

      # 548 行目にある「c-y」用の定義をもってきて、割り当て対象のキーを「c-v」に変更しています。

      削除
  2. ありがとうございました。うまく行きました。助かりました。
    恐縮なのですが、もう2点教えていただけませんでしょうか。
    1.「c-x」をWindowsでいう「切り取り」にしたいのですが、
      設定ファイルをどういじればいいのでしょうか。
    2.「ctrl + alt + h」のショートカットキーで秀丸を起動させたいのですが、うまくいきません。
      別のアプリですが、「ctrl + alt + c」で別のアプリは起動します。
    何卒、よろしくお願いします。

    返信削除
    返信
    1. > 1.「c-x」をWindowsでいう「切り取り」にしたいのですが、
      >   設定ファイルをどういじればいいのでしょうか。
      434行目の以下の記述を削除すれば所望の動作になると思います。
      keymap_emacs["LC-x"] = keymap.defineMultiStrokeKeymap("C-x")

      > 2.「ctrl + alt + h」のショートカットキーで秀丸を起動させたいのですが、うまくいきません。
      >   別のアプリですが、「ctrl + alt + c」で別のアプリは起動します。
      ご利用のconfig.pyは「ctrl + alt + h」に対していは、何も設定していないようです。
      http://kurokawh.blogspot.jp/2013/05/win7-windows7.html
      ↑ではどうでしょうか。
      もしくは、秀丸の設定で「秀丸エディタの常駐」で「ctrl + alt + h」を設定すればよいのでは。

      削除
  3. うまくいきました。ありがとうございました。

    返信削除
  4. 「C-k, A-d, C-BSなど範囲選択後に切り取りをするスクリプトのタイミング依存の問題」について対策してみました。 確認してみていただければと思います。

    http://www49.atwiki.jp/ntemacs/pages/25.html

    返信削除
    返信
    1. 上記を投稿したものです。
      「C-k, A-d, C-BSなど範囲選択後に切り取りをするスクリプトのタイミング依存の問題」が発生していたのは何のソフトだったか教えてもらえますか? 問題の発生するソフトと発生しないソフトがあると思っています。よろしくお願いします。

      削除
    2. すみません。対策が完全でなかったようです。一旦、Wikiの内容は元に戻しました。
      また、ご連絡します。

      削除
    3. 対策版をアップしてみました。まだ改善点があるかもしれませんが、確認いただければと思います。

      削除
    4. ありがとうございます!m(_ _)m
      近日中に確認の上、結果を報告させていただきます。

      削除
    5. すみません、自分用にカスタマイズした内容を、新しいconfig.pyにマージする時間が取れず、まだ更新版の確認できていません。http://www49.atwiki.jp/ntemacs/pages/25.html から過去バージョン(自分がベースにしたconfig.py)が得られないのがツライ…。最近、変更をgitに残し始めたのですが、肝心のオリジナルが残っていないので手動マージが必要になってます。orz

      削除