Simplify tray menu

Simplify tray menu

#SingleInstance on
;#NoTrayIcon
SendMode Input

Menu, Tray, Icon, assets/keyboard.ico, 1, 1
Menu, Tray, Tip, Emoji Keyboard
Menu, Tray, Add, &Show, Toggle
Menu, Tray, Add
Menu, Tray, Add, Emoji &Keyboard by Gilles Waeber, Credits
Menu, Tray, Add
Menu, Tray, Add, E&xit, Exit
Menu, Tray, Default, &Show
Menu, Tray, NoStandard

#Include assets\JSON_ToObj.ahk
#Include assets\Webapp.ahk
__Webapp_AppStart:
;<< Header End >>

;             not focusable
Gui __Webapp_:+E0x08000000 +AlwaysOnTop -MaximizeBox -MinimizeBox ; +E0x40000 +ToolWindow ;  -Caption
OnMessage(0x112, "WM_SYSCOMMAND")
WinSet, Transparent, 230

WM_SYSCOMMAND(wParam)
{
	global vVisible
    if (wParam = 0xF060 and vVisible) ; SC_CLOSE hide instead of closing
    {
        Hide()
        return 0
    }
}

;Variable containing the current state
vVisible := false

;Get our HTML DOM object
iWebCtrl := getDOM()

;Change App name on run-time
setAppName("Emoji Keyboard")

; Our custom protocol's url event handler
app_call(args) {

	;MsgBox %args%
	param := SubStr(args, 6)
	if SubStr(args, 1, 5) = "send/"
		Send(param)
}

; function to run when page is loaded
app_page(NewURL) {
}

Gui __Webapp_:Hide

~LAlt::	; <-- OPEN with double left alt key
	global vVisible
	if (A_PriorHotkey <> "~LAlt" or A_TimeSincePriorHotkey > 400) {
		if(vVisible){
			vVisible := false
			Hide()
			KeyWait, LAlt
			Send, {LAlt}
		}
		return
	}
	KeyWait, LAlt
	Show()
Return

; Functions to be called from the html/js source
Exit() {
	ExitApp
}

clipSaved =
bClipSaved := False

Credits(){
	Run, http://www.gilleswaeber.ch
}
Reload() {
	Reload
}
Run(t) {
	Run, %t%
}
Send(t) {
	global clipSaved, bClipSaved
	if(not bClipSaved){
		clipSaved := ClipboardAll
		bClipSaved := True
	}
	Clipboard := t
	Sleep, 10
	Send, ^v
	SetTimer, RestoreClipboard, 200
}
RestoreClipboard() {
	global clipSaved, bClipSaved
	SetTimer, RestoreClipboard, Off
	Clipboard := clipSaved
	clipSaved =
	bClipSaved := False
}
Show(){
	global vVisible
	vVisible := true
	Gui __Webapp_:Show
	Sleep, 10
	Send, !{Esc}
}
Hide(){
	global vVisible
	vVisible := false
	Gui __Webapp_:Hide
}
Toggle(){
	global vVisible
	if(vVisible){
		Hide()
	}
	else{
		Show()
	}
}
Ready(){
	global j
	getDOM().document.ahk.setKeymap(j.keymap)
}

#If vVisible
; Corresponding keys                    	;	US	CH
SC001::getDOM().document.ahk.input(1)   	;	ESC	ESC
SC03B::getDOM().document.ahk.input(59)   	;	F1	F1
SC03C::getDOM().document.ahk.input(60)   	;	F2	F2
SC03D::getDOM().document.ahk.input(61)   	;	F3	F3
SC03E::getDOM().document.ahk.input(62)   	;	F4	F4
SC03F::getDOM().document.ahk.input(63)   	;	F5	F5
SC040::getDOM().document.ahk.input(64)   	;	F6	F6
SC041::getDOM().document.ahk.input(65)   	;	F7	F7
SC042::getDOM().document.ahk.input(66)   	;	F8	F8
SC043::getDOM().document.ahk.input(67)   	;	F9	F9
SC044::getDOM().document.ahk.input(68)   	;	F10	F10
SC057::getDOM().document.ahk.input(87)   	;	F11	F11
SC058::getDOM().document.ahk.input(88)   	;	F12	F12
SC029::getDOM().document.ahk.input(41)   	;	`	§
SC002::getDOM().document.ahk.input(2)    	;	1	1
SC003::getDOM().document.ahk.input(3)   	;	2	2
SC004::getDOM().document.ahk.input(4)   	;	3	3
SC005::getDOM().document.ahk.input(5)   	;	4	4
SC006::getDOM().document.ahk.input(6)   	;	5	5
SC007::getDOM().document.ahk.input(7)   	;	6	6
SC008::getDOM().document.ahk.input(8)   	;	7	7
SC009::getDOM().document.ahk.input(9)   	;	8	8
SC00A::getDOM().document.ahk.input(10)   	;	9	9
SC00B::getDOM().document.ahk.input(11)   	;	0	0
SC00C::getDOM().document.ahk.input(12)   	;	-	'
SC00D::getDOM().document.ahk.input(13)   	;	=	^
SC010::getDOM().document.ahk.input(16)   	;	q	q
SC011::getDOM().document.ahk.input(17)   	;	w	w
SC012::getDOM().document.ahk.input(18)   	;	e	e
SC013::getDOM().document.ahk.input(19)   	;	r	r
SC014::getDOM().document.ahk.input(20)   	;	t	t
SC015::getDOM().document.ahk.input(21)   	;	y	z
SC016::getDOM().document.ahk.input(22)   	;	u	u
SC017::getDOM().document.ahk.input(23)   	;	i	i
SC018::getDOM().document.ahk.input(24)   	;	o	o
SC019::getDOM().document.ahk.input(25)   	;	p	p
SC01A::getDOM().document.ahk.input(26)   	;	[	è
SC01B::getDOM().document.ahk.input(27)   	;	]	¨
SC01E::getDOM().document.ahk.input(30)   	;	a	a
SC01F::getDOM().document.ahk.input(31)   	;	s	s
SC020::getDOM().document.ahk.input(32)   	;	d	d
SC021::getDOM().document.ahk.input(33)   	;	f	f
SC022::getDOM().document.ahk.input(34)   	;	g	g
SC023::getDOM().document.ahk.input(35)   	;	h	h
SC024::getDOM().document.ahk.input(36)   	;	j	j
SC025::getDOM().document.ahk.input(37)   	;	k	k
SC026::getDOM().document.ahk.input(38)   	;	l	l
SC027::getDOM().document.ahk.input(39)   	;	;	é
SC028::getDOM().document.ahk.input(40)   	;	'	à
SC02B::getDOM().document.ahk.input(43)   	;	\	$
SC056::getDOM().document.ahk.input(86)   	;	\	<
SC02C::getDOM().document.ahk.input(44)   	;	z	y
SC02D::getDOM().document.ahk.input(45)   	;	x	x
SC02E::getDOM().document.ahk.input(46)   	;	c	c
SC02F::getDOM().document.ahk.input(47)   	;	v	v
SC030::getDOM().document.ahk.input(48)   	;	b	b
SC031::getDOM().document.ahk.input(49)   	;	n	n
SC032::getDOM().document.ahk.input(50)   	;	m	m
SC033::getDOM().document.ahk.input(51)   	;	,	,
SC034::getDOM().document.ahk.input(52)   	;	.	.
SC035::getDOM().document.ahk.input(53)   	;	/	-
+SC029::getDOM().document.ahk.input(41)   	;	`	§
+SC002::getDOM().document.ahk.input(2,1)	;	1	1
+SC003::getDOM().document.ahk.input(3,1)	;	2	2
+SC004::getDOM().document.ahk.input(4,1)	;	3	3
+SC005::getDOM().document.ahk.input(5,1)	;	4	4
+SC006::getDOM().document.ahk.input(6,1)	;	5	5
+SC007::getDOM().document.ahk.input(7,1)	;	6	6
+SC008::getDOM().document.ahk.input(8,1)	;	7	7
+SC009::getDOM().document.ahk.input(9,1)	;	8	8
+SC00A::getDOM().document.ahk.input(10,1)	;	9	9
+SC00B::getDOM().document.ahk.input(11,1)	;	0	0
+SC00C::getDOM().document.ahk.input(12,1)	;	-	'
+SC00D::getDOM().document.ahk.input(13,1)	;	=	^
+SC010::getDOM().document.ahk.input(16,1)	;	q	q
+SC011::getDOM().document.ahk.input(17,1)	;	w	w
+SC012::getDOM().document.ahk.input(18,1)	;	e	e
+SC013::getDOM().document.ahk.input(19,1)	;	r	r
+SC014::getDOM().document.ahk.input(20,1)	;	t	t
+SC015::getDOM().document.ahk.input(21,1)	;	y	z
+SC016::getDOM().document.ahk.input(22,1)	;	u	u
+SC017::getDOM().document.ahk.input(23,1)	;	i	i
+SC018::getDOM().document.ahk.input(24,1)	;	o	o
+SC019::getDOM().document.ahk.input(25,1)	;	p	p
+SC01A::getDOM().document.ahk.input(26,1)	;	[	è
+SC01B::getDOM().document.ahk.input(27,1)	;	]	¨
+SC01E::getDOM().document.ahk.input(30,1)	;	a	a
+SC01F::getDOM().document.ahk.input(31,1)	;	s	s
+SC020::getDOM().document.ahk.input(32,1)	;	d	d
+SC021::getDOM().document.ahk.input(33,1)	;	f	f
+SC022::getDOM().document.ahk.input(34,1)	;	g	g
+SC023::getDOM().document.ahk.input(35,1)	;	h	h
+SC024::getDOM().document.ahk.input(36,1)	;	j	j
+SC025::getDOM().document.ahk.input(37,1)	;	k	k
+SC026::getDOM().document.ahk.input(38,1)	;	l	l
+SC027::getDOM().document.ahk.input(39,1)	;	;	é
+SC028::getDOM().document.ahk.input(40,1)	;	'	à
+SC02B::getDOM().document.ahk.input(43,1)	;	\	$
+SC056::getDOM().document.ahk.input(86,1)	;	\	<
+SC02C::getDOM().document.ahk.input(44,1)	;	z	y
+SC02D::getDOM().document.ahk.input(45,1)	;	x	x
+SC02E::getDOM().document.ahk.input(46,1)	;	c	c
+SC02F::getDOM().document.ahk.input(47,1)	;	v	v
+SC030::getDOM().document.ahk.input(48,1)	;	b	b
+SC031::getDOM().document.ahk.input(49,1)	;	n	n
+SC032::getDOM().document.ahk.input(50,1)	;	m	m
+SC033::getDOM().document.ahk.input(51,1)	;	,	,
+SC034::getDOM().document.ahk.input(52,1)	;	.	.
+SC035::getDOM().document.ahk.input(53,1)	;	/	-
#If

