Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

110.22 Ahk script Debugger 1.1.5b (line-by-line capable)


  • Please log in to reply
9 replies to this topic
Decarlo110
  • Members
  • 303 posts
  • Last active: Feb 12 2006 02:15 AM
  • Joined: 15 Dec 2004
Usage:

#!d debugger settings dialog. Generates or reads from .ini file.
F12 Breaks if there is no splashtext-break; useful if no Line# Return is specified.
RCtrl continue from break; hold down for continuous advance.

Note1: At break-points, hotkeys and timers will still run.
Note2: The presence of timers other than the debug timer will prevent straightforward, line-by-line monitoring of non-timer code.

settings (in settings dialog):

use debug = allows toggling of debug mode.

debug line-by-line = if not checked, the debugger will intercept and display commands which have an execution time of at least .01 sec.

skip 400+ lines-passed alert = is displayed when each of ~400 code lines in LinesHistory execute in less than .01 sec, meaning the debugger will miss monitoring some lines.

sleep to maintain active windows (millisec) = allows adjustment in combination with A_WinDelay, for active windows seen by target code.

Line# Return of target code = used to alert on thread completed (optional).

which Lines to check = if this is used, turn off line-by-line for faster debugging. Specified lines should be Sleep 10 or higher, used as break-points.

---

To debug, place the following 2 lines at the top of the target code to be debugged, after the subroutine label:
if debug_On 
   GoSub Debug_Init

If you have an OnClipboardChange routine, place the following immediately after the label:
if OnClipboardChangeDeactivated OR debugRun   ; or just: if debugRun
   RETURN

Along with the Break/Exit-debug options in the debugger, you may also Reload from the File menu of the Ahk main window.

Here is the debugger code (an example for debugging is given at the end):

SetTitleMatchMode, 2
GoSub Load_DebuggerSettings   ; place in auto-execute section
return

Load_DebuggerSettings:
if FileExist(A_ScriptDir . "\Ahk debugger settings.ini")
{
	IniRead, Debug_On, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_On
	IniRead, Debug_LineByLine, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_LineByLine
	IniRead, Debug_skip400alert, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_skip400alert
	IniRead, Debug_sleepToActive, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_sleepToActive
	IniRead, Debug_line#_Return, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_line#_Return
	IniRead, Debug_LinesToCheck, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_LinesToCheck
}
else
{
	Debug_On = 1
	Debug_LineByLine = 1
	Debug_skip400alert = 0
	Debug_sleepToActive = 100
	Debug_line#_Return = 0
	Debug_LinesToCheck = 0

	FileAppend,
	( LTrim
	[preferences]

	Debug_On = 1
	Debug_LineByLine = 1
	Debug_skip400alert = 0
	Debug_sleepToActive = 100
	Debug_line#_Return = 0
	Debug_LinesToCheck = 0
	), %A_ScriptDir%\Ahk debugger settings.ini
}
;msgbox,,, loaded, .5
return


#!d::

GoSub Load_DebuggerSettings
Gui 31:Destroy
Gui, 31: +AlwaysOnTop
Gui, 31: Add, Checkbox, x16 y7 h20 vDebug_On Checked%Debug_On%, use debug
Gui, 31: Add, Button, Default Hidden x153 y7, OK
Gui, 31: Add, Checkbox, x16 y29 h20 vDebug_LineByLine Checked%Debug_LineByLine%, debug line-by-line
Gui, 31: Add, Checkbox, x16 y51 h20 vDebug_skip400alert Checked%Debug_skip400alert%, skip 400+ lines-passed alert
Gui, 31: Add, Edit, x16 y76 w42 h20 vDebug_sleepToActive, %Debug_sleepToActive%  ;100
Gui, 31: Add, Text, x59 y76 w164,sleep to maintain active windows seen by target code (millisec)
Gui, 31: Add, Edit, x16 y108 w42 h20 vDebug_line#_Return, %Debug_line#_Return%  ;0
Gui, 31: Add, Text, x60 y108 w190, Line# Return of target code (optional).`nused to alert on thread completed
Gui, 31: Add, Edit, x16 y140 w210 h20 vDebug_LinesToCheck, %Debug_LinesToCheck%  ;0
Gui, 31: Add, Text, x16 y162 w210, which Lines to check (0 or blank = all)`nuse commas for 2+
, spaces optional.`nSet specified Lines as Sleep 10 or greater.
Gui, 31: Show, h210 w250, Debug settings
return


31ButtonOK:
31GuiClose:
31GuiEscape:
Gui, 31:Submit
Gui, 31:Destroy
IniWrite, %Debug_On%, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_On
IniWrite, %Debug_LineByLine%, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_LineByLine
IniWrite, %Debug_skip400alert%, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_skip400alert
IniWrite, %Debug_sleepToActive%, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_sleepToActive
IniWrite, %Debug_line#_Return%, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_line#_Return
IniWrite, %Debug_LinesToCheck%, %A_ScriptDir%\Ahk debugger settings.ini, preferences, Debug_LinesToCheck
return


