[Function] object_list() Display contents of objects

Post your working scripts, libraries and tools.
User avatar
Relayer
Posts: 160
Joined: 30 Sep 2013, 13:09
Location: Delaware, USA

[Function] object_list() Display contents of objects

Post by Relayer » 16 Feb 2023, 11:41

Updated 2023-03-07

For v1 I have relied on a script I found on the forum that produces a nice text rendering of what objects contain. It helps in crafting custom data structures and is very useful in troubleshooting. Here is a v2 version that I've put together that distinguishes between plain objects and then arrays and maps. There are probably embellishments that could be added that would better span the capability of v2 but this at least got me to where I was with v1. The examples may help provide some education for those beginning to work with v2 for the first time.

A call to this function as object_list(complexObj, "complex object") produces the human readable result:
Spoiler

Relayer

Code: Select all

#SingleInstance Force
#Requires AutoHotkey v2.0

;#Include "C:\utilities\AutoHotKey\V2\Lib\object_list.ahk"

;EXAMPLE
jack := "this is not an object"  ;NOTE: this example shows behavior when you pass a non-object to the function
object_list(jack, "misfire")

complexObj := [ "one", "two", "three", "four"
				, map("five", 5)
				, {six : 6, seven : 7, eight : map("dog", "cat")
				, nine : [ 10, 9, 8, 7
				, map("1040", array({})), 6, 5, 4, 3 ]}
				, map()
				, array()
				, {} ]

object_list(complexObj, "complex object")
object_list(complexObj, "complex object", True) ;show details

;Object... not quoted key, key is PROPERTY and is NOT case sensitive... accessed by '.'
manny := { JAN : "01"
		,  Feb : "02"
		,  Mar : "03"
		,  Apr : "04"
		,  May : "05"
		,  Jun : "06"
		,  Jul : "07"
		,  Aug : "08"
		,  Sep : "09"
		,  Oct : "10"
		,  Nov : "11"
		,  Dec : "12"
		,  name : "Calendar as OBJECT" }
		
; MAP  is associative array... key is quoted and IS CASE SENSITIVE... accessed by ["yada"]
moe := map( "JAN" , "01"
		 ,  "Feb`n`n" , "02"
		 ,  "Mar`t" , "03"
		 ,  "Apr" , "04"
		 ,  "May" , "05"
		 ,  "Jun" , "06"
		 ,  "Jul" , "07"
		 ,  "Aug" , "08"
		 ,  "Sep" , "09"
		 ,  "Oct" , "10"
		 ,  "Nov" , "11"
		 ,  "Dec" , "12"
		 , "name", "Calendar as MAP" )

Msgbox(moe["Feb`n`n"])
Msgbox(moe["Mar`t"])

object_list(manny)
object_list(manny, "manny")
object_list(moe)
object_list(moe, "moe")

;array
jack := ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
Msgbox(jack[5])
object_list(jack, "jack")

Msgbox(manny is object) ;yes
Msgbox(manny is map) ;no
Msgbox(manny is array) ;no
Msgbox(moe is object) ;yes
Msgbox(moe is map) ;yes
Msgbox(moe is array) ;no

Msgbox(manny.jan . "`n" . moe["JAN"])

for k, v in moe
	Msgbox("map: " . k . " = " . v)

;Object NOT enumerable this way
;for k, v in manny

;make Object enumerable with 'OwnProps'
for k, v in manny.OwnProps()
	Msgbox("object (thru 'OwnProps'): " . k . " = " . v)
	
Msgbox(ObjOwnPropCount(manny))
Msgbox(ObjGetCapacity(manny))

^Escape::ExitApp


/*
---------------------------------------------------------------------------------------------------
Function      : object_list(obj, name [string], details [boolean])
              :
Description   : Traverses the object's member variables and builds a string to show what it
              : contains.  Displays the contents stored in any type of object: MAP, ARRAY, OBJECT
              : 
Parameters    :     obj - The object to display
              :    name - The name you want to show for the object at the top level. If the object
              :           is not an ARRAY and there is a member named "name" it will be used. Note
              :           that 'name' is lower case for a MAP.
              : details - 'True' will enable showing all built in properties, 'False' otherwise
              : 
Returns       : string summary of object suitable for viewing
              : 
Remarks       : OBJECT properties are shown as <.property> = value
              : ARRAY  keys are shown as [key] = value
              : MAP    keys are shown as ['key'] = value
---------------------------------------------------------------------------------------------------
*/

