AutoHotKeyのバージョンがv2に正式に移行になり、スクリプト内で使える文法が変更になりました。v2対応に必要な変更点が多いので、変更メモを残しておきます。最後に、Emacs風なキーバインド用の設定ファイルも掲載しておきます。
- 公式サイト:Changes from v1.1 to v2.0
https://www.autohotkey.com/docs/v2/v2-changes.htm
■AutoHotKey v1->v2への変更点
自分の使ってるスクリプトで、主に必要になった変更点は下記の通りです。
- ①変数代入式「a = 10」が「a := 10」に変更。
v1) a = 10
v2) a := 10
- ②if式の等号比較が、「==」から「=」に変更になった。
v1) if (a == b)
v2) if (a = b)
- ③ホットキーの中身が複数行になるときは、{}で囲う
v1) ^a::
move_beginning_of_line()
Return
v2) ^a::
{
move_beginning_of_line()
Return
}
- ④IfWinActiveが使えなくなった。
ref) https://www.autohotkey.com/docs/v2/lib/_HotIf.htm#variant
v1) IfWinActive,ahk_class Notepad
func()
v2) #HotIf WinActive("ahk_class Notepad")
^a::func()
- ⑤Send キーが、Send "キー"になった。
v1) Send ^a
Send {Esc}
v2) Send "^a"
Send "{Esc}"
- ⑥SetBatchLines -1がなくなり、デフォルトになった。
v1) SetBatchLines -1
v2) ;; SetBatchLines -1
- ⑦#InstallKeybdHook->InstallKeybdHookに変更
v1) #InstallKeybdHook
v2) InstallKeybdHook
- ⑧ListLines OffのOffが使えなくなった。0にすればよい。
v1) ListLines Off
v2) ListLines 0
- ⑨SendModeの第1引数が、Stringになった
v1) SendMode Input
v2) SendMode "Input"
- ⑩Suspendの第1引数が、Intになった
ref) https://www.autohotkey.com/docs/v2/lib/Suspend.htm
v1) Suspend Toggle
v2) Suspend ;; default is -1 (= Toggle)
- ⑪予約語の修飾子%%が要らなくなった。%A_ThisHotKey%->A_ThisHotKey
v1) Send %A_ThisHotKey%
v2) Send A_ThisHotKey
- ⑫nullの代入が右辺空欄から、右辺""に変わった
v1) var =
v2) var := ""
- ⑬Clipboard変数が、A_Clipboard変数に名称変更。
ref) https://www.autohotkey.com/docs/v2/lib/ClipWait.htm#Examples
v1) var = Clipboard
v2) var := A_Clipboard
■Emacs-likeな設定ファイル(v2対応)
emacs-like.ahk
;;
;; An autohotkey script that provides emacs-like keybinding on Windows
;;
;; global constants
DEBUG_MODE := 0
;; global variables
; turns to be 1 when ctrl-x is pressed
gIsCtrlXPressed := 0
; turns to be 1 when ctrl-space is pressed
gIsMarkDown := 0
; turns to be 1 when escape key is pressed
gIsEscapePressed := 0
; turns to be 1 when Ctrl-s, Ctrl-r
gIsSearching := 0
reset_pre_keys()
{
global
gIsCtrlXPressed := 0
gIsMarkDown := 0
gIsEscapePressed := 0
Return
}
reset_all_status()
{
reset_pre_keys()
global gIsSearching := 0
}
delete_char()
{
Send "{Del}"
reset_all_status()
Return
}
delete_backward_char()
{
Send "{BS}"
reset_all_status()
Return
}
kill_line()
{
Send "{ShiftDown}{END}{ShiftUp}"
Sleep 50 ;[ms] this value depends on your environment
A_Clipboard := "" ; set empty
Send "^x"
ClipWait(0.1) ; wait for copy finish
text := A_Clipboard ; get the copied text
;; if start pos is at line end (text is empty)
if (text = "") {
Send "{ShiftDown}{Right}{ShiftUp}"
Sleep 50 ;[ms] this value depends on your environment
Send "^x"
}
reset_all_status()
Return
}
open_line()
{
Send "{END}{Enter}{Up}"
reset_all_status()
Return
}
quit()
{
Send "{ESC}"
reset_all_status()
Return
}
newline()
{
Send "{Enter}"
reset_all_status()
Return
}
indent_for_tab_command()
{
Send "{Tab}"
reset_all_status()
Return
}
newline_and_indent()
{
Send "{Enter}{Tab}"
reset_all_status()
Return
}
isearch_forward()
{
global
If gIsSearching
Send "{F3}"
Else
{
Send "^f"
gIsSearching := 1
}
reset_pre_keys()
Return
}
isearch_backward()
{
global
If gIsSearching
Send "+{F3}"
Else
{
Send "^f"
gIsSearching := 1
}
reset_pre_keys()
Return
}
kill_region()
{
Send "^x"
reset_all_status()
Return
}
kill_ring_save()
{
Send "^c"
reset_all_status()
Return
}
yank()
{
Send "^v"
reset_all_status()
Return
}
undo()
{
Send "^z"
reset_all_status()
Return
}
find_file()
{
Send "^o"
reset_all_status()
Return
}
save_buffer()
{
Send "^s"
reset_all_status()
Return
}
kill_window()
{
Send "!{F4}"
reset_all_status()
Return
}
kill_buffer()
{
Send "^w"
reset_all_status()
Return
}
move_beginning_of_line()
{
global
If gIsMarkDown
Send "+{HOME}"
Else
{
Send "{HOME}"
reset_all_status()
}
Return
}
move_end_of_line()
{
global
If gIsMarkDown
Send "+{END}"
Else
{
Send "{END}"
reset_all_status()
}
Return
}
previous_line()
{
global
If gIsMarkDown
Send "+{Up}"
Else
{
Send "{Up}"
reset_all_status()
}
Return
}
next_line()
{
global
If gIsMarkDown
Send "+{Down}"
Else
{
Send "{Down}"
reset_all_status()
}
Return
}
forward_char()
{
global
If gIsMarkDown
Send "+{Right}"
Else
{
Send "{Right}"
reset_all_status()
}
Return
}
backward_char()
{
global
If gIsMarkDown
Send "+{Left}"
Else
{
Send "{Left}"
reset_all_status()
}
Return
}
scroll_up()
{
global
If gIsMarkDown
Send "+{PgUp}"
Else
{
Send "{PgUp}"
reset_all_status()
}
Return
}
scroll_down()
{
global
If gIsMarkDown
Send "+{PgDn}"
Else
{
Send "{PgDn}"
reset_all_status()
}
Return
}
; https://qiita.com/c-nuts/items/20d02e572b6a06d5dce7
ime_switch()
{
global
Send "{vkF3sc029}"
reset_all_status()
Return
}
pageup_top()
{
global
If gIsMarkDown
Send "+^{Home}"
Else
{
Send "^{Home}"
reset_all_status()
}
Return
}
pagedown_bottom()
{
global
If gIsMarkDown
Send "+^{End}"
Else
{
Send "^{End}"
reset_all_status()
}
Return
}
set_ignore_targets() {
; Applications you want to disable emacs-like keybindings
; (Please comment out applications you don't use)
GroupAdd "IgnoreTargets", "ahk_class ConsoleWindowClass" ; Cygwin, Ubuntu
GroupAdd "IgnoreTargets", "ahk_class cygwin/x X rl-xterm-XTerm-0"
GroupAdd "IgnoreTargets", "ahk_class VMwareUnityHostWndClass"
GroupAdd "IgnoreTargets", "ahk_class Vim" ; GVIM
GroupAdd "IgnoreTargets", "ahk_class Emacs" ; NTEmacs
GroupAdd "IgnoreTargets", "ahk_class XEmacs" ; XEmacs on Cygwin
GroupAdd "IgnoreTargets", "ahk_exe vcxsrv.exe" ; gnome-terminal
GroupAdd "IgnoreTargets", "ahk_exe xyzzy.exe" ; xyzzy
GroupAdd "IgnoreTargets", "ahk_exe putty.exe" ; PuTTY
GroupAdd "IgnoreTargets", "ahk_exe ttermpro.exe" ; TeraTerm
GroupAdd "IgnoreTargets", "ahk_exe TurboVNC.exe" ; VNC
GroupAdd "IgnoreTargets", "ahk_exe vncviewer.exe" ; VNC
}
main() {
if (DEBUG_MODE > 0)
InstallKeybdHook
;; Disable log
ListLines 0
;; Disable delay
SetControlDelay 0
;; SetKeyDelay 0
SetKeyDelay -1 ;; disable key delay
SetWinDelay 0
SendMode "Input"
;;SendMode "Play"
set_ignore_targets()
}
main()
#UseHook
;; Set suspend toggle key
#SuspendExempt
^F1::Suspend
#SuspendExempt False
#HotIf not WinActive("ahk_group IgnoreTargets")
^x::global gIsCtrlXPressed := 1
Esc::
{
global
If gIsEscapePressed
{
Send "{Esc}"
gIsEscapePressed := 0
}
Else
gIsEscapePressed := 1
Return
}
^f::
{
global
If gIsCtrlXPressed
find_file()
Else
forward_char()
Return
}
^c::
{
global
If gIsCtrlXPressed
kill_window()
Return
}
^d::delete_char()
^h::delete_backward_char()
^k::kill_line()
k::
{
global
If gIsCtrlXPressed
kill_buffer()
Else
Send A_ThisHotkey
Return
}
;;^o::open_line()
^o::ime_switch()
; Ctrl-\ (Backslash) vkE2sc073 SC02B
;^\::
;^vkE2sc073::
^vkE2::ime_switch()
^g::quit()
^j::newline_and_indent()
^m::newline()
^i::indent_for_tab_command()
^s::
{
global
If gIsCtrlXPressed
save_buffer()
Else
isearch_forward()
Return
}
^r::isearch_backward()
^w::kill_region()
!w::kill_ring_save()
w::
{
global
If gIsEscapePressed
kill_ring_save()
Else
Send A_ThisHotkey
Return
}
^y::yank()
^/::undo()
;; ^{Space}::
;; ^vk20sc039::
^vk20::
{
global
If gIsMarkDown
gIsMarkDown := 0
Else
gIsMarkDown := 1
Return
}
^a::move_beginning_of_line()
^e::move_end_of_line()
^p::previous_line()
^n::next_line()
^b::backward_char()
^v::scroll_down()
!v::scroll_up()
v::
{
global
If gIsEscapePressed
scroll_up()
Else
Send A_ThisHotkey
Return
}
!<::pageup_top()
<::
{
global
If gIsEscapePressed
pageup_top()
Else
Send A_ThisHotkey
Return
}
!>::pagedown_bottom()
>::
{
global
If gIsEscapePressed
pagedown_bottom()
Else
Send A_ThisHotkey
Return
}
■参考サイト
- AutoHotKey公式サイト:Changes from v1.1 to v2.0
https://www.autohotkey.com/docs/v2/v2-changes.htm - 🚀 Make the switch to AutoHotkey v2! 🚀 Here's what you need to know 💡
https://youtu.be/zpF1D7eMHXs - AutoHotkey v2 is now the official version of ahk
https://youtu.be/Tun3R634QgY - autohotkey v1 を autohotkey v2 に移植
https://benizara.hatenablog.com/entry/2023/03/05/014148 - Bug? HotIfWinActive
https://www.autohotkey.com/boards/viewtopic.php?style=2&t=95739 - Windows 10でemacs風キーバーインド。AutoHotKeyの設定をちょい足し編。
https://qiita.com/c-nuts/items/20d02e572b6a06d5dce7 - Windows 10でも「Emacs風キーバインド」を使おう【AutoHotKey】
https://linuxfan.info/windows-emacs-keybindings - Windows の操作を Emacs のキーバインドで行うための設定 (AutoHotKey版)
https://w.atwiki.jp/ntemacs/pages/20.html - GitHub - usi3 / emacs.ahk
https://github.com/usi3/emacs.ahk