#SingleInstance on
;#NoTrayIcon
SendMode Input

Menu, Tray, Icon, assets/keyboard.ico, 1, 1
Menu, Tray, Tip, Emoji Keyboard
Menu, Tray, Add
Menu, Tray, Add, &Show, Toggle
Menu, Tray, Add
Menu, Tray, Add, Emoji &Keyboard by Gilles Waeber, Credits
Menu, Tray, Default, &Show

#Include assets\JSON_ToObj.ahk
#Include assets\Webapp.ahk
__Webapp_AppStart:
;<< Header End >>

;             not focusable
Gui __Webapp_:+E0x08000000 +AlwaysOnTop -MaximizeBox -MinimizeBox ; +E0x40000 +ToolWindow ;  -Caption
OnMessage(0x112, "WM_SYSCOMMAND")
WinSet, Transparent, 230

WM_SYSCOMMAND(wParam)
{
	global vVisible
    if (wParam = 0xF060 and vVisible) ; SC_CLOSE hide instead of closing
    {
        Hide()
        return 0
    }
}

;Variable containing the current state
vVisible := false

;Get our HTML DOM object
iWebCtrl := getDOM()

;Change App name on run-time
setAppName("Emoji Keyboard")

; Our custom protocol's url event handler
app_call(args) {

	;MsgBox %args%
	param := SubStr(args, 6)
	if SubStr(args, 1, 5) = "send/"
		Send(param)
}

; function to run when page is loaded
app_page(NewURL) {
}

Gui __Webapp_:Hide

~LAlt::	; <-- OPEN with double left alt key
	global vVisible
	if (A_PriorHotkey <> "~LAlt" or A_TimeSincePriorHotkey > 400) {
		if(vVisible){
			vVisible := false
			Hide()
			KeyWait, LAlt
			Send, {LAlt}
		}
		return
	}
	KeyWait, LAlt
	Show()
Return

; Functions to be called from the html/js source
Exit() {
	ExitApp
}

clipSaved =
bClipSaved := False

Credits(){
	Run, http://www.gilleswaeber.ch
}
Reload() {
	Reload
}
Run(t) {
	Run, %t%
}
Send(t) {
	global clipSaved, bClipSaved
	if(not bClipSaved){
		clipSaved := ClipboardAll
		bClipSaved := True
	}
	Clipboard := t
	Sleep, 10
	Send, ^v
	SetTimer, RestoreClipboard, 200
}
RestoreClipboard() {
	global clipSaved, bClipSaved
	SetTimer, RestoreClipboard, Off
	Clipboard := clipSaved
	clipSaved =
	bClipSaved := False
}
Show(){
	global vVisible
	vVisible := true
	Gui __Webapp_:Show
	Sleep, 10
	Send, !{Esc}
}
Hide(){
	global vVisible
	vVisible := false
	Gui __Webapp_:Hide
}
Toggle(){
	global vVisible
	if(vVisible){
		Hide()
	}
	else{
		Show()
	}
}
Ready(){
	global j
	getDOM().document.ahk.setKeymap(j.keymap)
}

#If vVisible
; Corresponding keys                    	;	US	CH
SC001::getDOM().document.ahk.input(1)   	;	ESC	ESC
SC03B::getDOM().document.ahk.input(59)   	;	F1	F1
SC03C::getDOM().document.ahk.input(60)   	;	F2	F2
SC03D::getDOM().document.ahk.input(61)   	;	F3	F3
SC03E::getDOM().document.ahk.input(62)   	;	F4	F4
SC03F::getDOM().document.ahk.input(63)   	;	F5	F5
SC040::getDOM().document.ahk.input(64)   	;	F6	F6
SC041::getDOM().document.ahk.input(65)   	;	F7	F7
SC042::getDOM().document.ahk.input(66)   	;	F8	F8
SC043::getDOM().document.ahk.input(67)   	;	F9	F9
SC044::getDOM().document.ahk.input(68)   	;	F10	F10
SC057::getDOM().document.ahk.input(87)   	;	F11	F11
SC058::getDOM().document.ahk.input(88)   	;	F12	F12
SC029::getDOM().document.ahk.input(41)   	;	`	§
SC002::getDOM().document.ahk.input(2)    	;	1	1
SC003::getDOM().document.ahk.input(3)   	;	2	2
SC004::getDOM().document.ahk.input(4)   	;	3	3
SC005::getDOM().document.ahk.input(5)   	;	4	4
SC006::getDOM().document.ahk.input(6)   	;	5	5
SC007::getDOM().document.ahk.input(7)   	;	6	6
SC008::getDOM().document.ahk.input(8)   	;	7	7
SC009::getDOM().document.ahk.input(9)   	;	8	8
SC00A::getDOM().document.ahk.input(10)   	;	9	9
SC00B::getDOM().document.ahk.input(11)   	;	0	0
SC00C::getDOM().document.ahk.input(12)   	;	-	'
SC00D::getDOM().document.ahk.input(13)   	;	=	^
SC010::getDOM().document.ahk.input(16)   	;	q	q
SC011::getDOM().document.ahk.input(17)   	;	w	w
SC012::getDOM().document.ahk.input(18)   	;	e	e
SC013::getDOM().document.ahk.input(19)   	;	r	r
SC014::getDOM().document.ahk.input(20)   	;	t	t
SC015::getDOM().document.ahk.input(21)   	;	y	z
SC016::getDOM().document.ahk.input(22)   	;	u	u
SC017::getDOM().document.ahk.input(23)   	;	i	i
SC018::getDOM().document.ahk.input(24)   	;	o	o
SC019::getDOM().document.ahk.input(25)   	;	p	p
SC01A::getDOM().document.ahk.input(26)   	;	[	è
SC01B::getDOM().document.ahk.input(27)   	;	]	¨
SC01E::getDOM().document.ahk.input(30)   	;	a	a
SC01F::getDOM().document.ahk.input(31)   	;	s	s
SC020::getDOM().document.ahk.input(32)   	;	d	d
SC021::getDOM().document.ahk.input(33)   	;	f	f
SC022::getDOM().document.ahk.input(34)   	;	g	g
SC023::getDOM().document.ahk.input(35)   	;	h	h
SC024::getDOM().document.ahk.input(36)   	;	j	j
SC025::getDOM().document.ahk.input(37)   	;	k	k
SC026::getDOM().document.ahk.input(38)   	;	l	l
SC027::getDOM().document.ahk.input(39)   	;	;	é
SC028::getDOM().document.ahk.input(40)   	;	'	à
SC02B::getDOM().document.ahk.input(43)   	;	\	$
SC056::getDOM().document.ahk.input(86)   	;	\	<
SC02C::getDOM().document.ahk.input(44)   	;	z	y
SC02D::getDOM().document.ahk.input(45)   	;	x	x
SC02E::getDOM().document.ahk.input(46)   	;	c	c
SC02F::getDOM().document.ahk.input(47)   	;	v	v
SC030::getDOM().document.ahk.input(48)   	;	b	b
SC031::getDOM().document.ahk.input(49)   	;	n	n
SC032::getDOM().document.ahk.input(50)   	;	m	m
SC033::getDOM().document.ahk.input(51)   	;	,	,
SC034::getDOM().document.ahk.input(52)   	;	.	.
SC035::getDOM().document.ahk.input(53)   	;	/	-
+SC029::getDOM().document.ahk.input(41)   	;	`	§
+SC002::getDOM().document.ahk.input(2,1)	;	1	1
+SC003::getDOM().document.ahk.input(3,1)	;	2	2
+SC004::getDOM().document.ahk.input(4,1)	;	3	3
+SC005::getDOM().document.ahk.input(5,1)	;	4	4
+SC006::getDOM().document.ahk.input(6,1)	;	5	5
+SC007::getDOM().document.ahk.input(7,1)	;	6	6
+SC008::getDOM().document.ahk.input(8,1)	;	7	7
+SC009::getDOM().document.ahk.input(9,1)	;	8	8
+SC00A::getDOM().document.ahk.input(10,1)	;	9	9
+SC00B::getDOM().document.ahk.input(11,1)	;	0	0
+SC00C::getDOM().document.ahk.input(12,1)	;	-	'
+SC00D::getDOM().document.ahk.input(13,1)	;	=	^
+SC010::getDOM().document.ahk.input(16,1)	;	q	q
+SC011::getDOM().document.ahk.input(17,1)	;	w	w
+SC012::getDOM().document.ahk.input(18,1)	;	e	e
+SC013::getDOM().document.ahk.input(19,1)	;	r	r
+SC014::getDOM().document.ahk.input(20,1)	;	t	t
+SC015::getDOM().document.ahk.input(21,1)	;	y	z
+SC016::getDOM().document.ahk.input(22,1)	;	u	u
+SC017::getDOM().document.ahk.input(23,1)	;	i	i
+SC018::getDOM().document.ahk.input(24,1)	;	o	o
+SC019::getDOM().document.ahk.input(25,1)	;	p	p
+SC01A::getDOM().document.ahk.input(26,1)	;	[	è
+SC01B::getDOM().document.ahk.input(27,1)	;	]	¨
+SC01E::getDOM().document.ahk.input(30,1)	;	a	a
+SC01F::getDOM().document.ahk.input(31,1)	;	s	s
+SC020::getDOM().document.ahk.input(32,1)	;	d	d
+SC021::getDOM().document.ahk.input(33,1)	;	f	f
+SC022::getDOM().document.ahk.input(34,1)	;	g	g
+SC023::getDOM().document.ahk.input(35,1)	;	h	h
+SC024::getDOM().document.ahk.input(36,1)	;	j	j
+SC025::getDOM().document.ahk.input(37,1)	;	k	k
+SC026::getDOM().document.ahk.input(38,1)	;	l	l
+SC027::getDOM().document.ahk.input(39,1)	;	;	é
+SC028::getDOM().document.ahk.input(40,1)	;	'	à
+SC02B::getDOM().document.ahk.input(43,1)	;	\	$
+SC056::getDOM().document.ahk.input(86,1)	;	\	<
+SC02C::getDOM().document.ahk.input(44,1)	;	z	y
+SC02D::getDOM().document.ahk.input(45,1)	;	x	x
+SC02E::getDOM().document.ahk.input(46,1)	;	c	c
+SC02F::getDOM().document.ahk.input(47,1)	;	v	v
+SC030::getDOM().document.ahk.input(48,1)	;	b	b
+SC031::getDOM().document.ahk.input(49,1)	;	n	n
+SC032::getDOM().document.ahk.input(50,1)	;	m	m
+SC033::getDOM().document.ahk.input(51,1)	;	,	,
+SC034::getDOM().document.ahk.input(52,1)	;	.	.
+SC035::getDOM().document.ahk.input(53,1)	;	/	-
#If


