sea side she side

写真と山、資格が好きなアラフォーエンジニアのブログ

AutoHotkey

      2018/08/07

Windows 7になって直面した問題の一つが日本語入力のOff/Onのキーバインドでした。

Emacsキーバインドが大好きで、Windows VistaまではCmdSpace(Win+Spaceで日本語入力)とxkeymacsを使って生活していました。ところがWindows 7になってWin+SpaceのキーバインドをAeroの機能として強制的に奪ってしまうのです。

レジストリをいじったり他のソフトを試したりしたものの解決せずほとほと困っているところにAutoHotkeyなるものを見つけました。

AutoHotkeyはホットキーへの機能の割り当てなど常駐ソフトの作成に特化したスクリプトエンジンである。
多彩なコマンドが用意されており、GUIを持ったプログラムの作成も可能。
GNU GENERAL PUBLIC LICENSE Version 2の下で配布されるフリーソフトで、C++で作られている。

システムで奪われてしまった物でも奪い返せそうな情報があってわらをもすがる気持ちで使ってみたところ見事に奪い返すことができました!

例えば日本語入力On/Offであれば、

 #Space::!`
 !Space::!`

とすることで、Win+SpaceとAlt+SpaceがAlt+~(英語キーボードなので日本語入力はAlt+~)に置き換わります。

これならと思い普段使っているEmacsキーバインドもと思い実際に使っていたのですが、TeraTermでどうにもうまく動いてくれません。おそらくはTeraTermと先にあるShellが認識できないようです。

この時点でもう調べるのも面倒になってきていたので、AutoHotkey+xkeymacsの組み合わせで使っていたのですが、ふと思い出して調べ直したところ先人はやはりいる物です。

 WindowsでEmacs風キーバインド - USIPEDIA

TeraTermを除外処理する方法を取り入れてくれています。ただEmacsキーバインドしか愛せない人はこれをそのまま使うと思います(笑)が、さすがに^Cやら^Vはcopy、yankで使いたいので自分用に削ります。

xkeymacsの時と同様に、Win+Space、^f、^n、^b、^p、^a、^e、^d、^h、^jだけ残しました。

 ; for ATOK
 #Space::!`
 !Space::!`
 
 ;;
 ;; WindowsでEmacs風キーバインド
 ;;
 #InstallKeybdHook
 #UseHook
  
 ; C-x が押されると1になる
 is_pre_x = 0
 ; C-Space が押されると1になる
 is_pre_spc = 0
  
 ; Emacs風キーバインドを無効にしたいウィンドウ一覧
 ; 必要の無い部分はコメントアウトして下さい
 is_target()
 {
	IfWinActive,ahk_class VTWin32 ;teraterm
		Return 1
 	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 Vim ;Windows上のGVIM
 ;		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 ;Cygwin上のXEmacs
 ;		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
 }
 newline()
 {
 	Send {Enter}
 	global is_pre_spc = 0
 	Return
 }
 newline_and_indent()
 {
 	Send {Enter}{Tab}
 	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
 }
 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
 }
 
 
 ^f::
 	If is_target()
 		Send %A_ThisHotkey%
 	Else
 	{
 		If is_pre_x
 		find_file()
 		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
 ^j::
 	If is_target()
 		Send %A_ThisHotkey%
 	Else
 		newline_and_indent()
 	Return
 ^/::
 	If is_target()
 		Send %A_ThisHotkey%
 	Else
 		undo()
 	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
 ^@::
 	If is_target()
 		Send %A_ThisHotkey%
 	Else
 	{
 		If is_pre_spc
 			is_pre_spc = 0
 		Else
 			is_pre_spc = 1
 	}
 	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
 #k::
 	MsgBox, 4,, スクリプトを終了しますか?,
 	IfMsgBox, Yes
 		ExitApp
 	Return

今日も先人に感謝。

 - IT , , ,