Что нового

[Новая функция] Запрос на новую функцию или макро для возвращения текущей функции

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Хотелось бы узнать, какая функция выполняется при вызове функции или получения значения от макро. Некий аналог @ScriptLineNumber, только показывающий название функции - Main если на момент вызова выполняется главный скрипт, и funcname если функция. Хочу сделать некое подобие traceback'ов
 

SyDr

Сидра
Сообщения
651
Репутация
158
Эмммм... Что-то вроде...
Код:
Func _Display($string)
	MsgBox(4096, Default, $string)
EndFunc

_Display("main")
Another()
Func Another()
	MsgBox(4096, Default, "Another")
EndFunc


В чём суть, непонятно как-то...
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
SyDr
суть в обработке исключений. можно конечно руками писать в теле каждой функции. но хотелось бы иметь что-то вроде @ScriptCurrenctFunc, которая бы показывала где именно она была вызвана. Например, сейчас я обрабатываю ошибки и вывожу отчет простейшим
Код:
; Here we have some error
__Matrix_Err($imsg, 'main')
Func _MyFunc($someparams)
    ; Here I do something and have another error
    __Matrix_Err($imsg, '_MyFunc')
EndFunc

Func __Matrix_Err($imsg, $funcname)
	Switch $imsg
		Case 1
			$smsg = 'One or more arrays are not numbered matrices'
	ConsoleWrite($smsg & ' (' & $funcname & ')' & @CRLF)
EndFunc

а хотелось бы
Код:
; Here we have some error
__Matrix_Err($imsg, @ScriptCurrentFunc)
Func _MyFunc($someparams)
    ; Here I do something and have another error
    __Matrix_Err($imsg, @ScriptCurrentFunc)
EndFunc

Func __Matrix_Err($imsg, $funcname)
	Switch $imsg
		Case 1
			$smsg = 'One or more arrays are not numbered matrices'
	ConsoleWrite($smsg & ' (' & $funcname & ')' & @CRLF)
EndFunc


думаю, объяснять какой в этом смысл не надо.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Подобную функцию-макрос можно сделать только для не скомпилированного скрипта.

Подобный запрос кажется уже был озвучен на оф. форуме, разработчики посчитали что оно не нужно.


Добавлено:
Сообщение автоматически объединено:

[?]
Подобную функцию-макрос можно сделать только для не скомпилированного скрипта
Вот так к примеру:

Код:
#include <GUIConstantsEx.au3>

$hGUI = GUICreate("ScriptCurrentFunc Demo", 300, 200)
$nButton = GUICtrlCreateButton("Call Funcs", 20, 40, 60, 20)
GUISetState(@SW_SHOW, $hGUI)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nButton
			_MyFunc()
			_OtherFunc()
	EndSwitch
WEnd

Func _MyFunc()
	ConsoleWrite(ScriptCurrentFunc(@ScriptLineNumber) & @LF)
EndFunc

Func _OtherFunc()
	ConsoleWrite(ScriptCurrentFunc(@ScriptLineNumber) & @LF)
EndFunc

Func ScriptCurrentFunc($iLine)
	If @Compiled Then Return SetError(1, 0, '')
	
	Local $aRead = StringSplit(StringStripCR(FileRead(@ScriptFullPath)), @LF)
	Local $sFuncName = "", $sFncPttrn = '(?i)^\h*func\h+(\w+)\s*\(.*?\).*?$'
	
	For $i = 1 To $aRead[0]
		If StringRegExp($aRead[$i], $sFncPttrn) Then
			$sFuncName = StringRegExpReplace($aRead[$i], $sFncPttrn, '\1')
		EndIf
		
		If $i = $iLine Then
			If $sFuncName = "" Then SetError(1)
			Return $sFuncName
		EndIf
	Next
EndFunc
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Kaster,
А если так попробовать?
Код:
#include <GUIConstantsEx.au3>

Global $sCurrentFunc

$hGUI = GUICreate("ScriptCurrentFunc Demo", 300, 200)
$nButton = GUICtrlCreateButton("Call Funcs", 20, 40, 60, 20)
GUISetState(@SW_SHOW, $hGUI)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nButton
			_MyFunc()
			_OtherFunc()
			_NextFunc()
	EndSwitch
WEnd

Func _MyFunc()
	$sCurrentFunc = '_MyFunc'
	Local $i_Random = Random(0, 1, 1)
	ScriptCurrentFunc($i_Random)
EndFunc   ;==>_MyFunc

Func _OtherFunc()
	$sCurrentFunc = '_OtherFunc'
	Local $i_Random = Random(0, 1, 1)
	ScriptCurrentFunc($i_Random)
EndFunc   ;==>_OtherFunc

Func _NextFunc()
	$sCurrentFunc = '_NextFunc'
	Local $i_Random = Random(0, 1, 1)
	ScriptCurrentFunc($i_Random)
EndFunc   ;==>_NextFunc