RunZ: add ExitIfInactivate config

RunZ: add ExitIfInactivate config

#NoEnv
#SingleInstance, Force
#NoTrayIcon

FileEncoding, utf-8
SendMode Input

; 自动生成的命令文件
global g_SearchFileList := A_ScriptDir . "\SearchFileList.txt"
; 配置文件
global g_ConfFile := A_ScriptDir . "\RunZ.ini"

if !FileExist(g_ConfFile)
{
    FileCopy, %g_ConfFile%.help.txt, %g_ConfFile%
}

global g_Conf := class_EasyINI(g_ConfFile)

; 所有命令
global g_Commands
; 当搜索无结果时使用的命令
global g_FallbackCommands
; 当前是否使用着 g_FallbackCommands
global g_UseFallbackCommands
; 编辑框当前内容
global g_CurrentInput
; 当前匹配到的第一条命令
global g_CurrentCommand
; 当前匹配到的所有命令
global g_CurrentCommandList
; 是否启用 TCMatch
global g_EnableTCMatch = TCMatchOn(g_Conf.Config.TCMatchPath)
; 列表第一列的首字母或数字
global g_FirstChar := Asc(g_Conf.Gui.FirstChar)
; 在列表中显示的行数
global g_DisplayRows := g_Conf.Gui.DisplayRows
; 在列表中显示的文字列数（多出的会被截断）
global g_DisplayCols := g_Conf.Gui.DisplayCols
; 命令使用了显示框
global g_UseDisplay
; 当前输入命令的参数，数组，为了方便没有添加 g_ 前缀
global Arg

if (FileExist(g_SearchFileList))
{
    LoadFiles()
}
else
{
    GoSub, ReloadFiles
}

Gui, Main:Font, % "s" g_Conf.Gui.FontSize, % g_Conf.Gui.FontName
Gui, Main:Add, Edit, % "gProcessInputCommand vSearchArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
Gui, Main:Add, Edit, % "ReadOnly vDisplayArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.DisplayAreaHeight
        , % SearchCommand("", true)
if (g_Conf.Gui.ShowCurrentCommand)
{
    Gui, Main:Add, Edit, % "ReadOnly"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
}
Gui, Main:Show, , RunZ
if (g_Conf.Gui.HideTitle)
{
    WinSet, Style, -0xC00000, A
}

if (g_Conf.Config.ExitIfInactivate)
{
    OnMessage(0x06, "WM_ACTIVATE")
}

Hotkey, IfWinActive, RunZ
Hotkey, ~enter, RunCurrentCommand
Hotkey, ^j, ClearInput
Hotkey, f1, Help
Hotkey, f2, EditConfig
Hotkey, esc, ExitRunZ
Hotkey, ^d, OpenCurrentFileDir
Hotkey, ^x, DeleteCurrentFile
Hotkey, ^s, ShowCurrentFile
Hotkey, ^r, ReloadFiles

if (g_Conf.Config.RunInBackground)
{
    Hotkey, esc, WindowMin
}

Loop, % g_DisplayRows
{
    key := Chr(g_FirstChar + A_Index - 1)
    ; lalt +
    Hotkey, <!%key%, RunSelectedCommand1
    ; tab +
    Hotkey, ~%key%, RunSelectedCommand2
    ; shift +
    Hotkey, ~+%key%, AddCustomCommand
}

if (g_Conf.Config.SaveInputText && g_Conf.Auto.InputText != "")
{
    Send, % g_Conf.Auto.InputText
}

return

ExitRunZ:
    if (g_Conf.Config.SaveInputText)
    {
        g_Conf.DeleteKey("auto", "InputText")
        g_Conf.AddKey("auto", "InputText", g_CurrentInput)
        g_Conf.Save()
    }

    ExitApp
return

WindowMin:
    WinMinimize, A
return

GenerateSearchFileList()
{
    FileDelete, %g_SearchFileList%

    searchFileType := g_Conf.Config.SearchFileType

    for dirIndex, dir in StrSplit(g_Conf.Config.SearchFileDir, " | ")
    {
        if (InStr(dir, "A_") == 1)
        {
            searchPath := %dir%
        }
        else
        {
            searchPath := dir
        }

        for extIndex, ext in StrSplit(searchFileType, " | ")
        {
            Loop, Files, %searchPath%\%ext%, R
            {
                if (g_Conf.Config.SearchFileExclude != ""
                        && RegexMatch(A_LoopFileLongPath, g_Conf.Config.SearchFileExclude))
                {
                    continue
                }
                FileAppend, file | %A_LoopFileLongPath%`n, %g_SearchFileList%,
            }
        }
    }
}

ReloadFiles:
    GenerateSearchFileList()

    LoadFiles()
return

ProcessInputCommand:
    GuiControlGet, g_CurrentInput, , SearchArea
    SearchCommand(g_CurrentInput)
return

SearchCommand(command = "", firstRun = false)
{
    result := ""
    commandPrefix := SubStr(command, 1, 1)

    if (commandPrefix == ";" || commandPrefix == ":")
    {
        if (commandPrefix == ";")
        {
            g_CurrentCommand := g_FallbackCommands[1]
        }
        else if (commandPrefix == ":")
        {
            g_CurrentCommand := g_FallbackCommands[2]
        }

        g_CurrentCommandList.Insert(g_CurrentCommand)
        result .= "a | " . g_CurrentCommand
        Arg := SubStr(g_CurrentInput, 2)
        DisplaySearchResult(result)
        return result
    }
    ; 用空格来判断参数
    else if (InStr(command, " ") && g_CurrentCommand != "")
    {
        if (g_UseFallbackCommands)
        {
            Arg := command
        }
        else
        {
            Arg := SubStr(command, InStr(command, " ") + 1)
        }
        return
    }

    g_CurrentCommandList := Object()

    order := g_FirstChar

    for index, element in g_Commands
    {
        splitedElement := StrSplit(element, " | ")

        if (splitedElement[1] == "file")
        {
            SplitPath, % splitedElement[2], , fileDir, , fileNameNoExt

            ; 只搜索和展示不带扩展名的文件名
            elementToSearch := fileNameNoExt
            elementToShow := "file | " . fileNameNoExt

            if (splitedElement.Length() >= 3)
            {
                elementToSearch .= " " . splitedElement[3]
                elementToShow .= "（" . splitedElement[3] . "）"
            }

            elementToShow := SubStr(elementToShow, 1, g_DisplayCols)

            if (g_Conf.Config.SearchFullPath)
            {
                ; TCMatch 在搜索路径时只搜索文件名，强行将 \ 转成空格
                elementToSearch := StrReplace(fileDir, "\", " ") . " " . elementToSearch
            }
        }
        else
        {
            elementToShow := SubStr(element, 1, g_DisplayCols)
            elementToSearch := splitedElement[2]
        }

        if (MatchCommand(elementToSearch, command))
        {
            g_CurrentCommandList.Insert(element)

            if (order == g_FirstChar)
            {
                g_CurrentCommand := element
            }
            else
            {
                result .= "`n"
            }

            result .= Chr(order++) . " | " . elementToShow

            if (order - g_FirstChar >= g_DisplayRows)
            {
                break
            }
            ; 第一次运行只加载 function 类型
            if (firstRun && (order - g_FirstChar >= g_DisplayRows - 4))
            {
                result .= "`n`n现有 " g_Commands.Length() " 条命令。"
                result .= "`n`n键入内容 搜索，回车 执行第一条，Alt + 字母 执行，F1 帮助，Esc 退出。"

                break
            }
        }
    }

    if (result == "")
    {
        g_UseFallbackCommands := true
        g_CurrentCommand := g_FallbackCommands[1]
        g_CurrentCommandList := g_FallbackCommands
        Arg := g_CurrentInput

        for index, element in g_FallbackCommands
        {
            if (index != 1)
            {
                result .= "`n"
            }

            result .= Chr(g_FirstChar - 1 + index++) . " | " . element
        }
    }
    else
    {
        g_UseFallbackCommands := false
    }

    DisplaySearchResult(result)
    return result
}

DisplaySearchResult(result)
{
    DisplayText(result)

    if (g_CurrentCommandList.Length() == 1 && g_Conf.Config.RunIfOnlyOne)
    {
        GoSub, RunCurrentCommand
    }

    if (g_Conf.Gui.ShowCurrentCommand)
    {
        ControlSetText, Edit3, %g_CurrentCommand%
    }
}

ClearInput:
    ControlSetText, Edit1,
return

RunCurrentCommand:
    if (g_CurrentInput != "")
    {
        g_UseDisplay := false

        RunCommand(g_CurrentCommand)
        if (g_Conf.Config.RunOnce && !g_UseDisplay)
        {
            GoSub, ExitRunZ
        }
    }
return

MatchCommand(Haystack, Needle)
{
    if (g_EnableTCMatch)
    {
        return TCMatch(Haystack, Needle)
    }

    return InStr(Haystack, Needle)
}

