LoginSignup
6
8

More than 5 years have passed since last update.

AutoHotkeyでゆるゆるなemacsキーバインド

Posted at

目的

emacsのキーバインドをEclipseやAtomなど、使いたいアプリケーションに応じて、個別に調べて設定するのは大変。にもかかわらず、本当にあったらうれしいキーバインドはC-hなどシンプルなものだけ。であれば、OSのキーバインドをフックして全般的に変えてくれる系がうれしい。

そこで、AutoHotkeyを使って自分が必要な最低限のキーバインドだけを残し、かつIMEのトグルとAutoHotkey自信のON/OFFも切り替えられるように調べてScriptを作る。

ダウンロード&インストール

AutoHotkeyからWindowsインストーラをダウンロード。
そのインストーラを叩くだけ。

設定の作成

ネットにあるemacsのSciptを参考に作る。変更後の設定は、この最後尾に載せる。

emacsキーバインドで有効にしているもの

各ソフトのキーバインドと被るので、最小限のみ。

  • C-f, C-b, C-n, C-pの十字移動
  • C-a, C-eの先頭末尾移動
  • C-h, C-dの削除
  • C-mの改行

IMEの設定

IMEはC-oで切り替えたいので、AutoHotkeyを流行らせるアップローダ跡地から089のIMEの切り替えよう関数の設定をダウンロードして、下記のコードを埋め込む。

#Include IME.ahk

^o::
  If is_target()
    Send %A_ThisHotkey%
  Else
  {
    getIMEMode := IME_Get()
    If (%getIMEMode% = 0)
    {
      IME_SET(1)
      Return
    }
    Else
    {
      IME_SET(0)
      Return
    }
  }
  Return

AutoHotkeyのON/OFF切り替え

どうしてもほかのソフトとバッティングする場合は、一時停止したい。C-@にSuspendを割り当てる。通知領域にAutoHotkeyを表示しておくと、Suspend中はSになる。

^@::
  Suspend, Toggle
  Return

全設定

;;
;; An autohotkey script that provides emacs-like keybinding on Windows
;;
#InstallKeybdHook
#UseHook
#Include IME.ahk

; The following line is a contribution of NTEmacs wiki http://www49.atwiki.jp/ntemacs/pages/20.html
SetKeyDelay 0

; turns to be 1 when ctrl-x is pressed
is_pre_x = 0
; turns to be 1 when ctrl-space is pressed
is_pre_spc = 0

