How to get list of auto uncluded library functions??

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
10inchOfSnow
Posts: 23
Joined: 26 Jul 2019, 06:41

How to get list of auto uncluded library functions??

Post by 10inchOfSnow » 03 Aug 2021, 07:35

How to get list of auto uncluded library functions and other #included files?
And another one, how to do something then file was included (or auto included)?
Read the docs, can't find anything
User avatar
mikeyww
Posts: 26945
Joined: 09 Sep 2014, 18:38

Re: How to get list of auto uncluded library functions??

Post by mikeyww » 03 Aug 2021, 07:37

The includes are hard-coded, so I'd think that the script knows the list.
10inchOfSnow
Posts: 23
Joined: 26 Jul 2019, 06:41

Re: How to get list of auto uncluded library functions??

Post by 10inchOfSnow » 03 Aug 2021, 09:35

Pity, I really need that :|
User avatar
mikeyww
Posts: 26945
Joined: 09 Sep 2014, 18:38

Re: How to get list of auto uncluded library functions??

Post by mikeyww » 03 Aug 2021, 10:53

I'm not saying that there isn't a way. I simply did not understand your situation that would require it.
User avatar
Alguimist
Posts: 428
Joined: 05 Oct 2015, 16:41
Contact:

Re: How to get list of auto uncluded library functions??

Post by Alguimist » 03 Aug 2021, 14:07

There is a function called EnumIncludes:

Code: Select all

/**
 * Function: EnumIncludes
 *     Enumerates all #Include files in the specified script by passing the
 *     the full path to each included file, in turn, to the specified callback
 *     function.
 * Syntax:
 *     count := EnumIncludes( AhkScript, callback [, AhkExe ] )
 * Parameter(s):
 *     count      [retval] - total number of identified #Include(s)
 *     AhkScript      [in] - AutoHotkey script file to scan
 *     callback       [in] - callback function, must be a "Function object"
 *     AhkExe    [in, opt] - if specified, must be the path to the AutoHotkey.exe
 *                           to use as reference for the standard library folder
 *                           location. Defaults to A_AhkPath
 * Remarks:
 *     To continue enumeration, the callback function must return true(1); to stop
 *     enumeration, it must return false(0) or blank("").
 */