RunCommand(command)
{
    command := StrSplit(command, "（")[1]

    if (RegexMatch(command, "^(file|url)"))
    {
        cmd := StrSplit(command, " | ")[2]

        if (InStr(cmd, ".lnk"))
        {
            ; 处理 32 位 ahk 运行不了某些 64 位系统 .lnk 的问题
            FileGetShortcut, %cmd%, filePath
            if (!FileExist(filePath))
            {
                filePath := StrReplace(filePath, "C:\Program Files (x86)", "C:\Program Files")
                if (FileExist(filePath))
                {
                    cmd := filePath
                }
            }
        }

        Run, %cmd%
    }
    else if (InStr(command, "function | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        if (IsLabel(cmd))
        {
            GoSub, %cmd%
        }
    }
    else if (InStr(command, "cmd | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        RunWithCmd(cmd)
    }
}

RunSelectedCommand1:
    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

RunSelectedCommand2:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 2, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

AddCustomCommand:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    if (g_CurrentCommandList[index] != "")
    {
        g_Conf.AddKey("command", g_CurrentCommandList[index], g_CurrentInput)

        g_Conf.Save()

        LoadFiles()
    }
return

LoadFiles()
{
    g_Commands := Object()
    g_FallbackCommands := Object()

    for key, value in g_Conf.Command
    {
        if (value != "")
        {
            g_Commands.Insert(key . "（" . value "）")
        }
        else
        {
            g_Commands.Insert(key)
        }
    }

    if (FileExist(A_ScriptDir "\UserFunctions.ahk"))
    {
        userFunctionLabel := "UserFunctions"
        if (IsLabel(userFunctionLabel))
        {
            GoSub, %userFunctionLabel%
        }
        else
        {
            MsgBox, 未在 %A_ScriptDir%\UserFunctions.ahk 中发现 %userFunctionLabel% 标签，请修改！
        }
    }

    GoSub, Functions

    Loop, Read, %g_SearchFileList%
    {
        g_Commands.Insert(A_LoopReadLine)
    }

    if (g_Conf.Config.LoadControlPanelFunctions)
    {
        Loop, Read, %A_ScriptDir%\ControlPanelFunctions.txt
        {
            g_Commands.Insert(A_LoopReadLine)
        }
    }
}

DisplayText(text)
{
    textToDisplay := StrReplace(text, "`n", "`r`n")
    ControlSetText, Edit2, %textToDisplay%
}

DisplayResult(result)
{
    DisplayText(result)
    g_UseDisplay := true
}

; AddAction(label, info, fallback)
@(label, info, fallback = false)
{
    if (!IsLabel(label))
    {
        MsgBox, 未找到 %label% 标签，请检查 %A_ScriptDir%\UserFunctions.ahk 文件格式！
        return
    }

    g_Commands.Insert("function | " . label . "（" . info . "）")
    if (fallback)
    {
        g_FallbackCommands.Insert("function | " . label . "（" . info . "）")
    }
}

RunAndGetOutput(command)
{
    tempFileName := "RunZ.stdout.log"
    fullCommand = bash -c "%command% &> %tempFileName%"

    if (!FileExist("c:\msys64\usr\bin\bash.exe"))
    {
        fullCommand = %ComSpec% /C "%command% > %tempFileName%"
    }

    RunWait, %fullCommand%, %A_Temp%, Hide
    FileRead, result, %A_Temp%\%tempFileName%
    FileDelete, %A_Temp%\%tempFileName%
    return result
}

RunWithCmd(command)
{
    if (FileExist("c:\msys64\usr\bin\mintty.exe"))
    {
        Run, % "mintty -e sh -c '" command "; read'"
    }
    else
    {
        Run, % ComSpec " /C " command " & pause"
    }
}

OpenPath(filePath)
{
    if (!FileExist(filePath))
    {
        return
    }

    if (FileExist(g_Conf.Config.TCPath))
    {
        TCPath := g_Conf.Config.TCPath
        Run, %TCPath% /O /A /L="%filePath%"
    }
    else
    {
        SplitPath, filePath, , fileDir, ,
        Run, explorer "%fileDir%"
    }
}

OpenCurrentFileDir:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]
    OpenPath(filePath)
return

DeleteCurrentFile:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]

    if (!FileExist(filePath))
    {
        return
    }

    FileRecycle, % filePath
    GoSub, ReloadFiles
return

ShowCurrentFile:
    clipboard := StrSplit(g_CurrentCommand, " | ")[2]
    ToolTip, % clipboard
    SetTimer, RemoveToolTip, 800
return

RemoveToolTip:
    ToolTip
    SetTimer, RemoveToolTip, Off
return

WM_ACTIVATE(wParam, lParam)
{
    if (wParam >= 1) ; 窗口激活
    {
        return
    }
    else if (wParam <= 0) ; 窗口非激活
    {
        GoSub, ExitRunZ
    }
}

#include %A_ScriptDir%\..\lib\class_EasyIni.ahk
#include %A_ScriptDir%\lib\Kanji\Kanji.ahk
#include %A_ScriptDir%\lib\TCMatch.ahk
#include %A_ScriptDir%\lib\Eval.ahk
#include %A_ScriptDir%\Functions.ahk
; 用户自定义命令
#include *i %A_ScriptDir%\UserFunctions.ahk

#NoEnv
#SingleInstance, Force
#NoTrayIcon

FileEncoding, utf-8
SendMode Input

; 自动生成的命令文件
global g_SearchFileList := A_ScriptDir . "\SearchFileList.txt"
; 配置文件
global g_ConfFile := A_ScriptDir . "\RunZ.ini"

if !FileExist(g_ConfFile)
{
    FileCopy, %g_ConfFile%.help.txt, %g_ConfFile%
}

global g_Conf := class_EasyINI(g_ConfFile)

; 所有命令
global g_Commands
; 当搜索无结果时使用的命令
global g_FallbackCommands
; 当前是否使用着 g_FallbackCommands
global g_UseFallbackCommands
; 编辑框当前内容
global g_CurrentInput
; 当前匹配到的第一条命令
global g_CurrentCommand
; 当前匹配到的所有命令
global g_CurrentCommandList
; 是否启用 TCMatch
global g_EnableTCMatch = TCMatchOn(g_Conf.Config.TCMatchPath)
; 列表第一列的首字母或数字
global g_FirstChar := Asc(g_Conf.Gui.FirstChar)
; 在列表中显示的行数
global g_DisplayRows := g_Conf.Gui.DisplayRows
; 在列表中显示的文字列数（多出的会被截断）
global g_DisplayCols := g_Conf.Gui.DisplayCols
; 命令使用了显示框
global g_UseDisplay
; 当前输入命令的参数，数组，为了方便没有添加 g_ 前缀
global Arg

if (FileExist(g_SearchFileList))
{
    LoadFiles()
}
else
{
    GoSub, ReloadFiles
}

Gui, Main:Font, % "s" g_Conf.Gui.FontSize, % g_Conf.Gui.FontName
Gui, Main:Add, Edit, % "gProcessInputCommand vSearchArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
Gui, Main:Add, Edit, % "ReadOnly vDisplayArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.DisplayAreaHeight
        , % SearchCommand("", true)
if (g_Conf.Gui.ShowCurrentCommand)
{
    Gui, Main:Add, Edit, % "ReadOnly"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
}
Gui, Main:Show, , RunZ
if (g_Conf.Gui.HideTitle)
{
    WinSet, Style, -0xC00000, A
}

Hotkey, IfWinActive, RunZ
Hotkey, ~enter, RunCurrentCommand
Hotkey, ^j, ClearInput
Hotkey, f1, Help
Hotkey, f2, EditConfig
Hotkey, esc, ExitRunZ
Hotkey, ^d, OpenCurrentFileDir
Hotkey, ^x, DeleteCurrentFile
Hotkey, ^s, ShowCurrentFile
Hotkey, ^r, ReloadFiles

if (g_Conf.Config.RunInBackground)
{
    Hotkey, esc, WindowMin
}

Loop, % g_DisplayRows
{
    key := Chr(g_FirstChar + A_Index - 1)
    ; lalt +
    Hotkey, <!%key%, RunSelectedCommand1
    ; tab +
    Hotkey, ~%key%, RunSelectedCommand2
    ; shift +
    Hotkey, ~+%key%, AddCustomCommand
}

if (g_Conf.Config.SaveInputText && g_Conf.Auto.InputText != "")
{
    Send, % g_Conf.Auto.InputText
}

return

ExitRunZ:
    if (g_Conf.Config.SaveInputText)
    {
        g_Conf.DeleteKey("auto", "InputText")
        g_Conf.AddKey("auto", "InputText", g_CurrentInput)
        g_Conf.Save()
    }

    ExitApp
return

WindowMin:
    WinMinimize, A
return

GenerateSearchFileList()
{
    FileDelete, %g_SearchFileList%

    searchFileType := g_Conf.Config.SearchFileType

    for dirIndex, dir in StrSplit(g_Conf.Config.SearchFileDir, " | ")
    {
        if (InStr(dir, "A_") == 1)
        {
            searchPath := %dir%
        }
        else
        {
            searchPath := dir
        }

        for extIndex, ext in StrSplit(searchFileType, " | ")
        {
            Loop, Files, %searchPath%\%ext%, R
            {
                if (g_Conf.Config.SearchFileExclude != ""
                        && RegexMatch(A_LoopFileLongPath, g_Conf.Config.SearchFileExclude))
                {
                    continue
                }
                FileAppend, file | %A_LoopFileLongPath%`n, %g_SearchFileList%,
            }
        }
    }
}

ReloadFiles:
    GenerateSearchFileList()

    LoadFiles()
return

ProcessInputCommand:
    GuiControlGet, g_CurrentInput, , SearchArea
    SearchCommand(g_CurrentInput)
return

SearchCommand(command = "", firstRun = false)
{
    result := ""
    commandPrefix := SubStr(command, 1, 1)

    if (commandPrefix == ";" || commandPrefix == ":")
    {
        if (commandPrefix == ";")
        {
            g_CurrentCommand := g_FallbackCommands[1]
        }
        else if (commandPrefix == ":")
        {
            g_CurrentCommand := g_FallbackCommands[2]
        }

        g_CurrentCommandList.Insert(g_CurrentCommand)
        result .= "a | " . g_CurrentCommand
        Arg := SubStr(g_CurrentInput, 2)
        DisplaySearchResult(result)
        return result
    }
    ; 用空格来判断参数
    else if (InStr(command, " ") && g_CurrentCommand != "")
    {
        if (g_UseFallbackCommands)
        {
            Arg := command
        }
        else
        {
            Arg := SubStr(command, InStr(command, " ") + 1)
        }
        return
    }

    g_CurrentCommandList := Object()

    order := g_FirstChar

    for index, element in g_Commands
    {
        splitedElement := StrSplit(element, " | ")

        if (splitedElement[1] == "file")
        {
            SplitPath, % splitedElement[2], , fileDir, , fileNameNoExt

            ; 只搜索和展示不带扩展名的文件名
            elementToSearch := fileNameNoExt
            elementToShow := "file | " . fileNameNoExt

            if (splitedElement.Length() >= 3)
            {
                elementToSearch .= " " . splitedElement[3]
                elementToShow .= "（" . splitedElement[3] . "）"
            }

            elementToShow := SubStr(elementToShow, 1, g_DisplayCols)

            if (g_Conf.Config.SearchFullPath)
            {
                ; TCMatch 在搜索路径时只搜索文件名，强行将 \ 转成空格
                elementToSearch := StrReplace(fileDir, "\", " ") . " " . elementToSearch
            }
        }
        else
        {
            elementToShow := SubStr(element, 1, g_DisplayCols)
            elementToSearch := splitedElement[2]
        }

        if (MatchCommand(elementToSearch, command))
        {
            g_CurrentCommandList.Insert(element)

            if (order == g_FirstChar)
            {
                g_CurrentCommand := element
            }
            else
            {
                result .= "`n"
            }

            result .= Chr(order++) . " | " . elementToShow

            if (order - g_FirstChar >= g_DisplayRows)
            {
                break
            }
            ; 第一次运行只加载 function 类型
            if (firstRun && (order - g_FirstChar >= g_DisplayRows - 4))
            {
                result .= "`n`n现有 " g_Commands.Length() " 条命令。"
                result .= "`n`n键入内容 搜索，回车 执行第一条，Alt + 字母 执行，F1 帮助，Esc 退出。"

                break
            }
        }
    }

    if (result == "")
    {
        g_UseFallbackCommands := true
        g_CurrentCommand := g_FallbackCommands[1]
        g_CurrentCommandList := g_FallbackCommands
        Arg := g_CurrentInput

        for index, element in g_FallbackCommands
        {
            if (index != 1)
            {
                result .= "`n"
            }

            result .= Chr(g_FirstChar - 1 + index++) . " | " . element
        }
    }
    else
    {
        g_UseFallbackCommands := false
    }

    DisplaySearchResult(result)
    return result
}