Debug_Init:

WinShow, - AutoHotkey v ahk_class AutoHotkey	; in case DetectHiddenWindows is off.  exclude tooltips
WinRestore, - AutoHotkey v ahk_class AutoHotkey	; prepare for WinMove
WinMove, - AutoHotkey v ahk_class AutoHotkey,, 0, 590, 1024, 150  ; set window to debug-style shape
WinActivate, - AutoHotkey v ahk_class AutoHotkey
Thread, Interrupt, 0	; always allow debug timer
if Debug_LineByLine
	SetBatchLines 1		; allows line-by-line debug
SetTimer Debug, 1
sleep 300	; SetBatchLines=1 requires sufficient sleep to properly take effect
return


Debug:

Debug_line#_Return2 := A_LineNumber + 2
Debug()
return


; adding/deleting lines in this code block requires adjusting Debug_line#_Close
Debug()
{
	Debug_line#_Close := A_LineNumber + 110	; Line of closing brace *******

	global Debug_line#_Return	; return of target code being debugged
	global Debug_line#_Return2	; return of debug timer routine
	global Debug_LinesToCheck
	global debugRun			; for OnClipboardChange handling
	global Debug_On, Debug_skip400alert, Debug_sleepToActive	; settings
	static Debug_line#_Return3

	debugRun ++
	sleep Debug_sleepToActive	; wait for window activated by target code
	winA := WinActive("A")		; store ID of active window
	clipSaved_debug := clipboard
	clipboard =

	ListLines
	WinActivate, - AutoHotkey v ahk_class AutoHotkey	; exclude Ahk tooltips
	ControlSend,, +^{end}^c, - AutoHotkey v ahk_class AutoHotkey	; call main window
	codeToDebug := clipboard
	ControlSend,, ^{end}{up 11}+{end}^c, - AutoHotkey v ahk_class AutoHotkey  ; up # to last line before debug call
	Loop
	{
		code_Line := clipboard
		code_Line := StringL( code_Line, InStr(code_Line, ":")-1 )
		if code_Line is number
			BREAK
		else
			ControlSend,, {up}{home}+{end}^c, - AutoHotkey v ahk_class AutoHotkey
	}
	clipboard := clipSaved_debug
	if (code_Line = Debug_line#_Return2)	; dont display Return of debug timer
	{
		Loop 400
			a=1
		WinActivate, ahk_id %winA%
		WinWaitActive, ahk_id %winA%	; restore active window seen by target code
		Debug_line#_Return3 := A_LineNumber + 2
		if ! GetKeyState("F12", "p")
			RETURN
	}
	Loop 4
		SendMessage, 0x115, 0, 0, Edit1, - AutoHotkey v ahk_class AutoHotkey

	If !Debug_skip400alert & (debugRun >1)
	  && !InStr(codeToDebug, "`n" . Debug_line#_Close . ": }")
	  && !InStr(codeToDebug, "`n" . Debug_line#_Return3 . ": ")
	{
		msgbox, 4353, debug,
		( LTrim
		More than 400 lines were executed in 0.00 sec.
		Some lines of code being debugged have scrolled past in the Line history buffer.`n
		1) Verify that Debug_line#_Close matches the line # of the closing } in Debug()`n
		2) Use    Thread, Interrupt, 0   before   SetTimer, Debug, 1`n
		3) A sleep of 10 or greater may be needed logically prior to Line %code_Line%`n
		[This alert can be deactivated in the debug settings dialog.]`n
		Continue debug?
		)
		IfMsgBox, Cancel
		{
			debugRun =
			SetTimer Debug, off
			WinMove, - AutoHotkey v ahk_class AutoHotkey,, 153, 153, 768, 558
			Loop 400	; for code tracing readability
				a=1
			RETURN
		}
	}
	If (debugRun > 1) AND (InStr(codeToDebug, "`n" . Debug_line#_Return . ": " ) )
	{
		SplashText("*thread completed - press Space to exit", 0, 350)
		Keywait Space, D
		Keywait Space
		debugRun =
		SetTimer Debug, off
		SplashTextOff
		WinMove, - AutoHotkey v ahk_class AutoHotkey,, 153, 153, 768, 558
		WinMinimize - AutoHotkey v ahk_class AutoHotkey
		Loop 400
			a=1
		RETURN
	}
/*	; display lines in preferred editor
	ControlSend,, ^g, <editor_caption>
	sleep 50	; use higher Priority to prevent interruption
	ControlSend,, %code_Line%{Enter}, <editor_caption>
*/
	if ( ! Debug_LinesToCheck ) OR In(code_Line, Debug_LinesToCheck) OR GetKeyState("F12", "p")
	{
		SplashText("variables current to Line " . code_Line
		. "   press RCtrl to continue.  RCtrl.RShift to exit debug", 0, 500)
		WinSet, Enable,, exit debug
		Keywait RCtrl, D
		sleep 150
		if GetKeyState("RShift", "p") AND GetKeyState("RCtrl", "p")
		{
			; needed to exit.  using before Keywait above disallows other threads
			Thread, Priority, 999

			debugRun =
			SetTimer, Debug, off
			WinRestore, - AutoHotkey v ahk_class AutoHotkey
			WinMove, - AutoHotkey v ahk_class AutoHotkey,, 153, 153, 768, 558
			WinMinimize - AutoHotkey v ahk_class AutoHotkey
		}
		SplashTextOff
	}
	Loop 400	; for code tracing readability & to prevent false thread-complete alert
		a=1
	WinActivate, ahk_id %winA%
	WinWaitActive, ahk_id %winA%,, 1.2	; restore active window seen by target code
}	; this line number must match Debug_line#_Close *******


StringL(in, charsToKeep, charsToTrim="")
{
	StringLeft, out, in, %charsToKeep%
	if charsToTrim
		StringTrimLeft, out, out, %charsToTrim%
	return out
}

In( a, b )   ; If a in b list
{
	Loop, Parse, b, `,, %A_Space%%A_Tab%
		if a = %A_LoopField%
			Return 1
}

SplashText(title="", timeout="", width="", height="", text="")   ; default timeout 700
{
	SplashTextOn, %Width%, %Height%, %Title%, %Text%
	if timeout =
		sleep 700
	else if timeout = 0	; leave on until replaced or turned off later
		RETURN
	else
		sleep %timeout%
	SplashTextOff
	return
}


!-::	; example code for debug

if debug_On
	GoSub Debug_Init

; the lines above prepare the debug
; the lines below are the code to debug (example)

Loop 3
{
	sleep 10
	a=1
	b=2
	c=3
	d=4
}
Return

i will probably improve the code to optionally show last 10 lines executed, or last N lines specified by the user. Also, it would be good to have a display of target variables, selected by the user beforehand. Currently, ^v to display all the script's variables, will have to suffice. I will also look into removing the timer-limitation in line-by-line mode.
1) The Open Source Definition http://www.opensourc...ition_plain.php

2) Intuitive. Logical. Versatile. Adaptable. <>

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
That's a great idea. When I find time I will study the code. Thanks for sharing.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
Yes, it's a great script!
Simple to read, but I will also have to try the different settings..

Nice 1!

Thalon

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
don't these functions
StringL(in, charsToKeep, charsToTrim="") 

InString(a,b)
already exist in AHK? I thought StringMid and InStr() would do the same thing?
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

shimanov
  • Members
  • 610 posts
  • Last active: Jul 18 2006 08:35 PM
  • Joined: 25 Sep 2005
An interactive AHk debugger is an interesting idea. Could be useful to help new users get a feel for AHk.

Decarlo110
  • Members
  • 303 posts
  • Last active: Feb 12 2006 02:15 AM
  • Joined: 15 Dec 2004

don't these functions

StringL(in, charsToKeep, charsToTrim="") 
InString(a,b)
already exist in AHK? I thought StringMid and InStr() would do the same thing?

You are right that StringMid can be used, but i've personally found StringL() to be a bit more useful than StringMid() would be, and so it has become my preference. On InString() vs. InStr(), my use of InString() had simply become a habit (there were 2 months after Functions had first become available that the current built-in functions were not yet built-in), plus i stripped part of my custom function that i had been experimenting with. Anyway, i've changed the code to use InStr() throughout. Thanks for mentioning it.

---

For those who have been experimenting with the debugger, you may have noticed that the line-by-line mode wasnt really line-by-line. In v1.1.2 it had been working, but when i coded the Debug_Init subroutine, i changed the sleep value to 10, which apparently affects whether SetBatchLines=1 takes effect. However, this has been fixed by raising the Sleep period to a higher value (300).

; v1.1.4

; fixed line-by-line mode
; added Return=Submit+Close in settings dialog

Thanks all for the compliments. I hope to improve the code further.
1) The Open Source Definition http://www.opensourc...ition_plain.php

2) Intuitive. Logical. Versatile. Adaptable. <>

Decarlo110
  • Members
  • 303 posts
  • Last active: Feb 12 2006 02:15 AM
  • Joined: 15 Dec 2004
; v1.1.5

;

; fixed/eliminated indefinite waiting if target script uses dialog windows

1) The Open Source Definition http://www.opensourc...ition_plain.php

2) Intuitive. Logical. Versatile. Adaptable. <>

luckcity
  • Members
  • 31 posts
  • Last active: Jun 13 2011 05:01 AM
  • Joined: 02 Mar 2008
I hope someone is around to help for this subject.
I wish to see the last line of my code listed in the debugger

All I see is the code lines of the debugger listed, and once in a while some of my code, after pressing F5.

or perhaps there is an simple alternative to this debugger..

I see Decarlo110 hasnt been posting for a few years.
ta,

indhunathan
  • Guests
  • Last active:
  • Joined: --
how to use debugger coding?
:lol:

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
https://ahknet.autoh... ... htm#idebug