object_list(obj, name := "", details := False)
{
	if (isObject(obj))
		Msgbox(object_list_(obj, name,, details))
	else
		Msgbox("object_list() reports... Passed parameter is not an object:"
			. "`n" . (name = "" ? "" : "<" . name . ">`n") . obj)
	Return
}

;recursive
object_list_(obj, name := "", indent := "`n", details := False)
{
	static recursionDepth := 0
	
	inputIs := type(obj)
	
	if (++recursionDepth >= 200)
	{
		Msgbox("object_list recursion depth hit trigger of " . recursionDepth)
		Return False
	}
	if (name = "") and !(obj is array) and ( (obj is map) ? obj.Has("name") : obj.HasOwnProp("name") )
		name := (obj is map) ? obj["name"] : obj.name
	;suppress CR on first line but not on recursive call when indent = " ."
	output := indent = "`n" ? ("<" . name . "> = <" . inputIs . ">") : (indent . "<" . name . "> = <" . inputIs . ">")
	indent .= " ."
	
	; The array 'possibleProperties' is a list of built-in properties for v2 objects.  When
	; details are requested, the 'try' in the for-loop will attempt to extract each property
	; and only successful ones will be included in the output.
	if (details)
	{
		possibleProperties := [ "Length", "Capacity", "Default", "Count", "CaseSense"
							  , "BackColor", "FocusedCtrl", "Hwnd", "MarginX", "MarginY", "MenuBar", "Name", "Title"
							  , "ClassNN", "Enabled", "Focused", "Gui", "Text", "Type", "Value", "Visible" ]
		
		for k, v in possibleProperties
			try output .= indent . "<." . v . "> = " . obj.%v%
	}
	keyCount := 0
	for key, val in ((obj is Map) or (obj is Array)) ? obj : obj.OwnProps()
	{
		;if key is an object its type will be displayed
		;the KEY will NOT be enumerated but any associated VALUE will if it is also an object
		if (isObject(key))
			key := type(key)
			
		keyCount++
		key := StrReplace(key, "`t", "``t")
		key := StrReplace(key, "`n", "``n")
		key := StrReplace(key, "`r", "``r")
		switch inputIS
		{
			case "Map":   key := "['" . key . "']" ;report using single quotes and brackets
			case "Array": key := "[" . key . "]"   ;report using brackets only
		}

		if (isObject(val))
			output .= object_list_(val, key, indent, details) ;recursive
		else
			output .= indent . "<" . key . "> = " . val
	}
	if (keyCount = 0) and ((inputIs = "Map") or (inputIs = "Array") or (inputIs = "Object"))
		output := StrReplace(output, inputIs, "EMPTY " . inputIs)

	recursionDepth--
	return output
}

XMCQCX
Posts: 224
Joined: 14 Oct 2020, 23:44

Re: [Function] object_list() Display contents of objects

Post by XMCQCX » 20 Mar 2023, 17:05

Awesome, thanks for sharing! I print the result in Notepad++ with Tail monitoring enable on my secondary monitor. Extremely useful. :thumbup:

User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: [Function] object_list() Display contents of objects

Post by FanaticGuru » 24 Mar 2023, 16:26

Relayer wrote:
16 Feb 2023, 11:41
A call to this function as object_list(complexObj, "complex object") produces the human readable result:

This is what I use.

Code: Select all

#Requires AutoHotkey v2.0

; DisplayObj by FanaticGuru (inspired by tidbit and Lexikos v1 code)
DisplayObj(Obj, Depth := 5, IndentLevel := '')
{
	List := ''
	If Type(Obj) ~= 'Object|Gui'
		Obj := Obj.OwnProps()
	For k, v in Obj
	{
		List .= IndentLevel '[' k '] <' Type(v) '>'
		If (IsObject(v) && Depth > 1)
			List .= '`n' DisplayObj(v, Depth - 1, IndentLevel . '    ')
		Else
			If !isobject(v)
				List .= ' => ' v
		List .= '`n'
	}
	Return RTrim(List)
}

complexObj := ['one', 'two', 'three', 'four'
	, Map('five', 5)
	, { six: 6, seven: 7, eight: Map('dog', 'cat')
		, nine: [10, 9, 8, 7
			, Map('1040', Array([],{})), 6, 5, 4, 3] }
	, Map()
	, Array()
	, {}]

MsgBox DisplayObj(complexObj)

It does not do quite as much but it is considerably simplier.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Post Reply

Return to “Scripts and Functions (v2)”