DisplaySearchResult(result)
{
    DisplayText(result)

    if (g_CurrentCommandList.Length() == 1 && g_Conf.Config.RunIfOnlyOne)
    {
        GoSub, RunCurrentCommand
    }

    if (g_Conf.Gui.ShowCurrentCommand)
    {
        ControlSetText, Edit3, %g_CurrentCommand%
    }
}

ClearInput:
    ControlSetText, Edit1,
return

RunCurrentCommand:
    if (g_CurrentInput != "")
    {
        g_UseDisplay := false

        RunCommand(g_CurrentCommand)
        if (g_Conf.Config.RunOnce && !g_UseDisplay)
        {
            GoSub, ExitRunZ
        }
    }
return

MatchCommand(Haystack, Needle)
{
    if (g_EnableTCMatch)
    {
        return TCMatch(Haystack, Needle)
    }

    return InStr(Haystack, Needle)
}

RunCommand(command)
{
    command := StrSplit(command, "（")[1]

    if (RegexMatch(command, "^(file|url)"))
    {
        cmd := StrSplit(command, " | ")[2]

        if (InStr(cmd, ".lnk"))
        {
            ; 处理 32 位 ahk 运行不了某些 64 位系统 .lnk 的问题
            FileGetShortcut, %cmd%, filePath
            if (!FileExist(filePath))
            {
                filePath := StrReplace(filePath, "C:\Program Files (x86)", "C:\Program Files")
                if (FileExist(filePath))
                {
                    cmd := filePath
                }
            }
        }

        Run, %cmd%
    }
    else if (InStr(command, "function | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        if (IsLabel(cmd))
        {
            GoSub, %cmd%
        }
    }
    else if (InStr(command, "cmd | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        RunWithCmd(cmd)
    }
}

RunSelectedCommand1:
    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

RunSelectedCommand2:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 2, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

AddCustomCommand:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    if (g_CurrentCommandList[index] != "")
    {
        g_Conf.AddKey("command", g_CurrentCommandList[index], g_CurrentInput)

        g_Conf.Save()

        LoadFiles()
    }
return

LoadFiles()
{
    g_Commands := Object()
    g_FallbackCommands := Object()

    for key, value in g_Conf.Command
    {
        if (value != "")
        {
            g_Commands.Insert(key . "（" . value "）")
        }
        else
        {
            g_Commands.Insert(key)
        }
    }

    if (FileExist(A_ScriptDir "\UserFunctions.ahk"))
    {
        userFunctionLabel := "UserFunctions"
        if (IsLabel(userFunctionLabel))
        {
            GoSub, %userFunctionLabel%
        }
        else
        {
            MsgBox, 未在 %A_ScriptDir%\UserFunctions.ahk 中发现 %userFunctionLabel% 标签，请修改！
        }
    }

    GoSub, Functions

    Loop, Read, %g_SearchFileList%
    {
        g_Commands.Insert(A_LoopReadLine)
    }

    if (g_Conf.Config.LoadControlPanelFunctions)
    {
        Loop, Read, %A_ScriptDir%\ControlPanelFunctions.txt
        {
            g_Commands.Insert(A_LoopReadLine)
        }
    }
}

DisplayText(text)
{
    textToDisplay := StrReplace(text, "`n", "`r`n")
    ControlSetText, Edit2, %textToDisplay%
}

DisplayResult(result)
{
    DisplayText(result)
    g_UseDisplay := true
}

; AddAction(label, info, fallback)
@(label, info, fallback = false)
{
    if (!IsLabel(label))
    {
        MsgBox, 未找到 %label% 标签，请检查 %A_ScriptDir%\UserFunctions.ahk 文件格式！
        return
    }

    g_Commands.Insert("function | " . label . "（" . info . "）")
    if (fallback)
    {
        g_FallbackCommands.Insert("function | " . label . "（" . info . "）")
    }
}

RunAndGetOutput(command)
{
    tempFileName := "RunZ.stdout.log"
    fullCommand = bash -c "%command% &> %tempFileName%"

    if (!FileExist("c:\msys64\usr\bin\bash.exe"))
    {
        fullCommand = %ComSpec% /C "%command% > %tempFileName%"
    }

    RunWait, %fullCommand%, %A_Temp%, Hide
    FileRead, result, %A_Temp%\%tempFileName%
    FileDelete, %A_Temp%\%tempFileName%
    return result
}

RunWithCmd(command)
{
    if (FileExist("c:\msys64\usr\bin\mintty.exe"))
    {
        Run, % "mintty -e sh -c '" command "; read'"
    }
    else
    {
        Run, % ComSpec " /C " command " & pause"
    }
}

OpenPath(filePath)
{
    if (!FileExist(filePath))
    {
        return
    }

    if (FileExist(g_Conf.Config.TCPath))
    {
        TCPath := g_Conf.Config.TCPath
        Run, %TCPath% /O /A /L="%filePath%"
    }
    else
    {
        SplitPath, filePath, , fileDir, ,
        Run, explorer "%fileDir%"
    }
}

OpenCurrentFileDir:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]
    OpenPath(filePath)
return

DeleteCurrentFile:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]

    if (!FileExist(filePath))
    {
        return
    }

    FileRecycle, % filePath
    GoSub, ReloadFiles
return

ShowCurrentFile:
    clipboard := StrSplit(g_CurrentCommand, " | ")[2]
    ToolTip, % clipboard
    SetTimer, RemoveToolTip, 800
return

RemoveToolTip:
    ToolTip
    SetTimer, RemoveToolTip, Off
return

#include %A_ScriptDir%\..\lib\class_EasyIni.ahk
#include %A_ScriptDir%\lib\Kanji\Kanji.ahk
#include %A_ScriptDir%\lib\TCMatch.ahk
#include %A_ScriptDir%\lib\Eval.ahk
#include %A_ScriptDir%\Functions.ahk
; 用户自定义命令
#include *i %A_ScriptDir%\UserFunctions.ahk


[feature] Shift + t

[feature] Shift + t

; Autohotkey configuration file
; AHK Version v.1.1.32.00
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 22 Mar. 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#SingleInstance Force
#Persistent

GLOBAL_DEBUG_MODE := 0
Return

CapsLock::Ctrl
LCtrl::Return
;LCtrl::CapsLock

; DEBUG TOOLS -----------------------------------------------------------------

#c::
  If(GLOBAL_DEBUG_MODE > 0) {
    ; WinGetTitle, title, A
    WinGetClass, title, A
    MsgBox %title%
  }
Return

f12::
  If(GLOBAL_DEBUG_MODE > 0) {
    Reload
  }
Return

; SYSTEM ----------------------------------------------------------------------