; Applications you want to disable emacs-like keybindings
; (Please comment out applications you don't use)
is_target()
{
  IfWinActive,ahk_class ConsoleWindowClass ; Cygwin
    Return 1
  IfWinActive,ahk_class MEADOW ; Meadow
    Return 1
  IfWinActive,ahk_class cygwin/x X rl-xterm-XTerm-0
    Return 1
  IfWinActive,ahk_class MozillaUIWindowClass ; keysnail on Firefox
    Return 1
  ; Avoid VMwareUnity with AutoHotkey
  IfWinActive,ahk_class VMwareUnityHostWndClass
    Return 1
  IfWinActive,ahk_class Vim ; GVIM
    Return 1
;  IfWinActive,ahk_class SWT_Window0 ; Eclipse
;    Return 1
;   IfWinActive,ahk_class Xming X
;     Return 1
;   IfWinActive,ahk_class SunAwtFrame
;     Return 1
;   IfWinActive,ahk_class Emacs ; NTEmacs
;     Return 1  
;   IfWinActive,ahk_class XEmacs ; XEmacs on Cygwin
;     Return 1
  Return 0
}

delete_char()
{
  Send {Del}
  global is_pre_spc = 0
  Return
}
delete_backward_char()
{
  Send {BS}
  global is_pre_spc = 0
  Return
}
kill_line()
{
  Send {ShiftDown}{END}{SHIFTUP}
  Sleep 50 ;[ms] this value depends on your environment
  Send ^x
  global is_pre_spc = 0
  Return
}
open_line()
{
  Send {END}{Enter}{Up}
  global is_pre_spc = 0
  Return
}
quit()
{
  Send {ESC}
  global is_pre_spc = 0
  Return
}
newline()
{
  Send {Enter}
  global is_pre_spc = 0
  Return
}
indent_for_tab_command()
{
  Send {Tab}
  global is_pre_spc = 0
  Return
}
newline_and_indent()
{
  Send {Enter}{Tab}
  global is_pre_spc = 0
  Return
}
isearch_forward()
{
  Send ^f
  global is_pre_spc = 0
  Return
}
isearch_backward()
{
  Send ^f
  global is_pre_spc = 0
  Return
}
kill_region()
{
  Send ^x
  global is_pre_spc = 0
  Return
}
kill_ring_save()
{
  Send ^c
  global is_pre_spc = 0
  Return
}
yank()
{
  Send ^v
  global is_pre_spc = 0
  Return
}
undo()
{
  Send ^z
  global is_pre_spc = 0
  Return
}
find_file()
{
  Send ^o
  global is_pre_x = 0
  Return
}
save_buffer()
{
  Send, ^s
  global is_pre_x = 0
  Return
}
kill_emacs()
{
  Send !{F4}
  global is_pre_x = 0
  Return
}

move_beginning_of_line()
{
  global
  if is_pre_spc
    Send +{HOME}
  Else
    Send {HOME}
  Return
}
move_end_of_line()
{
  global
  if is_pre_spc
    Send +{END}
  Else
    Send {END}
  Return
}
previous_line()
{
  global
  if is_pre_spc
    Send +{Up}
  Else
    Send {Up}
  Return
}
next_line()
{
  global
  if is_pre_spc
    Send +{Down}
  Else
    Send {Down}
  Return
}
forward_char()
{
  global
  if is_pre_spc
    Send +{Right}
  Else
    Send {Right}
  Return
}
backward_char()
{
  global
  if is_pre_spc
    Send +{Left}
  Else
    Send {Left}
  Return
}
scroll_up()
{
  global
  if is_pre_spc
    Send +{PgUp}
  Else
    Send {PgUp}
  Return
}
scroll_down()
{
  global
  if is_pre_spc
    Send +{PgDn}
  Else
    Send {PgDn}
  Return
}



^f::
  If is_target()
    Send %A_ThisHotkey%
  Else
    forward_char()
  Return  
^d::
  If is_target()
    Send %A_ThisHotkey%
  Else
    delete_char()
  Return
^h::
  If is_target()
    Send %A_ThisHotkey%
  Else
    delete_backward_char()
  Return
^o::
  If is_target()
    Send %A_ThisHotkey%
  Else
  {
    getIMEMode := IME_Get()
    If (%getIMEMode% = 0)
    {
      IME_SET(1)
      Return
    }
    Else
    {
      IME_SET(0)
      Return
    }
  }
  Return
^g::
  If is_target()
    Send %A_ThisHotkey%
  Else
    quit()
  Return
^m::
  If is_target()
    Send %A_ThisHotkey%
  Else
    newline()
  Return
!s::
  If is_target()
    Send %A_ThisHotkey%
  Else
    isearch_forward()
  Return
;$^{Space}::
^vk20sc039::
  If is_target()
    Send {CtrlDown}{Space}{CtrlUp}
  Else
  {
    If is_pre_spc
      is_pre_spc = 0
    Else
      is_pre_spc = 1
  }
  Return
^@::
  Suspend, Toggle
  Return
^a::
  If is_target()
    Send %A_ThisHotkey%
  Else
    move_beginning_of_line()
  Return
^e::
  If is_target()
    Send %A_ThisHotkey%
  Else
    move_end_of_line()
  Return
^p::
  If is_target()
    Send %A_ThisHotkey%
  Else
    previous_line()
  Return
^n::
  If is_target()
    Send %A_ThisHotkey%
  Else
    next_line()
  Return
^b::
  If is_target()
    Send %A_ThisHotkey%
  Else
    backward_char()
  Return
6
8
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
6
8