--[[ Debug current au3-variable, by @BugFix • Recognizes all syntactically allowed forms of variables in au3 scripts (also nested and with functions inside) • Resolve internal references in the description text for most syntax variants • Non-resolvable syntax variants can be output as "raw" via call parameter • Output: Variable only, Variable + Error, Variable + Error + Extended, Variable + Extended • Any output type can be combined with the "raw" parameter • All settings are made in the shortcut definition in "SciTEUser.properties". example: command.name.38.$(au3)=DebugAU3 + Err + Ext command.mode.38.$(au3)=subsystem:lua,savebefore:no command.38.$(au3)=dostring do props['debug.err.au3'] = 'err_ext' props['debug.err.au3.raw'] = '0' dofile(props["Lua.User.Scripts.Path"]..'/DebugAU3.lua') end command.shortcut.38.$(au3)=Alt+KeypadMinus props["Lua.User.Scripts.Path"] --> this is my private path property for lua scripts replace this with your storage path, i.e. "C:\\users\\MICKYMOUSE\\scripts\\DebugAU3.lua" Debug type: props['debug.err.au3'] = '' (var only), or ('err' var+err, 'ext' var+ext, 'err_ext' var+err+ext) Debug text mode: props['debug.err.au3.raw'] = '0' or ('1' = 'raw') ]] --[[ Samples, partly very specific ;=p • $varXYZ ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '$varXYZ' & ' --> ' & $varXYZ & @CRLF) • $var[$i] ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '$var[' & $i & ']' & ' --> ' & $var[$i] & @CRLF) • $var[$i][$j] ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '$var[' & $i & '][' & $j & ']' & ' --> ' & $var[$i][$j] & @CRLF) • $ar[0][1] ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '$ar[' & 0 & '][' & 1 & ']' & ' --> ' & $ar[0][1] & @CRLF) • ($var[$i][$j])[$f][$g][$h] ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '(' & $var[$i][$j] & ')[' & $f & '][' & $g & '][' & $h & ']' & ' --> ' & ($var[$i][$j])[$f][$g][$h] & @CRLF) • ($var[$i][$j]).mu.ma ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '(' & $var[$i][$j] & ').mu.ma' & ' --> ' & ($var[$i][$j]).mu.ma & @CRLF) • ($var[$i][$j][$k][($l-15)^2][6*3]).mama.mia ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '(' & $var[$i][$j][$k][($l-15)^2][6*3] & ').mama.mia' & ' --> ' & ($var[$i][$j][$k][($l-15)^2][6*3]).mama.mia & @CRLF) • $ar[_getIndex1($i)][_getIndex2($j)] ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '$ar[' & _getIndex1($i) & '][' & _getIndex2($j) & ']' & ' --> ' & $ar[_getIndex1($i)][_getIndex2($j)] & @CRLF) • $tRectDraw.Bottom ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '$tRectDraw.Bottom' & ' --> ' & $tRectDraw.Bottom & @CRLF) • $gm["Index"] ConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '$gm[' & "Index" & ']' & ' --> ' & $gm["Index"] & @CRLF) with the parameter 'err' is added: & "!@ " & @TAB & "#Error: " & @error & @CRLF) 'err_ext' is added: & "!@ " & @TAB & "#Error: " & @error & @TAB & "#Extended: " & @extended & @CRLF) 'ext' is added: & "!@ " & @TAB & "#Extended: " & @extended & @CRLF) Howto use: Place the cursor in the variable's base name or in front of the "$" and press the key combination. If the variable is the first in the line, you can set the cursor to any position before it. If the variable is the last one in the line, you can set the cursor to any position after it. If the first part of the variable is enclosed in round brackets, an attempt is made to resolve the entire part as one value. ]] local debugAU3 = { caret = nil, sline = nil, iline = nil, pstart = nil, pend = nil, svar = "$", compareStr = function(self, _t, _v) for _, v in pairs(_t) do if v == _v then return true end end return false end, searchStartLeft = function(self) if editor.CharAt[self.caret] == 36 then return self.caret end while (editor.CharAt[editor.CurrentPos]) ~= 36 do editor:CharLeft() if (editor.CurrentPos == 0) or (editor:LineFromPosition(editor.CurrentPos) < self.iline) then -- no match to the left of the cursor (now at editor position '0' or in the previous line) -- search on the right side return self:searchStartRight() end end return editor.CurrentPos end, searchStartRight = function(self) -- back to start position and search on the right side for the first "$" editor.CurrentPos = self.caret repeat editor:CharRight() until editor.CharAt[editor.CurrentPos] == 36 return editor.CurrentPos end, searchVar = function(self) self.caret = editor.CurrentPos self.iline = editor:LineFromPosition(self.caret) self.sline = editor:GetCurLine() if not self.sline:find("%$") then return nil end -- the line does not contain a variable self.pstart = self:searchStartLeft() local chrnext local function nextCharLineEnd() if editor:PositionAfter(editor.CurrentPos) == editor.LineEndPosition[self.iline] then return true else return false end end local function grabArray(_addcurrent) if string.char(editor.CharAt[editor:PositionAfter(editor.CurrentPos)]) ~= '[' then return nil end if _addcurrent ~= nil then self.svar = self.svar..string.char(editor.CharAt[editor.CurrentPos]) end local count, slast = 0, '' repeat editor:CharRight() chrnext = string.char(editor.CharAt[editor.CurrentPos]) if chrnext == '[' then count = count +1 elseif chrnext == ']' then if slast == '[' then self.pend = self.pend -1 self.svar = self.svar:sub(1,(self.svar:len()-1)) break end count = count -1 end slast = chrnext self.svar = self.svar..chrnext self.pend = editor.CurrentPos if nextCharLineEnd() == true then break end until (count == 0) and (string.char(editor.CharAt[editor:PositionAfter(editor.CurrentPos)]) ~= '[') return true end local function grabDotNotation(_addcurrent) if string.char(editor.CharAt[editor:PositionAfter(editor.CurrentPos)]) ~= '.' then return nil end if nextCharLineEnd() == true then return nil end if _addcurrent ~= nil then self.svar = self.svar..string.char(editor.CharAt[editor.CurrentPos]) end while editor:PositionAfter(editor.CurrentPos) ~= editor.CurrentPos do editor:CharRight() chrnext = string.char(editor.CharAt[editor.CurrentPos]) if chrnext:find('[%._%w]') then self.svar = self.svar..chrnext self.pend = editor.CurrentPos else editor:CharLeft() self.pend = self.pend -1 break end end return true end local function grabRoundBraces() if string.char(editor.CharAt[editor:PositionAfter(editor.CurrentPos)]) ~= ')' then return nil end if nextCharLineEnd() == true then return nil end if (nextCharLineEnd() == false) and (editor:PositionFromLine(self.iline) < self.pstart) then if (string.char(editor.CharAt[editor:PositionBefore(self.pstart)]) == '(') and (string.char(editor.CharAt[editor:PositionAfter(editor.CurrentPos)]) == ')') then editor:CharRight() -- goto ')' if (grabDotNotation(true) ~= nil) or (grabArray(true) ~= nil) then self.svar = '('..self.svar end end end return true end -- base name: $var while editor:PositionAfter(editor.CurrentPos) ~= editor.CurrentPos do chrnext = editor:PositionAfter(editor.CurrentPos) if string.char(editor.CharAt[chrnext]):find('[_%w]') then editor:CharRight() self.svar = self.svar..string.char(editor.CharAt[editor.CurrentPos]) else -- caret now before the last char from variable name self.pend = editor.CurrentPos break end end -- base name and possible dot notation: $var.abc grabDotNotation() -- base name and possible dot notation and following possible dot notation or array index -- ($var.abc).def ($var.abc)[$i][$j][$k] grabRoundBraces() -- follows: space, comma, line end or a operator --> the variable is complete chrnext = string.char(editor.CharAt[editor:PositionAfter(self.pend)]) if self:compareStr({' ','+','-','*','/','^',',','\r','\n'}, chrnext) then return true end -- grabs the array, if any, in arbitrary dimensions if chrnext == '[' then -- each pair "[..]" will added grabArray() -- checks for possible following dot notation and add grabDotNotation() end -- if result in round braces and -- dot notation and/or array indices was found (also nested) -- example ("|" is the caret position): -- $f4 = ($array[((($va|r1).abc).def).ghi)][$y][$z][$var2][$var3]).prop -- found: ((($var1).abc).def).ghi -- $f4 = ($array[((($va|r1).abc).def).ghi)][$y][$z][$var2][$var3]).prop -- found: ($array[((($var1).abc).def).ghi)][$y][$z][$var2][$var3]).prop while true do if grabRoundBraces() == nil then break end end return true end, writeDebugLine = function(self) local function separateIndices(_s, _fromstart) local ret = '' local s, e, l = _s:find('%b[]') if s == nil then return _s end if _fromstart == true then ret = _s:sub(1, s -1) end repeat l = e if s > l +1 then ret = ret.._s:sub(l +1, s -1) end ret = ret.."[' & ".._s:sub(s +1, e -1).." & ']" s, e = _s:find('%b[]', l) until s == nil if e ~= nil and e < _s:len() then ret = ret.._s:sub(e +1) end return ret end if self:searchVar() == nil then print("!> No or no valid variable found in line ["..(self.iline +1).."].") else local swrite, out, serr = self.svar, '', '' if props['debug.err.au3'] == 'err' then serr = ' & "!@ " & @TAB & "#Error: " & @error & @CRLF' elseif props['debug.err.au3'] == 'err_ext' then serr = ' & "!@ " & @TAB & "#Error: " & @error & @TAB & "#Extended: " & @extended & @CRLF' elseif props['debug.err.au3'] == 'ext' then serr = ' & "!@ " & @TAB & "#Extended: " & @extended & @CRLF' end -- for very special variables use raw mode (debug.err.au3.raw=1) if props['debug.err.au3.raw'] == '0' then -- if starts with "(" --> execute the code between the balanced "()" local n, open, close, cl_last = 0, swrite:find('%b()') if open ~= nil and open == 1 then repeat cl_last = close n = n +1 if n == 1 then out = out.."(' & "..swrite:sub(open +1, close -1).." & ')" end open, close = swrite:find('%b()', cl_last) if open ~= nil then out = out..separateIndices(swrite:sub(cl_last +1, open -1)) else out = out..separateIndices(swrite:sub(cl_last +1)) end until open == nil else out = separateIndices(self.svar, true) end end out = "\nConsoleWrite('@@_Debug_line' & @TAB & @TAB & @ScriptLineNumber & ' var: ' & '"..out.."' & ' --> ' & "..self.svar.." & @CRLF"..serr..")" editor:LineEnd() editor:InsertText(editor.CurrentPos, out) editor.CurrentPos = self.caret editor:SetSel(self.caret, self.caret) end end } debugAU3:writeDebugLine()