; Access different windows of the same group
!`::
  WinGet, process_name, ProcessName, A ; get the active window's process name
  process_windows := GetWindowsOfProcess(process_name)

  n_process_windows := process_windows.Length()

  index := 1 ; AHK arrays are 1 indexed
  While(GetKeyState("Alt", "P")) {
    If (GetKeyState("``", "P")) {
      If (index < n_process_windows) {
        index := index + 1
      } Else {
        index := 1
      }
      active_id := process_windows[index]
      WinActivate, ahk_id %active_id%
    }
  }

  index := ""
Return

; Get the window ids of all the processes under that process name
GetWindowsOfProcess(process_name) {
  ids := Array()
  WinGet, window_ids, List ; get the IDs for all running windows
  Loop %window_ids% {
    id := window_ids%A_Index%
    WinGetTitle, title, ahk_id %id%
    WinGet, a_process_name, ProcessName, ahk_id %id%
    ; only include windows with visible title
    If (title && a_process_name = process_name) {
      ids.Push(id)
    }
  }
  Return, ids
}

; TIMEKEEPER ------------------------------------------------------------------

; Shift focus to the timekeeper app
#!e::
  timekeeper_app := WinExist("ahk_class WindowsForms10.Window.8.app.0.262fb3d")
  If(timekeeper_app > 0) {
    WinActivate, ahk_id %timekeeper_app%
  } Else {
    Run, DTE.exe, C:\Program Files (x86)\DTEAxiom
  }
Return

; Start the timer on the selected item in the daily view
#IfWinActive ahk_class WindowsForms10.Window.8.app.0.262fb3d
  >+s::
    WinGetActiveTitle, active_title
    match_result := RegExMatch(active_title, "^Entries for")
    ; each item in the dropdown is approximately 25 pixels
    ; so item 4 (Start Timer) is 100 pixels down from the context menu
    drop_down := 100
    If(match_result > 0) {
      WinMove, 100, 100
      MouseMove, 100, 280
      Send {RButton}
      Sleep, 10 ; need to sleep to allow submenu time to come up
      MouseMove, 170, 300 + drop_down
      Send {LButton}
    }
Return

; MSOFFICE --------------------------------------------------------------------

; Let the print screen key open the application options key (for spell check)
; Word and Outlook
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class rctrl_renwnd32")
  PrintScreen::AppsKey
Return

; This ridiculous keymapping is care of Lenovo
; which maps F12 to some bloatware keyboard manager utility
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class XLMAIN")
  F12::
    Send {F12}
Return

; WORD ONLY -------------------------------------------------------------------

; Cycle through types of markup
#If WinActive("ahk_class OpusApp")
  >+m::
    Send !r
    Sleep, 10
    Send td
    Send {Down}
    Send {Enter}
Return

#If WinActive("ahk_class OpusApp")
  >+t::
    Send !h
    Send pg
    Send !t
Return


Add some comments

Add some comments

TotalCommander_Dialog:
; 本插件尝试将TotalCommander作为文件打开、保存对话框
; * 默认添加快捷键<lwin>o
;   在文件对话框或任意文字编辑界面按下快捷键跳转至TC
;   TC中选定文件后再次按下快捷键可实现文件打开功能
; * 尝试在打开文件对话框时，自动跳转到TC进行文件选择：
;   #32770，焦点Edit1且内无文字, 对话框内不含密码、password等内容
; * 快捷键：
;   lwin + o：在文件对话框或任意文字编辑界面按下快捷键跳转至TC
;   esc：离开TC，回到调用者
;   ctrl + 回车：将选择结果返回调用者
;   shift + 回车：将当前目录返回调用者（一般用于保存文件）
;   回车：和ctrl + 回车类似，但当仅选择一个目录时，进入目录而不返回调用者
; * 已知问题：
;   当返回的路径名过长（一般发生在多选时），返回的字符串会被截断为254字节
;   因为临时修改的esc、ctrl + 回车、shift + 回车，返回时会重置
;       如果用户重新映射了这些快捷键，会被还原回去，去掉select模式的原因，
;       是因为切换会normal模式后这些快捷键继续有效，怀疑是bug，未查明

vim.comment("<OpenTCDialog>", "激活TC选择文件, 需再次按下快捷键触发对话框打开事件")

;初始化设置：全局快捷键跳转到TC
IniWriteIfNullValue(ConfigPath, "Global", "*<lwin>o", "<OpenTCDialog>")

;初始化设置：自动跳转到TC作为文件选择对话框
IniWriteIfNull(ConfigPath, "TotalCommander_Config", "AsOpenFileDialog", "0")

;初始化设置：还有下面文字的窗口将排除TC作为文件选择对话框
;由于不支持中文，无法初始化"密码"，在后面代码中添加
IniWriteIfNull(ConfigPath, "TotalCommander_Config", "OpenFileDialogExclude", "password, pwd")

;读取配置参数，禁用时直接跳过
IniRead, AsOpenFileDialog, %ConfigPath%, TotalCommander_Config, AsOpenFileDialog, 1
if AsOpenFileDialog <> 1
    return

;读取排除窗体文字
;IniRead, OpenFileDialogExclude, %ConfigPath%, TotalCommander_Config, OpenFileDialogExclude, "密码, password"
Loop, read, %ConfigPath%
{
    ifInString, A_LoopReadLine, OpenFileDialogExclude
    {
        OpenFileDialogExclude := SubStr(A_LoopReadLine, InStr(A_LoopReadLine, "=")+1)
        IfNotInString, OpenFileDialogExclude, 密码
            OpenFileDialogExclude .= ", 密码"
        break
    }
}

;未发现TC路径时自动禁用该功能
if StrLen(TCPath) = 0
    return

;用于记录文件打开对话框所属窗体
global CallerId := 0

;等待OpenFileDialog出现
SetTimer, <CheckFileDialog>, 1000

return

<TCDialog_MapKeys>:
    vim.mode("normal", "TTOTAL_CMD")
    vim.map("<enter>", "<TC_PreSelected>", "TTOTAL_CMD")
    vim.map("<ctrl><enter>", "<TC_Selected>", "TTOTAL_CMD")
    vim.map("<shift><enter>", "<TC_SelectedCurrentDir>", "TTOTAL_CMD")
    vim.map("<esc>", "<Return_To_Caller>", "TTOTAL_CMD")
return

<TCDialog_UnMapKeys>:
    vim.mode("normal", "TTOTAL_CMD")
    vim.map("<enter>", "<>", "TTOTAL_CMD")
    vim.map("<ctrl><enter>", "<>", "TTOTAL_CMD")
    vim.map("<shift><enter>", "<>", "TTOTAL_CMD")
    vim.map("<esc>", "<>", "TTOTAL_CMD")
return

;返回调用者
<Return_To_Caller>:
    gosub, <TCDialog_UnMapKeys>

    ;未发现可激活的调用窗体时，最小化TC
    if CallerId = 0
    {
        Winminimize, AHK_CLASS TTOTAL_CMD
        sleep, 500
        CallerId := WinExist("A")
        if CallerId = 0
            return
    }

    WinActivate, ahk_id %CallerId%
return

;发现标准打开文件对话框，未记录，焦点控件为Edit1=>记录，并激活TC
<CheckFileDialog>:
    WinGetClass, class, A
    if class <> #32770
        return

    ControlGetFocus, ct, ahk_class #32770
    if ct <> Edit1
        return

    ;以此排除“另存为”，或其它已经包含文字的对话框
    ControlGetText, str, Edit1, ahk_class #32770
    if StrLen(str) > 0
        return

    ;排除用户自定义窗体
    WinGetText, str, ahk_class #32770
    WinGetTitle, title, ahk_class #32770
    if StrLen(title)=0
        return
    str .= title
    Loop, parse, OpenFileDialogExclude, `, , %A_Space%%A_Tab%
    {
        If StrLen(A_LoopField) = 0
            continue
        IfInString, str, %A_LoopField%
            return
    }

    id := WinExist("A")
    if id = 0
        return
    if id = %CallerId%
        return

    CallerId := id
    gosub, <FocusTC>
    gosub, <TCDialog_MapKeys>
return

; * 非TC窗口按下后激活TC窗口
; * TC窗口按下后复制当前选中文件返回原窗口后粘贴
<OpenTCDialog>:
    ; 复制保存文件对话框中的文件名到剪切板
    send, ^c
    WinGetClass, class, A

    ;在Total Commander按下快捷键时，激活调用窗体并执行粘贴操作
    if class = TTOTAL_CMD
    {
        gosub, <TC_Selected>
        return
    }

    if class <> TTOTAL_CMD
    {
        CallerId := WinExist("A")
        if CallerId = 0
            return

        gosub, <FocusTC>
        gosub, <TCDialog_MapKeys>
        return
    }

return

<TC_PreSelected>:
    ; cm_CopyNetNamesToClip
    SendPos(2021)
    sleep, 100 ; 此处用clipwait貌似会出错？

    ;未多选
    IfNotInString, clipboard, `n
    {
        ;当前复制项为文件夹时
        StringRight, str, clipboard, 1
        IfInString, str, \
            {
                ; cm_GoToDir
                SendPos(2003)
                return
            }
    }

    ;return 注意，此处无需return

<TC_Selected>:
    gosub, <TCDialog_UnMapKeys>

    SendPos(2021)
    sleep, 100

    ;仅在多选时两侧增加双引号
    IfInString, clipboard, `n
    {
        files := ""
        Loop, parse, clipboard, `n, `r
            files .= """" A_LoopField  """ "
        clipboard := files
    }

    ;未发现可激活的调用窗体时，最小化TC
    if CallerId = 0
    {
        Winminimize, AHK_CLASS TTOTAL_CMD
        sleep, 500
        CallerId := WinExist("A")
        if CallerId = 0
            return
    }

    WinActivate, ahk_id %CallerId%
    WinWait, ahk_id %CallerId%
    send, ^v
    send, {Enter}
return

<TC_SelectedCurrentDir>:
    gosub, <TCDialog_UnMapKeys>

    filename := "\" . clipboard
    ; cm_CopySrcPathToClip
    SendPos(2029)
    sleep, 100

    clipboard := clipboard . filename

    ;未发现可激活的调用窗体时，最小化TC
    if CallerId = 0
    {
        Winminimize, AHK_CLASS TTOTAL_CMD
        sleep, 500
        CallerId := WinExist("A")
        if CallerId = 0
            return
    }

    WinActivate, ahk_id %CallerId%
    WinWait, ahk_id %CallerId%
    send, ^v
    send, {Enter}{Enter}
return

TotalCommander_Dialog:
; 本插件尝试将TotalCommander作为文件打开对话框
; * 默认添加快捷键<lwin>o , 在文件对话框或任意文字编辑界面按下快捷键跳转至TC
;   TC中选定文件后再次按下快捷键可实现文件打开功能
; * 尝试在打开文件对话框时，自动跳转到TC进行文件选择：
;   #32770，焦点Edit1且内无文字, 对话框内不含密码、password等内容
; * 按下回车或Ctrl+回车均可直接选定文件
;   未多选情况下在文件夹上按下回车时，进入该文件夹而非选定

vim.comment("<OpenTCDialog>", "激活TC选择文件, 需再次按下快捷键触发对话框打开事件")

;初始化设置：全局快捷键跳转到TC
IniWriteIfNullValue(ConfigPath, "Global", "*<lwin>o", "<OpenTCDialog>")

;初始化设置：自动跳转到TC作为文件选择对话框
IniWriteIfNull(ConfigPath, "TotalCommander_Config", "AsOpenFileDialog", "0")

;初始化设置：还有下面文字的窗口将排除TC作为文件选择对话框
;由于不支持中文，无法初始化"密码"，在后面代码中添加
IniWriteIfNull(ConfigPath, "TotalCommander_Config", "OpenFileDialogExclude", "password, pwd")

;读取配置参数，禁用时直接跳过
IniRead, AsOpenFileDialog, %ConfigPath%, TotalCommander_Config, AsOpenFileDialog, 1
if AsOpenFileDialog <> 1
    return

;读取排除窗体文字
;IniRead, OpenFileDialogExclude, %ConfigPath%, TotalCommander_Config, OpenFileDialogExclude, "密码, password"
Loop, read, %ConfigPath%
{
    ifInString, A_LoopReadLine, OpenFileDialogExclude
    {
        OpenFileDialogExclude := SubStr(A_LoopReadLine, InStr(A_LoopReadLine, "=")+1)
        IfNotInString, OpenFileDialogExclude, 密码
            OpenFileDialogExclude .= ", 密码"
        break
    }
}

;未发现TC路径时自动禁用该功能
if StrLen(TCPath) = 0
    return

;用于记录文件打开对话框所属窗体
global CallerId := 0

;等待OpenFileDialog出现
SetTimer, <CheckFileDialog>, 1000

return

<TCDialog_MapKeys>:
    vim.mode("normal", "TTOTAL_CMD")
    vim.map("<enter>", "<TC_PreSelected>", "TTOTAL_CMD")
    vim.map("<ctrl><enter>", "<TC_Selected>", "TTOTAL_CMD")
    vim.map("<shift><enter>", "<TC_SelectedCurrentDir>", "TTOTAL_CMD")
    vim.map("<esc>", "<Return_To_Caller>", "TTOTAL_CMD")
return

<TCDialog_UnMapKeys>:
    vim.mode("normal", "TTOTAL_CMD")
    vim.map("<enter>", "<>", "TTOTAL_CMD")
    vim.map("<ctrl><enter>", "<>", "TTOTAL_CMD")
    vim.map("<shift><enter>", "<>", "TTOTAL_CMD")
    vim.map("<esc>", "<>", "TTOTAL_CMD")
return

;返回调用者
<Return_To_Caller>:
    gosub, <TCDialog_UnMapKeys>

    ;未发现可激活的调用窗体时，最小化TC
    if CallerId = 0
    {
        Winminimize, AHK_CLASS TTOTAL_CMD
        sleep, 500
        CallerId := WinExist("A")
        if CallerId = 0
            return
    }

    WinActivate, ahk_id %CallerId%
