- Offizieller Beitrag
Angeregt durch diese Anfrage habe ich nach einer möglichst komfortablen Lösung gesucht.
Herausgekommen ist: DebugFuncCallSC.lua und DebugFuncCallSC.au3
- "DebugFuncCallSC.lua" muss in "SciTEStartup.lua" geladen sein
- Anwendung
Direkt in die Zeile nach einem Funktionsaufruf wird eingefügt: "_DebugFC_Set(@ScriptLineNumber)"
Sollte die Folgezeile eine Fehlerauswertung enthalten, dann in die nächste Zeile einfügen. Das Skript prüft ob in der Zeile ein "@error"
zu finden ist, und wertet dann die davor liegende Zeile aus.
Nun sind die Informationen für
"File" Name der Datei, die die Funktionsdeklaration enthält (Include, aktuelle Datei oder "Native")
"Func" Name der aufgerufenen Funktion
"Line" Zeile des Funktionsaufrufs
gespeichert bis zum nächsten Aufruf von "_DebugFC_Set()".
Ausgewertet wird dann mit: "$tDebug = _DebugFC_Get()"
"$tDebug" enthält die oben bereits benannten Inhalte in den Feldern
.File
.Func
.Line
Bsp.:
$result = _EineFunktion('bla', $a) ; Aufruf in Zeile #25, Datei aus UserInclude "_MyUDF.au3"
$iErr = @error
_DebugFC_Set(@ScriptLineNumber)
$tDebug = _DebugFC_Get()
ConsoleWrite($tDebug.File & '|' & $tDebug.Func & '(' & $tDebug.Line & ')' & @TAB & ($iErr ? 'FEHLER' : 'OK') & @CRLF)
;==================================================================================================================
OUTPUT:
_MyUDF.au3 | _EineFunktion() (25) OK
Alles anzeigen
Das Lua-Skript liest den Funktionsnamen aus, prüft ob diese Funktion im aktuellen Skript oder in einem der vorhandenen Includes deklariert wurde (falls nicht ist es eine native Funktion) und ermittelt die Zeile in der der Befehlsaufruf steht. Alles wird dann in eine temporäre Datei geschrieben.
Das AutoIt-Skript schubst das Lua-Skript an ( mit _DebugFC_Set() ), liest die Ergebnisse aus der temp. Datei und bereitet sie auf ( mit _DebugFC_Get() ).
WICHTIG!
Damit das korrekte Include gefunden wird, muss auch das Include eingebunden sein, das die aufgerufene Funktion tatsächlich enthält. Ein rekursives Suchen (Include im Include) wird nicht durchgeführt.!
-- TIME_STAMP 2021-06-08 13:41:48 v 0.1
-- coding:utf-8
--[[
- Skript in "SciTEStartup.lua" starten
- zugehöriges AutoItSkript "DebugFuncCallSC.au3" als Include
]]
DebugFC = {}
-----------------------------------------------------------------------------------------------------------------------------------------------------
DebugFC.IsComment = function(self, _pos) local tComment = {1,2} if tComment[editor.StyleAt[_pos]] == nil then return false else return true end end
DebugFC.InSense = function(self, _s) _s = _s:gsub("%a", function(_c) return string.format("[%s%s]", _c:upper(),_c:lower()) end) return _s end
DebugFC.FileExists = function(self, _path) local fh = io.open(_path) if fh ~= nil then fh:close() return true else return false end end
-----------------------------------------------------------------------------------------------------------------------------------------------------
-- OK
DebugFC.IncludeExistsInFolder = function(self, _incl)
-- OpenPath (Pfade für Includes) abfragen
local sOpen, tOpen = props['openpath.$(au3)'], {}
for w in sOpen:gmatch("([^;]+)") do table.insert(tOpen, w) end
-- Prüfen ob Include ohne Voranstellen von Ordner existiert (Include im Skriptdir oder kompletter Pfad im Include)
if self:FileExists(_incl) then
-- Ordnertrennzeichen im Pfad? ( "\" oder "/" )
local p = _incl:find('\\[^\\]+$')
if not p then p = _incl:find('/[^/]+$') end
if p then
return _incl:sub(1, p-1), _incl:sub(p+1) -- Pfad, Dateiname.ext
else
return props['FileDir'], _incl
end
end
-- in den gefundenen OpenPath nach Include suchen
if #tOpen > 0 then
for i=1, #tOpen do
if self:FileExists(tOpen[i]..'\\'.._incl) then return tOpen[i], _incl end
end
end
return nil, nil
end
-- OK
DebugFC.DeclaredFuncsInEditor = function(self)
local pattFunc = '('..self:InSense('func')..'%s+[%w_]+%s-%b())'
local pattFuncName = '('..self:InSense('func')..'%s+)([%w_]+)(%s-%b())'
local tFunc, e, n, sFunc, a = {}, 1, 0, ''
local s = editor:GetText()
while e do
a, e, fname = s:find(pattFunc, e)
if a and not self:IsComment(a) then
_, _, _, fname = fname:find(pattFuncName)
table.insert(tFunc, fname)
n = n +1
end
end
if n == 0 then return nil else return tFunc end
end
-- OK
DebugFC.DeclaredFuncsInFile = function(self, _file)
local pattFunc = '('..self:InSense('func')..'%s+[%w_]+%s-%b())'
local pattFuncName = '('..self:InSense('func')..'%s+)([%w_]+)(%s-%b())'
local tFunc, e, n, sFunc, s, a = {}, 1, 0, ''
local fh = io.open(_file)
if fh then s = fh:read('*a') fh:close() end
if s ~= nil then
while e do
a, e, fname = s:find(pattFunc, e)
if a then
_, _, _, fname = fname:find(pattFuncName)
table.insert(tFunc, fname)
n = n +1
end
end
end
if n == 0 then return nil else return tFunc end
end
-- OK
DebugFC.GetIncludes = function(self)
local text = editor:GetText()
local tIncl, incl = {}, ''
for _, incl in text:gmatch("[\n]?(#"..self:InSense('include').."%s-<([%w%s_.:\\/]+)>)") do table.insert(tIncl,incl) end -- #include <abc.au3> --> abc.au3
for _, _, incl in text:gmatch("[\n]?(#"..self:InSense('include').."%s-([\"'])([%w%s_.:\\/]+)%2)") do table.insert(tIncl,incl) end -- #include 'abc.au3' or #include "abc.au3" --> abc.au3
return tIncl
end
-- OK
DebugFC.WhereDeclared = function(self, _f)
-- im Skript deklarierte Funktionen - Rückgabe aktueller Skriptname
local tCurrent = self:DeclaredFuncsInEditor()
if tCurrent ~= nil then
for i=1, #tCurrent do
if tCurrent[i]:upper() == _f:upper() then
return props['FileNameExt']
end
end
end
-- in Includes deklarierte Funktionen - Rückgabe Includename
local tIncluded, tFuncs = self:GetIncludes()
if #tIncluded > 0 then
for i=1, #tIncluded do
local folder, file = self:IncludeExistsInFolder(tIncluded[i])
if folder ~= nil then
-- Funktionsdeklarationen aus Includedateien ermitteln
tFuncs = self:DeclaredFuncsInFile(folder..'\\'..file)
if tFuncs ~= nil then
for j=1, #tFuncs do
if tFuncs[j]:upper() == _f:upper() then
return tIncluded[i]
end
end
end
end
end
end
-- nicht deklariert: nativ
return 'Native'
end
-- In 1.te oder 2.te (ermöglicht vorheriges Abfangen von @error) Zeile unter Funktionsaufruf muss gesetzt werden: _DebugFC_Set(ScriptLineNumber)
-- Wenn in der 1.ten Zeile vor "_DebugFC_Set" ein "@error" gefunden wird, verwendet das Skript die 2.te Zeile davor
DebugFC.FuncFromLine = function(self, _line)
-- _line ist @ScriptLineNumber, steht 1 Zeile unter dem gefragten Funktionsaufruf, ist 1-basiert -> für 0-basiert: -2
_line = _line -2
local line = editor:GetLine(_line)
if line:find(self:InSense('@error')) then
_line = _line -1
line = editor:GetLine(_line)
_line = _line +1
end
local sfunc = line:match('([%w_]+)(%s-%b())')
local swrite, fh = ''
if sfunc ~= nil then
swrite = swrite..self:WhereDeclared(sfunc)..'\r\n'..sfunc..'()'..'\r\n'.._line..'\r\n'
fh = io.open(os.getenv('TEMP')..'\\DebugFuncCall.result','w+')
fh:write(swrite)
fh:close()
end
end
-- Gibt die zuletzt gespeicherten Werte aus über: _DebugFC_Get()
--[[ Bsp.
$result = _EineFunktion('bla', $a) ; Aufruf in Zeile #25, Datei aus UserInclude "_MyUDF.au3"
$iErr = @error
_DebugFC_Set(ScriptLineNumber)
$tDebug = _DebugFC_Get()
ConsoleWrite($tDebug.File & '|' & $tDebug.Func & '(' & $tDebug.Line & ')' & @TAB & ($iErr ? 'FEHLER' : 'OK') & @CRLF)
;==================================================================================================================
#cs OUTPUT
_MyUDF.au3 | _EineFunktion() (25) OK
#ce
]]
Alles anzeigen
;-- TIME_STAMP 2021-06-08 14:21:38 v 0.1
#cs
- "DebugFuncCallSC.lua" muss in "SciTEStartup.lua" geladen sein
- Anwendung
Direkt in die Zeile nach einem Funktionsaufruf wird eingefügt: "_DebugFC_Set(@ScriptLineNumber)"
Sollte die Folgezeile eine Fehlerauswertung enthalten, dann in die nächste Zeile einfügen. Das Skript prüft ob in der Zeile ein "@error"
zu finden ist, und wertet dann die davor liegende Zeile aus.
Nun sind die Informationen für
"File" Name der Datei, die die Funktionsdeklaration enthält (Include, aktuelle Datei oder "Native")
"Func" Name der aufgerufenen Funktion
"Line" Zeile des Funktionsaufrufs
gespeichert bis zum nächsten Aufruf von "_DebugFC_Set()".
Ausgewertet wird dann mit: "$tDebug = _DebugFC_Get()"
"$tDebug" enthält die oben bereits benannten Inhalte in den Feldern
.File
.Func
.Line
Bsp.:
$result = _EineFunktion('bla', $a) ; Aufruf in Zeile #25, Datei aus UserInclude "_MyUDF.au3"
$iErr = @error
_DebugFC_Set(@ScriptLineNumber)
$tDebug = _DebugFC_Get()
ConsoleWrite($tDebug.File & '|' & $tDebug.Func & '(' & $tDebug.Line & ')' & @TAB & ($iErr ? 'FEHLER' : 'OK') & @CRLF)
;==================================================================================================================
OUTPUT:
_MyUDF.au3 | _EineFunktion() (25) OK
#ce
Global $g_SciTECmd
Func _DebugFC_Set($_lineNumber)
_ScI_Dostring("DebugFC:FuncFromLine(_1)", $_lineNumber)
EndFunc
Func _DebugFC_Get()
Local $sRead = FileRead(@TempDir & '\DebugFuncCall.result')
Local $aSplit = StringSplit($sRead, @CRLF, 1)
If $aSplit[0] < 3 Then Return
Local $sFile = StringStripWS($aSplit[1], 2)
Local $sFunc = StringStripWS($aSplit[2], 2)
Local $sLine = StringStripWS($aSplit[3], 2)
Local $iLen1 = StringLen($sFile)
Local $iLen2 = StringLen($sFunc)
Local $iLen3 = StringLen($sLine)
Local $tGet = DllStructCreate( _
'char File[' & ($iLen1 = 0 ? 1 : $iLen1) & '];' & _
'char Func[' & ($iLen2 = 0 ? 1 : $iLen2) & '];' & _
'char Line[' & ($iLen3 = 0 ? 1 : $iLen3) & ']')
$tGet.File = $sFile
$tGet.Func = $sFunc
$tGet.Line = $sLine
Return $tGet
EndFunc
;===============================================================================
; Function Name....: _ScI_Dostring
; Description......: Einen Luastring mit/ohne Parameter aufrufen OHNE ein Ergebnis zu erhalten
; : Parameter im Lua-String (max. 10) sind in der Form "_1", "_2", .., "_n" zu benennen.
; Parameter(s).....: $_sLua - der Lua-String
; : $p1 - [optional] Parameter1 für den Lua-String ("_1")
; : ... bis
; : $p10 - [optional] Parameter10 für den Lua-String ("_10")
; Return Value(s)..: keine
; Author(s)........: BugFix ( bugfix@autoit.de )
;-------------------------------------------------------------------------------
; Bsp.:
; ohne Parameter:
; _ScI_Dostring("print('Hallo Welt!')")
;
; mit Parameter:
; _ScI_Dostring("editor:SetSelection(_1,_2)", 4, 14)
;===============================================================================
Func _ScI_Dostring($_sLuastring, $p1=Null, $p2=Null, $p3=Null, $p4=Null, $p5=Null, $p6=Null, $p7=Null, $p8=Null, $p9=Null, $p10=Null)
Local $aParamCall[] = [$p1,$p2,$p3,$p4,$p5,$p6,$p7,$p8,$p9,$p10], $index = 0
While $aParamCall[$index] <> Null
$_sLuastring = StringRegExpReplace($_sLuastring, '_\d+', $aParamCall[$index], 1)
$index += 1
WEnd
SendSciTE_Command("extender:dostring do " & $_sLuastring & " end")
EndFunc
; by BugFix
Func _GetHwndDirectorExtension()
Local $hActive = WinGetHandle('[ACTIVE]')
Local $PIDActive = WinGetProcess($hActive)
Local $aExtension = WinList("DirectorExtension")
Local $PIDExt
For $i = 1 To $aExtension[0][0]
$PIDExt = WinGetProcess($aExtension[$i][1])
If $PIDExt = $PIDActive Then Return $aExtension[$i][1]
Next
EndFunc
; by Jos
Func SendSciTE_Command($_sCmd, $Wait_For_Return_Info=0)
Local $WM_COPYDATA = 74
Local $WM_GETTEXT = 0x000D
Local $WM_GETTEXTLENGTH = 0x000E224
Local Const $SCI_GETLINE = 2153
Local $Scite_hwnd = _GetHwndDirectorExtension() ; Get SciTE DIrector Handle
Local $My_Hwnd = GUICreate("AutoIt3-SciTE interface") ; Create GUI to receive SciTE info
Local $My_Dec_Hwnd = Dec(StringTrimLeft($My_Hwnd, 2)) ; Convert my Gui Handle to decimal
$_sCmd = ":" & $My_Dec_Hwnd & ":" & $_sCmd ; Add dec my gui handle to commandline to tell SciTE where to send the return info
Local $CmdStruct = DllStructCreate('Char[' & StringLen($_sCmd) + 1 & ']')
DllStructSetData($CmdStruct, 1, $_sCmd)
Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr')
DllStructSetData($COPYDATA, 1, 1)
DllStructSetData($COPYDATA, 2, StringLen($_sCmd) + 1)
DllStructSetData($COPYDATA, 3, DllStructGetPtr($CmdStruct))
$g_SciTECmd = ''
DllCall('User32.dll', 'None', 'SendMessage', 'HWnd', $Scite_hwnd, _
'Int', $WM_COPYDATA, 'HWnd', $My_Hwnd, _
'Ptr', DllStructGetPtr($COPYDATA))
GUIDelete($My_Hwnd)
If $Wait_For_Return_Info Then
Local $n = 0
While $g_SciTECmd = '' Or $n < 10
Sleep(20)
$n += 1
WEnd
EndIf
Return $g_SciTECmd
EndFunc ;==>SendSciTE_Command
Func MY_WM_COPYDATA($hWnd, $msg, $wParam, $lParam)
Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr', $lParam)
Local $SciTECmdLen = DllStructGetData($COPYDATA, 2)
Local $CmdStruct = DllStructCreate('Char[' & $SciTECmdLen+1 & ']',DllStructGetData($COPYDATA, 3))
$g_SciTECmd = StringLeft(DllStructGetData($CmdStruct, 1), $SciTECmdLen)
EndFunc ;==>MY_WM_COPYDATA
Alles anzeigen