Func ScriptCurrentFunc($i_Error = 0)
	Local $s_Message = 'Success'
	If $i_Error Then $s_Message = 'Error'
	$s_Message = $sCurrentFunc & ': ' & $s_Message
	$sCurrentFunc = ''
	ConsoleWrite($s_Message & @LF)
EndFunc   ;==>ScriptCurrentFunc
Если функций много, то, ИМХО, можно написать скрипт, который будет нумеровать функции и формировать массив $a_Func. Код поменял, см. ниже.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
madmasles [?]
можно написать скрипт, который будет нумеровать функции и формировать массив $a_Func.
Проще уже скриптом добавлять в каждую функцию название этой самой функций. Ну или присваивать глобальной переменной её имя, чтобы в любой момент можно было проверить имя последней вызванной функций, типа @LastFuncName :smile:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR [?]
Проще уже скриптом добавлять в каждую функцию название этой самой функций. Ну или присваивать глобальной переменной её имя, чтобы в любой момент можно было проверить имя последней вызванной функций, типа @LastFuncName
Согласен, так проще. :smile:
Код изменил.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
madmasles [?]
Я имел в виду запуск отдельного скрипта, который пройдётся по основному и подставит переменные с именем функций.
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
madmasles
не, второй скрипт для такой простой задачи не вариант. пока ручками подобавляю. с глобальной переменной придется поработать, потому что в том варианте что у тебя, если вызвать ScriptCurrentFunc в главном скрипте, то он покажет последнюю выполненную функцию, а надо чтобы показывал Main. ну и конечно возьму на вооружение скрипт от Creator'a. даже не знаю, почему сам не подумал пошерстить текст скрипта регвыром :smile:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Kaster [?]
если вызвать ScriptCurrentFunc в главном скрипте, то он покажет последнюю выполненную функцию, а надо чтобы показывал Main
Почему? Переменная обнуляется в функции, добавьте возврат строки Main, если $sCurrentFunc пустая.
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
madmasles
а точно, не заметил. пардон муа :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Kaster [?]
пока ручками подобавляю
Вот попробуй это:

Код:
#include <GUIConstantsEx.au3>

SetCurrentFuncName()
Global $sCurrentFuncName = ""

$hGUI = GUICreate("SetCurrentFuncName Demo", 300, 200)
$nButton = GUICtrlCreateButton("Call Funcs", 20, 40, 60, 20)
GUISetState(@SW_SHOW, $hGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $nButton
            _MyFunc()
            _OtherFunc()
            _NextFunc()
    EndSwitch
WEnd

Func _MyFunc()
	
	MsgBox(64, 'FuncName', $sCurrentFuncName)
EndFunc

Func _OtherFunc()
	
	MsgBox(64, 'FuncName', $sCurrentFuncName)
EndFunc

Func _NextFunc()
	
	MsgBox(64, 'FuncName', $sCurrentFuncName)
EndFunc

Func SetCurrentFuncName()
	If @Compiled Or StringInStr($CmdLineRaw, '/Restarted') Then Return
	
	Local $sRead = FileRead(@ScriptFullPath)
	Local $aFuncs = StringRegExp($sRead, '(?i)\r?\n\h*func\h+(\w+)\h*\(.*?\)\r?\n', 3)
	
	$sRead = StringRegExpReplace($sRead, '(\r?\n?\t*SetCurrentFuncName\(\)\r?\n)(?:\t*Global \$sCurrentFuncName = ""\r?\n?)?', '\1Global $sCurrentFuncName = ""' & @CRLF, 1)
	
	For $i = 0 To UBound($aFuncs)-1
		If $aFuncs[$i] = "SetCurrentFuncName" Then
			ContinueLoop
		EndIf
		
		$sRead = StringRegExpReplace($sRead, _
			'(?i)(\r?\n\h*func\h+' & $aFuncs[$i] & '\h*\(.*\)\r?\n)\t*(?:\$sCurrentFuncName = "' & $aFuncs[$i] & '"|(.*?))\r?\n', _
			'\1' & @TAB & '$sCurrentFuncName = "' & $aFuncs[$i] & '"' & @CRLF & '\2')
	Next
	
	$hFile = FileOpen(@ScriptFullPath, 2)
	FileWrite($hFile, $sRead)
	FileClose($hFile)
	
	ShellExecute(@ScriptFullPath, $CmdLineRaw & ' /Restarted', @ScriptDir)
	Exit
EndFunc


SetCurrentFuncName, одноимённая функция и глобальная переменная должны быть определены заранее (хотя переменную можно и не писать, она будет добавлена, но тогда нужно будет продолжить выполнение скрипта при выводе сообщения об ошибке от wrapper'а).
При первом запуске скрипт сам в себя добавит переменную $sCurrentFuncName в каждую функцию и присвоит ей имя этой функций, затем перезапустится уже с новыми изменениями.

Поэтому перед компиляцией, данный скрипт должен быть выполнен хотя бы один раз :smile:
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
CreatoR
ок. спасибо. попробую на других, будущих скриптах. тот, для которого это нужно было уже готов. мне не хочется его переделывать, там некий примитивный обработчик уже приделан руками.
 
Верх