return

;发现标准打开文件对话框，未记录，焦点控件为Edit1=>记录，并激活TC
<CheckFileDialog>:
    WinGetClass, class, A
    if class <> #32770
        return

    ControlGetFocus, ct, ahk_class #32770
    if ct <> Edit1
        return

    ;以此排除“另存为”，或其它已经包含文字的对话框
    ControlGetText, str, Edit1, ahk_class #32770
    if StrLen(str) > 0
        return

    ;排除用户自定义窗体
    WinGetText, str, ahk_class #32770
    WinGetTitle, title, ahk_class #32770
    if StrLen(title)=0
        return
    str .= title
    Loop, parse, OpenFileDialogExclude, `, , %A_Space%%A_Tab%
    {
        If StrLen(A_LoopField) = 0
            continue
        IfInString, str, %A_LoopField%
            return
    }

    id := WinExist("A")
    if id = 0
        return
    if id = %CallerId%
        return

    CallerId := id
    gosub, <FocusTC>
    gosub, <TCDialog_MapKeys>
return

; * 非TC窗口按下后激活TC窗口
; * TC窗口按下后复制当前选中文件返回原窗口后粘贴
<OpenTCDialog>:
    ; 复制保存文件对话框中的文件名到剪切板
    send, ^c
    WinGetClass, class, A

    ;在Total Commander按下快捷键时，激活调用窗体并执行粘贴操作
    if class = TTOTAL_CMD
    {
        gosub, <TC_Selected>
        return
    }

    if class <> TTOTAL_CMD
    {
        CallerId := WinExist("A")
        if CallerId = 0
            return

        gosub, <FocusTC>
        gosub, <TCDialog_MapKeys>
        return
    }

return

<TC_PreSelected>:
    SendPos(2021)
    sleep, 100 ; 此处用clipwait貌似会出错？

    ;未多选
    IfNotInString, clipboard, `n
    {
        ;当前复制项为文件夹时
        StringRight, str, clipboard, 1
        IfInString, str, \
            {
                SendPos(2003)
                return
            }
    }

    ;return 注意，此处无需return

<TC_Selected>:
    gosub, <TCDialog_UnMapKeys>

    SendPos(2021)
    sleep, 100

    ;仅在多选时两侧增加双引号
    IfInString, clipboard, `n
    {
        files := ""
        Loop, parse, clipboard, `n, `r
            files .= """" A_LoopField  """ "
        clipboard := files
    }

    ;未发现可激活的调用窗体时，最小化TC
    if CallerId = 0
    {
        Winminimize, AHK_CLASS TTOTAL_CMD
        sleep, 500
        CallerId := WinExist("A")
        if CallerId = 0
            return
    }

    WinActivate, ahk_id %CallerId%
    WinWait, ahk_id %CallerId%
    send, ^v
    send, {Enter}
return

<TC_SelectedCurrentDir>:
    gosub, <TCDialog_UnMapKeys>

    filename := "\" . clipboard
    ; cm_CopySrcPathToClip
    SendPos(2029)
    sleep, 100

    clipboard := clipboard . filename

    ;未发现可激活的调用窗体时，最小化TC
    if CallerId = 0
    {
        Winminimize, AHK_CLASS TTOTAL_CMD
        sleep, 500
        CallerId := WinExist("A")
        if CallerId = 0
            return
    }

    WinActivate, ahk_id %CallerId%
    WinWait, ahk_id %CallerId%
    send, ^v
    send, {Enter}{Enter}
return


make the path for initializing point to C:\Users\%username%\Documents\App Builder

; Audacity hotkeys for segmenting Scripture for Scripture App Builder
; for stand alone use
;
; Version 1.2.4
;
; Written by Ian McQuay
; 2015-Jun-20
; Revised by IM 2015-Jun-23
; Revised by IM 2015-Aug-12
	; fixed wrong output key in tab when not in Audacity
	; fixed wrong output key in \ when not in Audacity
	; added handling send once marker to \ key
	; File open dialog instead of file save
	; Cancel button exits script. As does Esc
	; added handling to copy old ini file to new ini name and delete old file
	; added icon if used as a script
; Revised by IM 2015-10-01
	; created keysub to remove duplicate code in each hotkey.
	; found way of selecting exe file window so language setting problem avoided. No more ToolDock
; Revised by IM 2015-10-02
	; now pass actual key stroke to keysub. Removed need for if statements when Audacity not active. Much easier to add a new key shuold it be needed.
	; also added some documentation in keysub
; Revised IM 2015-10-03
	; * Pause now suspends all other hotkeys and puts notification above tray icon
	; * Suspend in menu now in both right and left click
	; * Suspend also puts up notification of state
	; * Suspend disables the Restart at menu item
	; * Suspend also toggles check mark on the Suspend menu item
; Revised IM 2020-12-01
  ; Revised path for Initialization to point to Documents\App Builder

;
;
; Allow only one instance
#SingleInstance force

; resmove the menu and create new entries
Menu, Tray, NoStandard
Menu, tray, Add, Restart timing at label..., restartAt ; Add the re-start menu
Menu, tray, Add, Suspend hot keys,     SuspendHandler  ; Add a suspend item
Menu, tray, Add, Exit,        ExitHandler     ; Add the exit item
; Left click menu items
Menu, restart, Add, Restart timing at label..., restartAt ; Add the re-start menu
Menu, restart, Add, Suspend hot keys,     SuspendHandler  ; Add a suspend item
Menu, restart, Add, Exit,        ExitHandler     ; Add the exit item

; if not compiled (i.e. used as a script), Set the menu icon and use
if (A_IsCompiled <> 1) {
	iconfile := "Timing-Labels-Assistant.ico"
	menu, tray, Icon, %iconfile%
}

; ini file start =========================================================================================
; Variable for ini file
oldinifile := "Aud-SAB-assist.ini"
iniFile := "timing-labels-assistant.ini"
if (FileExist(oldiniFile)) {
	FileCopy, %oldinifile%, %inifile%
	FileDelete, %oldinifile%
}
; Create ini file if needed
if (FileExist(iniFile)) {
} else {
	FileSelectFolder, PhrasesPath ,C:\Users\%A_Username%\Documents\App Builder, 1, Choose folder where Phrases files are found.
	IniWrite, %PhrasesPath%, %iniFile%, Path, PhrasesPath
}
;Read ini file
IniRead, PhrasesPath, %iniFile%, Path, PhrasesPath , C:\

; Select phrases file
FileSelectFile, PhrasesFile , 1 , %PhrasesPath% , Select Phrase file for currrent chapter, Phrases (*.phrases)
if (ErrorLevel) {
	ExitApp
}
; Update path if needed
curpath := RegExReplace(PhrasesFile, "^(..|....+)\\[^\\]+$", "$1")				; get curent path
if (curpath <> PhrasesPath)														; compare curpath to PharasePath, if different update the ini file
{
	IniWrite, %curpath%, %iniFile%, Path, PhrasesPath
}

; String opperation setup ======================================================================
; Read the content into a variable
FileRead, String , %PhrasesFile%

;Trim off the unwanted \ref line
newString := removeRef(String)
; Show the Phrases content
Run, Notepad.exe "%PhrasesFile%"

; come back here if cancel re-start dialog
norestart:

OnMessage(0x404,"AHK_NotifyTrayIcon") ; Check for left click on tray icon

; key difinitions start ==========================================================================

; Exit the app
pause::
	suspend
	gosub, suspendTip
return

:c?*:zx::
	ExitApp                        ; Exit the current script by typing zx
return

; Hotkeys start with a $ so they don't repeatedly fire themselves when not in Audacity.

$RButton::
	keytype := "{RButton}"
	gosub, keysub
return

$tab::
	keytype := "{tab}"
	gosub, keysub
return

$NumpadAdd::
	keytype := "{NumpadAdd}"
	gosub, keysub
return

$\::
	keytype := "\"
	gosub, keysub
return

; subroutines ===============================================================================================================

keysub:
	; provides the logic for processing two types of hot keys.
	IfWinActive, ahk_exe audacity.exe
	{
		; When Audacity is running
		if (keytype = "{RButton}")
		{
			; handle right mouse button presses
			SetKeyDelay 200
			send, {LButton}
			send ^b
			newString := getRef(newString)
		}
		else
		{
			; handle on the fly keys NumpadAdd, tab or \ during playback of audio.
			SetKeyDelay 200
			send, ^m
			newString := getRef(newString)
		}
	}
	else
	{
		; If Audacity is not in focus then send the pressed key
		send, %keytype%
		ifWinNotExist, ahk_exe audacity.exe  ; exit app if Audacity is not running.
		{
			ExitApp
		}
	}
return

restartAt:
	InputBox, startString, Restart, Please enter the label you want to restart at. e.g. 5c ;Get the values to match
	if ErrorLevel ; Check for cancel button
	{
		ErrorLevel := 0		; reset the ErrorLevel
		goto, norestart		; return to start
	}
	newString := removeRef(String)
	Loop
	{

		newString := removeLine(newString)
		testRef := RegExReplace(newString, "^([^\t]+)\t[^$]*$","$1")
		if (newString = RegExReplace(newString, "^.+\r\n(.*)", "$1"))  ; At the end of the string so empty
		{
			MsgBox, 16, Fatal Error, The value you entered was not found! The label must exist in the phrases file. Try again.,5  ; Tell user to try again
			newString := removeRef(String)						; reset the string to the initial value
			goto, restartAt																; restart the process
		}
	} until testRef = startString
return

ExitHandler:
  ExitApp
return

SuspendHandler:
  suspend toggle
  gosub, suspendTip
return

suspendTip:
  if (A_IsSuspended)
	{
		TrayTip, Timing Labels Assistant, Hot Keys suspended`nPress [pause] to resume
	} else {
		TrayTip, Timing Labels Assistant, Hot Keys active
	}
	Menu, restart, ToggleEnable, Restart timing at label...
	Menu, Tray, ToggleEnable, Restart timing at label...
	Menu, restart, ToggleCheck, Suspend hot keys
	Menu, Tray, ToggleCheck, Suspend hot keys
return

; Functions =============================================================================================================