EnumIncludes(AhkScript, callback, AhkExe:="")
{
	if !IsObject(callback)
		throw Exception("Invalid parameter -> object expected", -1, callback)
	
	static FullPath
	if !VarSetCapacity(FullPath)
		VarSetCapacity(FullPath, 260 * (A_IsUnicode ? 2 : 1))

	if DllCall("GetFullPathName", "Str", AhkScript, "UInt", 260, "Str", FullPath, "Ptr", 0, "UInt")
		AhkScript := FullPath
	SplitPath, % AhkScript ,, AhkScriptDir

	if (AhkExe != "") && DllCall("GetFullPathName", "Str", AhkExe, "UInt", 260, "Str", FullPath, "Ptr", 0, "UInt")
		AhkExe := FullPath
	if (AhkExe == "") || !FileExist(AhkExe)
		AhkExe := A_AhkPath
	
	cwd := A_WorkingDir
	SetWorkingDir, %AhkScriptDir%
	
	WshExec := "" ; for /iLib (auto-includes)
	includes := {}, count := 0
	script := [ AhkScript ]
	queue := [ AhKScript ]
	while IsObject(f := ObjRemoveAt(queue, 1)) || (f := FileOpen(f, 0|4))
	{
		IsBlockComment := false
		IsContSection := false

		AtEOF := ComObjType(f) ? "AtEndOfStream" : "AtEOF"
		while !f[AtEOF] ; when resumed, will always continue at last postion of file pointer
		{
			line := Trim(f.ReadLine(), " `t`r`n")
			if (line == "")
				continue
			
			if !IsBlockComment && !IsContSection
				if !(IsBlockComment := InStr(line, "/*") == 1) && (InStr(line, "(") == 1)
					IsContSection := line ~= "i)^\((?:\s*(?(?<=\s)(?!;)|(?<=\())(\bJoin\S*|[^\s)]+))*(?<!:)(?:\s+;.*)?$"
			; skip if within block comment/continuation section or if it's a solitary line comment
			if (IsBlockComment && (InStr(line, "*/")==1 ? !(IsBlockComment := false) : 1))
			|| (IsContSection && (InStr(line, ")")==1 ? !(IsContSection := false) : 1))
			|| (InStr(line, ";") == 1)
				continue

			if RegExMatch(line, "Oi)^#Include(?:Again)?(?:\s*,\s*|\s+)(?:\*i\s+)?(\S.*?)(?:\s*|\s+;.*)$", match)
			{
				ThisInclude := ""
				
				static ss_End := A_AhkVersion < "2" ? 0 : -1
				if (InStr(match[1], "<") == 1) && (SubStr(match[1], ss_End) == ">")
				{
					lib := Trim(SubStr(match[1], 2, -1), " `t")
					if pfx := InStr(lib, "_",, 2)
						pfx := SubStr(lib, 1, pfx-1)

					libs := [AhkScript . "\..\Lib", A_MyDocuments . "\AutoHotkey\Lib", AhkExe . "\..\Lib"]
					for i, dir in libs
					{
						if FileExist(ThisInclude := Format("{1}\{2}.ahk", dir, lib))
						|| (pfx && FileExist(ThisInclude := Format("{1}\{2}.ahk", dir, pfx)))
							break
						ThisInclude := ""
					}
				}
				else
				{
					ThisInclude := StrReplace(match[1], "`%A_ScriptDir`%", AhkScriptDir)
					ThisInclude := StrReplace(ThisInclude, "`%A_AppData`%", A_AppData)
					ThisInclude := StrReplace(ThisInclude, "`%A_AppDataCommon`%", A_AppDataCommon)
					ThisInclude := StrReplace(ThisInclude, "`%A_LineFile`%", script[1])

					if InStr(FileExist(ThisInclude), "D")
					{
						SetWorkingDir, %ThisInclude%
						continue
					}
				}

				if (ThisInclude != "") && DllCall("GetFullPathName", "Str", ThisInclude, "UInt", 260, "Str", FullPath, "Ptr", 0, "UInt")
					ThisInclude := FullPath

				if FileExist(ThisInclude) && !includes[ThisInclude]
				{
					includes[ThisInclude] := ++count ; value doesn't really matter as long as it's 'truthy'
					if !callback.Call(ThisInclude)
					{
						f.Close(), f := ""
						break 2
					}
					
					ObjPush(script, ThisInclude)
					ObjPush(queue, ThisInclude)
				}
			} ; if RegExMatch( ... )
		} ; while !f[AtEOF]

		f.Close(), f := "" ; close file/stream
		ObjRemoveAt(script, 1)

		if !ObjLength(queue) && !WshExec
		{
			cmd := Format("{1}{2}{1} /iLib * /ErrorStdOut {1}{3}{1}", Chr(34), A_AhkPath, AhkScript)
			WshExec := ComObjCreate("WScript.Shell").Exec(cmd)
			
			if (err := WshExec.StdErr.ReadAll())
			{
				e := Exception("Failed to retrieve auto-included script files. Script contains syntax error(s).", -1, cmd)
				; idea taken from Lexikos' LoadFile
				if RegExMatch(err, "Os)(.*?) \((\d+)\) : ==> (.*?)(?:\s*Specifically: (.*?))?\R?$", m)
					e.Message .= "`n`nReason:`t" . m[3] . "`nLine text:`t" . m[4] . "`nFile:`t" . m[1] . "`nLine:`t" . m[2]
				throw e
			}
			
			ObjPush(script, "*")
			ObjPush(queue, WshExec.StdOut)
		}
	} ; while IsObject(f := ObjRemoveAt(queue, 1)) ...
 	
	SetWorkingDir, %cwd%

	return count ; NumGet(&includes + 4*A_PtrSize)
}
10inchOfSnow
Posts: 23
Joined: 26 Jul 2019, 06:41