; Function to get ref and trim from front
getRef(s)
{
	;MsgBox , 8192, "Cur string", %s%, 3
	Ref := RegExReplace(s, "^([^\t]+)\t[^$]*$","$1")
	if ( s = removeLine(s)) {
		SetKeyDelay, 50
		send %Ref%{enter}
		SoundBeep, 750, 500
		ExitApp
	} else {
		SetKeyDelay, 50
		send %Ref%{enter}
		return removeLine(s)
    }
}
AHK_NotifyTrayIcon(wParam, lParam)
{
 global
 If lParam = 0x201
  ShowTrayPopup()
 return
}
ShowTrayPopup()
{
  Menu, restart, Show
}
removeLine(s)
{
	return RegExReplace(s, "^.+\r\n(.+)", "$1")
}
removeRef(s)
{
	return RegExReplace(s, "^\\ref	\\gl\r\n", "")
}
;

; Audacity hotkeys for segmenting Scripture for Scripture App Builder
; for stand alone use
;
; Version 1.2.4
;
; Written by Ian McQuay
; 2015-Jun-20
; Revised by IM 2015-Jun-23
; Revised by IM 2015-Aug-12
	; fixed wrong output key in tab when not in Audacity
	; fixed wrong output key in \ when not in Audacity
	; added handling send once marker to \ key
	; File open dialog instead of file save
	; Cancel button exits script. As does Esc
	; added handling to copy old ini file to new ini name and delete old file
	; added icon if used as a script
; Revised by IM 2015-10-01
	; created keysub to remove duplicate code in each hotkey.
	; found way of selecting exe file window so language setting problem avoided. No more ToolDock
; Revised by IM 2015-10-02
	; now pass actual key stroke to keysub. Removed need for if statements when Audacity not active. Much easier to add a new key shuold it be needed.
	; also added some documentation in keysub
; Revised IM 2015-10-03
	; * Pause now suspends all other hotkeys and puts notification above tray icon
	; * Suspend in menu now in both right and left click
	; * Suspend also puts up notification of state
	; * Suspend disables the Restart at menu item
	; * Suspend also toggles check mark on the Suspend menu item

;
;
; Allow only one instance
#SingleInstance force

; resmove the menu and create new entries
Menu, Tray, NoStandard
Menu, tray, Add, Restart timing at label..., restartAt ; Add the re-start menu
Menu, tray, Add, Suspend hot keys,     SuspendHandler  ; Add a suspend item
Menu, tray, Add, Exit,        ExitHandler     ; Add the exit item
; Left click menu items
Menu, restart, Add, Restart timing at label..., restartAt ; Add the re-start menu
Menu, restart, Add, Suspend hot keys,     SuspendHandler  ; Add a suspend item
Menu, restart, Add, Exit,        ExitHandler     ; Add the exit item

; if not compiled (i.e. used as a script), Set the menu icon and use
if (A_IsCompiled <> 1) {
	iconfile := "Timing-Labels-Assistant.ico"
	menu, tray, Icon, %iconfile%
}

; ini file start =========================================================================================
; Variable for ini file
oldinifile := "Aud-SAB-assist.ini"
iniFile := "timing-labels-assistant.ini"
if (FileExist(oldiniFile)) {
	FileCopy, %oldinifile%, %inifile%
	FileDelete, %oldinifile%
}
; Create ini file if needed
if (FileExist(iniFile)) {
} else {
	FileSelectFolder, PhrasesPath , \ , 1, Choose folder where Phrases files are found.
	IniWrite, %PhrasesPath%, %iniFile%, Path, PhrasesPath
}
;Read ini file
IniRead, PhrasesPath, %iniFile%, Path, PhrasesPath , C:\

; Select phrases file
FileSelectFile, PhrasesFile , 1 , %PhrasesPath% , Select Phrase file for currrent chapter, Phrases (*.phrases)
if (ErrorLevel) {
	ExitApp
}
; Update path if needed
curpath := RegExReplace(PhrasesFile, "^(..|....+)\\[^\\]+$", "$1")				; get curent path
if (curpath <> PhrasesPath)														; compare curpath to PharasePath, if different update the ini file
{
	IniWrite, %curpath%, %iniFile%, Path, PhrasesPath
}

; String opperation setup ======================================================================
; Read the content into a variable
FileRead, String , %PhrasesFile%

;Trim off the unwanted \ref line
newString := removeRef(String)
; Show the Phrases content
Run, Notepad.exe "%PhrasesFile%"

; come back here if cancel re-start dialog
norestart:

OnMessage(0x404,"AHK_NotifyTrayIcon") ; Check for left click on tray icon

; key difinitions start ==========================================================================

; Exit the app
pause::
	suspend
	gosub, suspendTip
return

:c?*:zx::
	ExitApp                        ; Exit the current script by typing zx
return

; Hotkeys start with a $ so they don't repeatedly fire themselves when not in Audacity.

$RButton::
	keytype := "{RButton}"
	gosub, keysub
return

$tab::
	keytype := "{tab}"
	gosub, keysub
return

$NumpadAdd::
	keytype := "{NumpadAdd}"
	gosub, keysub
return

$\::
	keytype := "\"
	gosub, keysub
return

; subroutines ===============================================================================================================

keysub:
	; provides the logic for processing two types of hot keys.
	IfWinActive, ahk_exe audacity.exe
	{
		; When Audacity is running
		if (keytype = "{RButton}")
		{
			; handle right mouse button presses
			SetKeyDelay 200
			send, {LButton}
			send ^b
			newString := getRef(newString)
		}
		else
		{
			; handle on the fly keys NumpadAdd, tab or \ during playback of audio.
			SetKeyDelay 200
			send, ^m
			newString := getRef(newString)
		}
	}
	else
	{
		; If Audacity is not in focus then send the pressed key
		send, %keytype%
		ifWinNotExist, ahk_exe audacity.exe  ; exit app if Audacity is not running.
		{
			ExitApp
		}
	}
return

restartAt:
	InputBox, startString, Restart, Please enter the label you want to restart at. e.g. 5c ;Get the values to match
	if ErrorLevel ; Check for cancel button
	{
		ErrorLevel := 0		; reset the ErrorLevel
		goto, norestart		; return to start
	}
	newString := removeRef(String)
	Loop
	{

		newString := removeLine(newString)
		testRef := RegExReplace(newString, "^([^\t]+)\t[^$]*$","$1")
		if (newString = RegExReplace(newString, "^.+\r\n(.*)", "$1"))  ; At the end of the string so empty
		{
			MsgBox, 16, Fatal Error, The value you entered was not found! The label must exist in the phrases file. Try again.,5  ; Tell user to try again
			newString := removeRef(String)						; reset the string to the initial value
			goto, restartAt																; restart the process
		}
	} until testRef = startString
return

ExitHandler:
  ExitApp
return

SuspendHandler:
  suspend toggle
  gosub, suspendTip
return

suspendTip:
  if (A_IsSuspended)
	{
		TrayTip, Timing Labels Assistant, Hot Keys suspended`nPress [pause] to resume
	} else {
		TrayTip, Timing Labels Assistant, Hot Keys active
	}
	Menu, restart, ToggleEnable, Restart timing at label...
	Menu, Tray, ToggleEnable, Restart timing at label...
	Menu, restart, ToggleCheck, Suspend hot keys
	Menu, Tray, ToggleCheck, Suspend hot keys
return

; Functions =============================================================================================================

; Function to get ref and trim from front
getRef(s)
{
	;MsgBox , 8192, "Cur string", %s%, 3
	Ref := RegExReplace(s, "^([^\t]+)\t[^$]*$","$1")
	if ( s = removeLine(s)) {
		SetKeyDelay, 50
		send %Ref%{enter}
		SoundBeep, 750, 500
		ExitApp
	} else {
		SetKeyDelay, 50
		send %Ref%{enter}
		return removeLine(s)
    }
}
AHK_NotifyTrayIcon(wParam, lParam)
{
 global
 If lParam = 0x201
  ShowTrayPopup()
 return
}
ShowTrayPopup()
{
  Menu, restart, Show
}
removeLine(s)
{
	return RegExReplace(s, "^.+\r\n(.+)", "$1")
}
removeRef(s)
{
	return RegExReplace(s, "^\\ref	\\gl\r\n", "")
}
;


vim.exe can be renamed to renamed to emacs.exe/nano.exe/...

#NoTrayIcon
#NoEnv

arg = %1%

SplitPath, arg, filename, dir
SetWorkingDir, %dir%

SplitPath, A_ScriptName, , , , editor

Run, %A_ScriptDir%\bin\mintty -t "%arg%" -e /bin/wslbridge -t "%editor%" "%filename%"

#NoTrayIcon
#NoEnv

arg = %1%

SplitPath, arg, filename, dir
SetWorkingDir, %dir%

Run, %A_ScriptDir%\bin\mintty -t "%arg%" -e /bin/wslbridge -t vim "%filename%"


removed xscape mapping

removed xscape mapping

;Replaces the default Win+E shortcut with XYplorer
#e::
run C:\Program Files (x86)\XYplorer\XYplorer.exe
return

;Ctrl + Alt + R -- reloads current script
^!r::Reload

;Alt + Win + E -- Opens this file
!#e::
EnvGet, HOME, HOMEPATH
run "gvim" "%HOME%\.dotfiles\autohotkey-scripts\my_keyboard_shortcuts.ahk"
Return

;shortcuts for Vim

Capslock::Ctrl

OpenWithVim() ;opens current file in vim if using XYPlorer, else opens vim
{
	EnvGet, DROPBOX, DB_HOME
	oldClipboard = %clipboard%
	IfWinActive, ahk_class ThunderRT6FormDC
	{
		SendInput ^p
		Sleep, 100
		Run, "gvim" "%clipboard%"
		clipboard = %oldClipboard%
	}
	Else
	{
		Run, "gvim" +star, C:\users\nate
	}
}

Pause::
OpenWithVim()
Return

Insert::
OpenWithVim()
Return

;Replaces the default Win+E shortcut with XYplorer
#e::
run C:\Program Files (x86)\XYplorer\XYplorer.exe
return

;Ctrl + Alt + R -- reloads current script
^!r::Reload

;Alt + Win + E -- Opens this file
!#e::
EnvGet, HOME, HOMEPATH
run "gvim" "%HOME%\.dotfiles\autohotkey-scripts\my_keyboard_shortcuts.ahk"
Return

;shortcuts for Vim

OpenWithVim() ;opens current file in vim if using XYPlorer, else opens vim
{
	EnvGet, DROPBOX, DB_HOME
	oldClipboard = %clipboard%
	IfWinActive, ahk_class ThunderRT6FormDC
	{
		SendInput ^p
		Sleep, 100
		Run, "gvim" "%clipboard%"
		clipboard = %oldClipboard%
	}
	Else
	{
		Run, "gvim" +star, C:\users\nate
	}
}

Pause::
OpenWithVim()
Return

Insert::
OpenWithVim()
Return

Capslock::send {lctrl down}
Capslock up::send % (a_priorkey = "Capslock") ? "{lctrl up}{esc}" : "{lctrl up}"