Re: How to get list of auto uncluded library functions??

Post by 10inchOfSnow » 04 Aug 2021, 01:49

mikeyww wrote:
03 Aug 2021, 10:53
I'm not saying that there isn't a way. I simply did not understand your situation that would require it.
Well, I want to post some of my scripts, the point is that I use a lot of my functions and classes auto-included and it would be handy to get a list so I don't have to copy the whole library.
10inchOfSnow
Posts: 23
Joined: 26 Jul 2019, 06:41

Re: How to get list of auto uncluded library functions??

Post by 10inchOfSnow » 04 Aug 2021, 01:52

Alguimist wrote:
03 Aug 2021, 14:07
There is a function called EnumIncludes:

Code: Select all

/**
 * Function: EnumIncludes
 *     Enumerates all #Include files in the specified script by passing the
 *     the full path to each included file, in turn, to the specified callback
 *     function.
 * Syntax:
 *     count := EnumIncludes( AhkScript, callback [, AhkExe ] )
 * Parameter(s):
 *     count      [retval] - total number of identified #Include(s)
 *     AhkScript      [in] - AutoHotkey script file to scan
 *     callback       [in] - callback function, must be a "Function object"
 *     AhkExe    [in, opt] - if specified, must be the path to the AutoHotkey.exe
 *                           to use as reference for the standard library folder
 *                           location. Defaults to A_AhkPath
 * Remarks:
 *     To continue enumeration, the callback function must return true(1); to stop
 *     enumeration, it must return false(0) or blank("").
 */
EnumIncludes(AhkScript, callback, AhkExe:="")
{
	if !IsObject(callback)
		throw Exception("Invalid parameter -> object expected", -1, callback)
	
	static FullPath
	if !VarSetCapacity(FullPath)
		VarSetCapacity(FullPath, 260 * (A_IsUnicode ? 2 : 1))

	if DllCall("GetFullPathName", "Str", AhkScript, "UInt", 260, "Str", FullPath, "Ptr", 0, "UInt")
		AhkScript := FullPath
	SplitPath, % AhkScript ,, AhkScriptDir

	if (AhkExe != "") && DllCall("GetFullPathName", "Str", AhkExe, "UInt", 260, "Str", FullPath, "Ptr", 0, "UInt")
		AhkExe := FullPath
	if (AhkExe == "") || !FileExist(AhkExe)
		AhkExe := A_AhkPath
	
	cwd := A_WorkingDir
	SetWorkingDir, %AhkScriptDir%
	
	WshExec := "" ; for /iLib (auto-includes)
	includes := {}, count := 0
	script := [ AhkScript ]
	queue := [ AhKScript ]
	while IsObject(f := ObjRemoveAt(queue, 1)) || (f := FileOpen(f, 0|4))
	{
		IsBlockComment := false
		IsContSection := false

		AtEOF := ComObjType(f) ? "AtEndOfStream" : "AtEOF"
		while !f[AtEOF] ; when resumed, will always continue at last postion of file pointer
		{
			line := Trim(f.ReadLine(), " `t`r`n")
			if (line == "")
				continue
			
			if !IsBlockComment && !IsContSection
				if !(IsBlockComment := InStr(line, "/*") == 1) && (InStr(line, "(") == 1)
					IsContSection := line ~= "i)^\((?:\s*(?(?<=\s)(?!;)|(?<=\())(\bJoin\S*|[^\s)]+))*(?<!:)(?:\s+;.*)?$"
			; skip if within block comment/continuation section or if it's a solitary line comment
			if (IsBlockComment && (InStr(line, "*/")==1 ? !(IsBlockComment := false) : 1))
			|| (IsContSection && (InStr(line, ")")==1 ? !(IsContSection := false) : 1))
			|| (InStr(line, ";") == 1)
				continue

			if RegExMatch(line, "Oi)^#Include(?:Again)?(?:\s*,\s*|\s+)(?:\*i\s+)?(\S.*?)(?:\s*|\s+;.*)$", match)
			{
				ThisInclude := ""
				
				static ss_End := A_AhkVersion < "2" ? 0 : -1
				if (InStr(match[1], "<") == 1) && (SubStr(match[1], ss_End) == ">")
				{
					lib := Trim(SubStr(match[1], 2, -1), " `t")
					if pfx := InStr(lib, "_",, 2)
						pfx := SubStr(lib, 1, pfx-1)

					libs := [AhkScript . "\..\Lib", A_MyDocuments . "\AutoHotkey\Lib", AhkExe . "\..\Lib"]
					for i, dir in libs
					{
						if FileExist(ThisInclude := Format("{1}\{2}.ahk", dir, lib))
						|| (pfx && FileExist(ThisInclude := Format("{1}\{2}.ahk", dir, pfx)))
							break
						ThisInclude := ""
					}
				}
				else
				{
					ThisInclude := StrReplace(match[1], "`%A_ScriptDir`%", AhkScriptDir)
					ThisInclude := StrReplace(ThisInclude, "`%A_AppData`%", A_AppData)
					ThisInclude := StrReplace(ThisInclude, "`%A_AppDataCommon`%", A_AppDataCommon)
					ThisInclude := StrReplace(ThisInclude, "`%A_LineFile`%", script[1])

					if InStr(FileExist(ThisInclude), "D")
					{
						SetWorkingDir, %ThisInclude%
						continue
					}
				}

				if (ThisInclude != "") && DllCall("GetFullPathName", "Str", ThisInclude, "UInt", 260, "Str", FullPath, "Ptr", 0, "UInt")
					ThisInclude := FullPath

				if FileExist(ThisInclude) && !includes[ThisInclude]
				{
					includes[ThisInclude] := ++count ; value doesn't really matter as long as it's 'truthy'
					if !callback.Call(ThisInclude)
					{
						f.Close(), f := ""
						break 2
					}
					
					ObjPush(script, ThisInclude)
					ObjPush(queue, ThisInclude)
				}
			} ; if RegExMatch( ... )
		} ; while !f[AtEOF]

		f.Close(), f := "" ; close file/stream
		ObjRemoveAt(script, 1)

		if !ObjLength(queue) && !WshExec
		{
			cmd := Format("{1}{2}{1} /iLib * /ErrorStdOut {1}{3}{1}", Chr(34), A_AhkPath, AhkScript)
			WshExec := ComObjCreate("WScript.Shell").Exec(cmd)
			
			if (err := WshExec.StdErr.ReadAll())
			{
				e := Exception("Failed to retrieve auto-included script files. Script contains syntax error(s).", -1, cmd)
				; idea taken from Lexikos' LoadFile
				if RegExMatch(err, "Os)(.*?) \((\d+)\) : ==> (.*?)(?:\s*Specifically: (.*?))?\R?$", m)
					e.Message .= "`n`nReason:`t" . m[3] . "`nLine text:`t" . m[4] . "`nFile:`t" . m[1] . "`nLine:`t" . m[2]
				throw e
			}
			
			ObjPush(script, "*")
			ObjPush(queue, WshExec.StdOut)
		}
	} ; while IsObject(f := ObjRemoveAt(queue, 1)) ...
 	
	SetWorkingDir, %cwd%

	return count ; NumGet(&includes + 4*A_PtrSize)
}
Thx, not sure, but for me this can count buildin functions and can't libs included (return 1) and classes (this is by design, I think).
User avatar
mikeyww
Posts: 26945
Joined: 09 Sep 2014, 18:38

Re: How to get list of auto uncluded library functions??

Post by mikeyww » 04 Aug 2021, 05:49

Thank you for explaining the script's purpose for you. One of the others may have the answer about the functions.
Post Reply

Return to “Ask for Help (v1)”