Ticket #3024: AutoItTools.lua

File AutoItTools.lua, 56.6 KB (added by anonymous, 6 years ago)
Line 
1--------------------------------------------------------------------------------
2-- This library contains tools specific to AutoIt.
3--
4-- NOTE: Names in parenthesis indicate which tool a function or lines of code
5-- belong to.  The tools are not listed by function name, merely feature name.
6--
7-- Current tools:
8--      UserList - Invoke FunctionList() to display a user list of all functions
9--      in the active file.
10--------------------------------------------------------------------------------
11AutoItTools = EventClass:new(Common)
12
13--------------------------------------------------------------------------------
14-- OnStartup()
15--
16-- Initializes variables.
17--------------------------------------------------------------------------------
18function AutoItTools:OnStartup()
19        -- The pattern to search for.  This pattern is applied across the entire
20        -- document.  The empty capture at the beginning returns the position,
21        -- useful for getting the line number.
22        -- NOTE: This will not match a function on the first line of the file
23        -- unless it has whitespace before it.
24        self.Pattern = "()[%s][Ff][Uu][Nn][Cc][%s]+([%w%s_]*%(.-%))"
25
26        -- The list seperator. (UserList)
27        self.Seperator = ";"
28        self.SeperatorByte = self.Seperator:byte()
29        -- The unique ID identifying our user list. (UserList)
30        self.ID = 12
31        -- Specifies the marker type to use (default: Bookmark).
32        self.Marker = 1
33        -- A table where the keys are the function strings and the values are the
34        -- line where the string is found. (UserList)
35        self.DataTable = { }
36
37        --Load keywords table used by propercase
38        f = io.open(props['SciteDefaultHome'].."\\api\\au3.api")
39        if f ~= nil then
40                self.ProperWords = f:read('*a')
41                f:close()
42                -- remove the ?x at the end of the lines of each keyword record
43                self.ProperWords = string.gsub(self.ProperWords,"\?%d","")
44                self.l_ProperWords = string.lower(self.ProperWords)
45        else
46                self.ProperWords = ""
47        end
48        -- Check for Beta and set the BETA_AUTOIT= in au3.properties to the correct value
49        f = io.open(props['SciteDefaultHome'].."\\..\\beta\\au3check.dat")
50        if f ~= nil then
51                -- Beta Exists
52                f:close()
53                for cmd  = 0, 50, 1 do
54                        if props['command.'..cmd..'.beta'] ~= '' then
55                                props['command.name.'..cmd..'.$(au3)']=props['command.'..cmd..'.beta']
56--~                             print('beta command.name.'..cmd..'.$(au3)=' .. props['command.name.'..cmd..'.$(au3)'])
57                        end
58                end
59
60--~             print("Beta exists.")
61        else
62                for cmd  = 0, 50, 1 do
63                        if props['command.'..cmd..'.beta'] ~= '' then
64                                props['command.name.'..cmd..'.$(au3)']=''
65--~                             print('no Beta command.name.'..cmd..'.$(au3)=' .. props['command.name.'..cmd..'.$(au3)'])
66                        end
67                end
68--~             print("Beta missing.")
69        end
70end     -- OnStartup()
71
72--------------------------------------------------------------------------------
73-- FunctionList()
74--
75-- Iterates over the document building a list of functions and displaying them
76-- in a user list.
77--
78-- Tool: AutoItTools.FunctionsList $(au3) savebefore:no Ctrl+L List Functions
79--------------------------------------------------------------------------------
80function AutoItTools:FunctionsList()
81        -- Local table used to build the list of strings.
82        local data = { }
83        -- Process the entire document at once.
84        local doc = "\n" .. editor:GetText()
85        for pos, str in doc:gmatch(self.Pattern) do
86                -- If we have a multi-line function definition, show it all on one line.
87                str = str:gsub("[\r\n]*", "")
88                -- Insert the string into both tables.
89                table.insert(data, str)
90                self.DataTable[str] = editor:LineFromPosition(pos)
91        end
92        -- Sort the table and build a string out of it.
93        table.sort(data, function(a, b) return string.lower(a) < string.lower(b) end)
94        local list = table.concat(data, self.Seperator)
95        -- Store the seperator, set our new one, show the list and restore the
96        -- original seperator.
97        local old_seperator = editor.AutoCSeparator
98        editor.AutoCSeparator = self.SeperatorByte
99        editor:ScrollCaret()
100        editor:UserListShow(self.ID, list)
101        editor.AutoCSeparator = old_seperator
102end     -- FunctionsList
103
104--------------------------------------------------------------------------------
105-- OnUserListSelection(id, str)
106--
107-- Marks the current line and jumps to the line containing the selected
108-- function.
109--
110-- Parameters:
111--      id - The ID of the event to make sure it is ours.
112--      str - The selected item.
113--
114-- Returns:
115--      The value true if the event was for us.
116--------------------------------------------------------------------------------
117function AutoItTools:OnUserListSelection(id, str)
118        if id == self.ID then
119                -- Look up the line we jump to using the string as the table key.
120                local line = self.DataTable[str]
121                if line then
122                        -- Clear our marker and set a new one.
123                        editor:MarkerDeleteAll(self.Marker)
124                        editor:MarkerAdd(editor:LineFromPosition(editor.CurrentPos), self.Marker)
125                        editor:GotoLine(line)
126                        editor:EnsureVisible(line)
127                end
128                return true
129        end
130end     -- OnUserListSelection()
131
132--------------------------------------------------------------------------------
133-- InsertRegion()
134--
135-- Inserts #Region...#EndRegion around the selected text.
136--
137-- Tool: AutoItTools.InsertRegion $(au3) savebefore:no,groupundo:yes Ctrl+Alt+R Insert Region
138--------------------------------------------------------------------------------
139function AutoItTools:InsertRegion()
140        local nl = self:NewLineInUse()
141        local word = self:GetWord()
142        local name = word:match("Func ([%w_]*)")
143        if name == nil then
144                name = ""
145        else
146                name = name .. "()"
147        end
148        pos = editor.SelectionStart
149        editor:ReplaceSel("#Region " .. name .. nl .. word .. nl .. "#EndRegion " .. name)
150        editor:SetSel(pos, pos)
151end     -- InsertRegion()
152
153--------------------------------------------------------------------------------
154-- DebugMsgBoxAdd()
155--
156-- Add debug MsgBox to the selected text (original by Jos van der Zande).
157--
158-- Tool: AutoItTools.DebugMsgBoxAdd $(au3) savebefore:no,groupundo:yes Alt+D Debug: Add MsgBox
159--------------------------------------------------------------------------------
160function AutoItTools:DebugMsgBoxAdd()
161        local word = self:GetWord2()
162        if word == "" then
163                print("Cursor not on any text.")
164                return
165        end
166        local word = word:gsub("\r", "")     -- remove CR
167        local word = word:gsub("\n", "")     -- remove LF
168        local word2 = word:gsub("'", "''")     -- replace quote by 2 quotes
169        local line = editor:LineFromPosition(editor.CurrentPos) + 1
170        editor:LineEnd()
171        editor:NewLine()
172--~     editor:AddText("MsgBox(262144,'debug line ~" .. line .. "' , \'" .. word2 .. "\:' & @CRLF & " .. word .. ") ;### Debug MSGBOX" )
173    local option = tonumber(props['debug.msgbox.option'])
174    if option == 2 then
175        editor:AddText("SetError(@Error, @Extended, MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @LF & \'" .. word2 .. "\' & @LF & @LF & 'Return:' & @LF & " .. word .. " & @LF & @LF & '@Error:' & @LF & @Error & @LF & @LF & '@Extended:' & @lf & @Extended)) ;### Debug MSGBOX" )
176    elseif option == 1 then
177        editor:AddText("SetError(@Error, @Extended, MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @LF & \'" .. word2 .. "\' & @LF & @LF & 'Return:' & @LF & " .. word .. " & @LF & @LF & '@Error:' & @LF & @Error)) ;### Debug MSGBOX" )
178    elseif option == 0 then
179        editor:AddText("SetError(@Error, @Extended, MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @LF & \'" .. word2 .. "\' & @LF & @LF & 'Return:' & @LF & " .. word .. ")) ;### Debug MSGBOX" )
180    elseif option == -1 then
181        editor:AddText("SetError(@Error, @Extended, MsgBox(262144,'debug line ~' & @ScriptLineNumber, \'" .. word2 .. "\:' & @LF & " .. word .. ")) ;### Debug MSGBOX" )
182        end
183        editor:LineDown()
184        editor:Home()
185end     -- DebugMsgBoxAdd()
186
187--------------------------------------------------------------------------------
188-- DebugConsoleWriteAdd()
189--
190-- Add debug ConsoleWrite to the selected text (original by Jos van der Zande).
191--
192-- Tool: AutoItTools.DebugConsoleWriteAdd $(au3) savebefore:no,groupundo:yes Ctrl+D Debug: Add ConsoleWrite
193--------------------------------------------------------------------------------
194function AutoItTools:DebugConsoleWriteAdd()
195        local word = self:GetWord2()
196        if word == "" then
197                print("Cursor not on any text.")
198                return
199        end
200        local word = word:gsub("\r", "")     -- replace quote by 2 quotes
201        local word = word:gsub("\n", "")     -- replace quote by 2 quotes
202        local word2 = word:gsub("'", "''")     -- replace quote by 2 quotes
203        local line = editor:LineFromPosition(editor.CurrentPos) + 1
204        editor:LineEnd()
205        editor:NewLine()
206--~     editor:AddText("ConsoleWrite('@@ (" .. line .. ") :(' & @min & ':' & @sec & ') " .. word2 .. " = ' & " .. word .. " & @CRLF) ;### Debug Console")
207        local option = tonumber(props['debug.console.option'])
208        if option == 3 then
209        editor:AddText("SetError(@Error, @Extended, ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : " .. word2 .. " = ' & " .. word .. " & @CRLF & '>Error code: ' & @Error & '    Extended code: ' & @Extended & '    SystemTime: ' & @HOUR & ':' & @MIN & ':' & @SEC & @CRLF)) ;### Debug Console" )
210    elseif option == 2 then
211        editor:AddText("SetError(@Error, @Extended, ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : " .. word2 .. " = ' & " .. word .. " & @CRLF & '>Error code: ' & @Error & '    Extended code: ' & @Extended & @CRLF)) ;### Debug Console" )
212    elseif option == 1 then
213        editor:AddText("SetError(@Error, @Extended, ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : " .. word2 .. " = ' & " .. word .. " & @CRLF & '>Error code: ' & @Error & @CRLF)) ;### Debug Console" )
214    elseif option == 0 then
215        editor:AddText("SetError(@Error, @Extended, ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : " .. word2 .. " = ' & " .. word .. " & @CRLF)) ;### Debug Console" )
216    elseif option == -1 then
217        editor:AddText("SetError(@Error, @Extended, ConsoleWrite('@@ (' & @ScriptLineNumber & ') :(' & @MIN & ':' & @SEC & ') " .. word2 .. " = ' & " .. word .. " & @CRLF)) ;### Debug Console" )
218    elseif option == -2 then
219--      editor:AddText("SetError(@Error, @Extended, ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') Error: ' & @error & ' Ext: ' & @extended & '  ; " .. word2 .. " = ' & " .. word .. " & @CRLF)) ;### Debug Console" )
220        editor:AddText("SetError(@Error, @Extended, ConsoleWrite(StringFormat('@@ Debug(%4d) Error: %3d Ext: %8d', @ScriptLineNumber, @error ,@extended) & '  ; " .. word2 .. " = ' & " .. word .. " & @CRLF)) ;### Debug Console" )
221    end
222        editor:LineDown()
223        editor:Home()
224end     -- DebugConsoleWriteAdd()
225
226--------------------------------------------------------------------------------
227-- OldCodeMark()
228--
229-- Comments out the selected text and names the section "Old Code".
230--
231-- Tool: AutoItTools.OldCodeMark $(au3) savebefore:no,groupundo:yes Alt+M Mark Old Code
232--------------------------------------------------------------------------------
233function AutoItTools:OldCodeMark()
234        local word = self:GetWord()
235        if word ~= "" then
236                editor:ReplaceSel("#cs Old Code")
237                editor:NewLine()
238                editor:AddText(word)
239                editor:NewLine()
240                editor:AddText("#ce Old Code")
241        end
242end     -- OldCodeMark()
243
244--------------------------------------------------------------------------------
245-- OldCodeGoto()
246--
247-- Jumps to the first line of old code in the document.
248--
249-- Tool: AutoItTools.OldCodeGoto $(au3) savebefore:no Alt+N Goto Old Code
250--------------------------------------------------------------------------------
251function AutoItTools:OldCodeGoto()
252        local doc = editor:GetText()
253        local pos = doc:find("#cs Old Code")
254        if pos then
255                editor:GotoLine(editor:LineFromPosition(pos))
256        else
257                print("No Old Code sections found.")
258        end
259end -- OldCodeGoto()
260
261--------------------------------------------------------------------------------
262-- CreateFunctionHeader(s, p)
263--
264-- Creates a function header for an AutoIt 3 function.
265--
266-- Parameters:
267--  s - The name of a function.
268--  p - The parameters to the function.
269--
270-- Returns:
271--  A string containing the function header.
272--------------------------------------------------------------------------------
273function AutoItTools:CreateFunctionHeader(s, p)
274    -- Change these :)
275    local defAuthor = props['UDFCreator']    -- Initial Author value
276    local defLineMax = 129                   -- Max length of line. AutoIt standard is 129.
277    local defSplit = 21                      -- Default index for '-' after param.
278
279    local nl = self:NewLineInUse()
280
281    local outStart   = "FUNCTION"
282    local outName    = s
283    local outDesc    = ""
284    local outSyntax  = ""
285    local outParams  = ""
286    local outReturn  = "None"
287    local outAuthor  = defAuthor
288    local outModify  = ""
289    local outRemarks = ""
290    local outRelated = ""
291    local outLink    = ""
292    local outExample = "No"
293
294    local name = s
295    local params = p
296
297    if name:sub(0, 2) == "__" then
298        outStart = "INTERNAL_USE_ONLY"
299    end
300
301    outSyntax = name .. "("
302
303    local paramSynt = ""
304    local iOptionals = 0
305    local fBroken = false
306    local sModifiers = ""
307    if params ~= "" and params ~= nil then
308        for byref, parameter, optional in string.gfind(params, "(%w-%s*%w*)%s*($[%w_]+)%s*[=]?%s*(.-)[,%)]") do
309            if parameter ~= "" and parameter ~= nil then
310                if outParams ~= "" then
311                    outParams = outParams .. nl .. ";" .. string.rep(" ", 18)
312                end
313
314                outParams = outParams .. parameter .. string.rep(" ", defSplit - string.len(parameter)) .. "- "
315
316                sModifiers = ""
317                if optional ~= "" and optional ~= nil then
318                    outParams = outParams .. "[optional] "
319
320                    if paramSynt ~= "" then
321                        paramSynt = paramSynt .. "[, "
322                    else
323                        paramSynt = paramSynt .. "["
324                    end
325
326                    iOptionals = iOptionals + 1
327                else
328                    byref = string.gsub(byref:lower(), "%s", "")
329                    if byref ~= "" then
330                        if byref == "byref" then
331                            outParams = outParams .. "[in/out] "
332                            sModifiers = "Byref "
333                        else
334                            if byref == "const" then
335                                outParams = outParams .. "[const] "
336                                sModifiers = "Const "
337                            else
338                                if byref == "byrefconst" or byref == "constbyref" then
339                                    outParams = outParams .. "[in/out and const] "
340                                    sModifiers = "Const Byref "
341                                else
342                                    print("Unrecognised parameter modifiers: '" .. byref .. "'")
343                                end
344                            end
345                        end
346                    end
347
348                    if paramSynt ~= "" then
349                        paramSynt = paramSynt .. ", "
350                    end
351                end
352
353                if fBroken then
354                    if string.len(paramSynt) + string.len(parameter) + iOptionals + 2 + 19 > defLineMax then
355                        outSyntax = outSyntax .. paramSynt .. nl .. ";" .. string.rep(" ", 18)
356                        paramSynt = ""
357                        fBroken = true
358                    end
359                else
360                    if string.len(outSyntax) + string.len(paramSynt) + string.len(parameter) + iOptionals + 2 + 19 > defLineMax then
361                        outSyntax = outSyntax .. paramSynt .. nl .. ";" .. string.rep(" ", 18)
362                        paramSynt = ""
363                        fBroken = true
364                    end
365                end
366                paramSynt = paramSynt .. sModifiers .. parameter
367
368                if optional ~= "" and optional ~= nil then
369                    paramSynt = paramSynt .. " = " .. optional
370                end
371
372                local paramtype = parameter:sub(2, 2)
373                local isarray = false
374                if paramtype == "a" then
375                    paramtype = parameter:sub(3, 3)
376                    isarray = true
377                end
378
379                local sAdd
380                if paramtype == "i" then
381                    sAdd = "integer"
382                elseif parameter:sub(2, 3) == "fu" then
383                    sAdd = "function (first class object)"
384                elseif parameter:sub(2, 4) == "tag" then
385                    sAdd = "structures definition"
386                elseif paramtype == "f" then
387                    sAdd = "floating point"
388                elseif paramtype == "b" then
389                    sAdd = "boolean"
390                elseif paramtype == "d" then
391                    sAdd = "binary variant"
392                elseif paramtype == "n" then
393                    sAdd = "general number"
394                elseif paramtype == "s" then
395                    sAdd = "string"
396                elseif paramtype == "h" then
397                    sAdd = "handle"
398                elseif paramtype == "m" then
399                    sAdd = "map"
400                elseif paramtype == "v" then
401                    sAdd = "variant"
402                elseif paramtype == "o" then
403                    sAdd = "object"
404                elseif paramtype == "id" then
405                    sAdd = "AutoIt controlid"
406                elseif paramtype == "p" then
407                    sAdd = "pointer"
408                elseif paramtype == "t" then
409                    sAdd = "dll struct"
410                else
411                    sAdd = "unknown"
412                end
413
414                if isarray then
415                    outParams = outParams .. "an array of " .. sAdd .. "s."
416                else
417                    if sAdd == 'object' then
418                        outParams = outParams .. "an " .. sAdd .. "."
419                    elseif sAdd == 'map' then
420                        outParams = outParams .. "a " .. sAdd .. "."
421                    elseif sAdd == 'structures definition' then
422                        outParams = outParams .. "a " .. sAdd .. "."
423                    elseif sAdd == 'function (first class object)' then
424                        outParams = outParams .. "" .. sAdd .. "."
425
426                    else
427                        if sAdd:sub(1, 1):find("[AEIOUaeiou]") ~= nil then
428                            outParams = outParams .. "an " .. sAdd .. " value."
429                        else
430                            outParams = outParams .. "a " .. sAdd .. " value."
431                        end
432                    end
433                end
434
435                if optional ~= "" and optional ~= nil then
436                    outParams = outParams .. " Default is " .. optional .. "."
437                end
438            end
439        end
440    else
441        outParams = "None"
442    end
443
444    outSyntax = outSyntax .. paramSynt .. string.rep("]", iOptionals) .. ")"
445
446    local res = "; #" .. outStart .. "# " .. string.rep("=", defLineMax - 5 - outStart:len()) .. nl
447    res = res .. "; Name ..........: " .. outName .. nl
448    res = res .. "; Description ...: " .. outDesc .. nl
449    res = res .. "; Syntax ........: " .. outSyntax .. nl
450    res = res .. "; Parameters ....: " .. outParams .. nl
451    res = res .. "; Return values .: " .. outReturn .. nl
452    res = res .. "; Author ........: " .. outAuthor .. nl
453    res = res .. "; Modified ......: " .. outModify .. nl
454    res = res .. "; Remarks .......: " .. outRemarks .. nl
455    res = res .. "; Related .......: " .. outRelated .. nl
456    res = res .. "; Link ..........: " .. outLink .. nl
457    res = res .. "; Example .......: " .. outExample .. nl
458    res = res .. "; " .. string.rep("=", defLineMax - 2) .. nl
459
460    return res
461end -- CreateFunctionHeader()
462
463--------------------------------------------------------------------------------
464-- CreateStructureHeader(s, p)
465--
466-- Creates a structure header for an AutoIt 3 struct.
467--
468-- Parameters:
469--  s - The name of a structure.
470--  p - The complete structure definition.
471--
472-- Returns:
473--  A string containing the structure header.
474--------------------------------------------------------------------------------
475function AutoItTools:CreateStructureHeader(s, p)
476    local defAuthor = props['UDFCreator']    -- Initial Author value
477
478    local defLineMax = 129                   -- Max length of line. AutoIt standard is 129.
479    local defSplit = 21                      -- Default index for '-' after param.
480
481    local nl = self:NewLineInUse()
482
483    local outStart   = "STRUCTURE"
484    local outName    = s
485    local outDesc    = ""
486    local outFields  = ""
487    local outAuthor  = defAuthor
488    local outRemarks = ""
489    local outRelated = ""
490
491    local str
492    if p ~= "" and p ~= nil then
493        p = p:sub(p:find("[\"']"), -1)
494
495        for sect in string.gfind(p, "%s*(.-)%s*[;\"']") do
496
497            if sect:match("[Aa][Ll][Ii][Gg][Nn]%s+%d+") then
498                -- Align statement: Ignore
499            else
500                str = sect:match("^%s*&%s*$([%w_]+)%s&%s*$")
501                if str ~= nil then
502                    -- Substruct
503
504                    if outFields ~= "" then
505                        outFields = outFields .. nl .. ";" .. string.rep(" ", 18)
506                    end
507
508                    outFields = outFields .. str .. string.rep(" ", defSplit - string.len(str)) .. "- A $" .. str .. " structure."
509                else
510                    if sect == nil or sect == "" or sect:upper() == "STRUCT" or sect:upper() == "ENDSTRUCT" then
511                        -- Substruct or empty: Ignore
512                    else
513                        local datatype, name = sect:match("^(.-)%s+(.-)$")
514
515                        if outFields ~= "" then
516                            outFields = outFields .. nl .. ";" .. string.rep(" ", 18)
517                        end
518
519                        outFields = outFields .. name .. string.rep(" ", defSplit - string.len(name)) .. "- "
520
521                        if datatype:sub(1, 1):find("[AEIOUaeiou]") ~= nil then
522                            outFields = outFields .. "An "
523                        else
524                            outFields = outFields .. "A "
525                        end
526
527                        outFields = outFields .. datatype .. " value."
528                    end
529                end
530            end
531
532        end
533    end
534
535    local res = "; #" .. outStart .. "# " .. string.rep("=", defLineMax - 5 - outStart:len()) .. nl
536    res = res .. "; Name ..........: " .. outName .. nl
537    res = res .. "; Description ...: " .. outDesc .. nl
538    res = res .. "; Fields ........: " .. outFields .. nl
539    res = res .. "; Author ........: " .. outAuthor .. nl
540    res = res .. "; Remarks .......: " .. outRemarks .. nl
541    res = res .. "; Related .......: " .. outRelated .. nl
542    res = res .. "; Link ..........: " .. nl
543    res = res .. "; " .. string.rep("=", defLineMax - 2) .. nl
544    return res
545end -- CreateStructureHeader
546
547--------------------------------------------------------------------------------
548-- InsertFunctionHeader()
549--
550-- Generates a function header and inserts it into the document.
551--
552-- Tool: AutoItTools.InsertFunctionHeader $(au3) savebefore:no,groupundo:yes Alt+U Insert Function Header
553--------------------------------------------------------------------------------
554function AutoItTools:InsertFunctionHeader()
555    local line, pos = editor:GetCurLine()
556    local pos = editor.CurrentPos - pos
557    local lineNum = editor:LineFromPosition(pos)
558--~ local from, to, name = line:find("[Ff][Uu][Nn][Cc][%s]*([%w%s_]*)")
559    local from, to, name = line:find("[Ff][Uu][Nn][Cc]%s+([%w%s_]*)")
560    local struct = false
561
562    if to == nil then
563        from, to, name = line:find("[Gg][Ll][Oo][Bb][Aa][Ll]%s+[Cc][Oo][Nn][Ss][Tt]%s+($[%w_]+)")
564        struct = true
565        if to == nil then
566            print("Function or struct definition not found, unable to insert header.")
567            return
568        end
569    end
570
571    -- remove comments from the line
572    from, to =  line:find(";")
573    while from ~= nil do
574        -- print(pos+from .. " type:" .. editor.StyleAt[pos+from])
575        if editor.StyleAt[pos+from] == SCE_AU3_COMMENT then
576            line = string.sub (line, 1 , from-1)   -- remove comment
577            from = nil                             -- exit loop
578        else
579            from, to =  line:find(";",from+1)      -- find next ; as this one is not a comment
580        end
581    end
582    -- print(" line:" .. line)
583    local pfrom, pto = line:find("%(")    -- check for opening parenthesis
584    if struct then
585        pfrom, pto = line:find("[\"']")
586    end
587
588    if pto ~= nil then
589        local i = 0
590        local tmp
591        while line:find("%s+_%s*$") do    -- found a line continuation
592            line = line:gsub("%s+_%s*$", "")    -- remove it
593            i = i + 1
594            pos = editor:PositionFromLine(lineNum+i)    -- set new position
595            tmp = editor:GetLine(lineNum+i)
596            -- remove comments from the line
597            from, to =  tmp:find(";")
598            while from ~= nil do
599                -- print(pos+from .. " type:" .. editor.StyleAt[pos+from])
600                if editor.StyleAt[pos+from] == SCE_AU3_COMMENT then
601                    tmp = string.sub (tmp, 1 , from-1)   -- remove comment
602                    from = nil                             -- exit loop
603                else
604                    from, to =  tmp:find(";",from+1)      -- find next ; as this one is not a comment
605                end
606            end
607            tmp = tmp:gsub("^%s*", "")    -- remove leading white space
608            line = line .. tmp
609        end
610        editor:Home()
611        line = line:gsub("[\r\n]", "")    -- remove line breaks
612        line = line:gsub("[\"']%s*&%s*[\"']", "") -- remove string joins
613        if name:sub(1, 1) == "$" then
614            editor:AddText(self:CreateStructureHeader(name, line))
615        else
616            editor:AddText(self:CreateFunctionHeader(name, line))
617        end
618    else
619        print("Argument list not found, unable to insert header.")
620        end
621end -- InsertFunctionHeader()
622--------------------------------------------------------------------------------
623-- ConsoleWritePattern(with_comment)
624--
625-- Returns the pattern used to find DebugConsoleWrite statements.  This must be
626-- a function so NewLineInUse() can be called on the correct document.
627--
628-- Paramters:
629--      with_comment - If true, returns the pattern with a leading comment.
630--
631-- Returns:
632--      The pattern used to find DebugConsoleWrite statements.
633--------------------------------------------------------------------------------
634function AutoItTools:ConsoleWritePattern(with_comment)
635        local nl = self:NewLineInUse()
636        if with_comment then
637                return nl .. "[%s]*;[%s]*(SetError%([^" .. nl .. "]-%) ;### Debug[^" .. nl .. "]+)"
638        else
639                return nl .. "[%s]*(SetError%([^" .. nl .. "]-%) ;### Debug[^" .. nl .. "]+)"
640        end
641end     -- ConsoleWritePattern()
642
643--------------------------------------------------------------------------------
644-- MsgBoxPattern(with_comment)
645--
646-- Returns the pattern used to find DebugMsgBox statements.  This must be
647-- a function so NewLineInUse() can be called on the correct document.
648--
649-- Paramters:
650--      with_comment - If true, returns the pattern with a leading comment.
651--
652-- Returns:
653--      The pattern used to find DebugMsgBox statements.
654--------------------------------------------------------------------------------
655function AutoItTools:MsgBoxPattern(with_comment)
656        local nl = self:NewLineInUse()
657        if with_comment then
658                return nl .. "[%s]*;[%s]*(SetError%([^" .. nl .. "]-%) ;### Debug[^" .. nl .. "]+)"
659        else
660                return nl .. "[%s]*(SetError%([^" .. nl .. "]-%) ;### Debug[^" .. nl .. "]+)"
661        end
662end     -- MsgBoxPattern()
663
664--------------------------------------------------------------------------------
665-- DebugComment()
666--
667-- Comment all Debug lines.
668--
669-- Tool: AutoItTools.DebugComment $(au3) savebefore:no,groupundo:yes Ctrl+Shift+D Debug: Comment all lines
670--------------------------------------------------------------------------------
671function AutoItTools:DebugComment()
672        -- Callback function.
673        local function pat_match(m1)
674                return self:NewLineInUse() .. ";\t" .. m1
675        end
676        -- Perform replacement.
677        self:ReplaceDocByPattern(self:ConsoleWritePattern(), pat_match)
678        self:ReplaceDocByPattern(self:MsgBoxPattern(), pat_match)
679end     -- DebugComment()
680
681--------------------------------------------------------------------------------
682-- DebugUncomment()
683--
684-- Uncomment all Debug lines.
685--
686-- Tool: AutoItTools.DebugUncomment $(au3) savebefore:no,groupundo:yes Ctrl+Alt+D Debug: Uncomment all lines
687--------------------------------------------------------------------------------
688function AutoItTools:DebugUncomment()
689        -- Callback function.
690        local function pat_match(m1)
691                return self:NewLineInUse() .. m1
692        end
693        -- Perform replacement.
694        self:ReplaceDocByPattern(self:ConsoleWritePattern(true), pat_match)
695        self:ReplaceDocByPattern(self:MsgBoxPattern(true), pat_match)
696end     -- DebugUncomment()
697
698--------------------------------------------------------------------------------
699-- DebugRemove()
700--
701-- Remove all Debug MsgBox/Console lines.
702--
703-- Tool: AutoItTools.DebugRemove $(au3) savebefore:no,groupundo:yes Ctrl+Alt+Shift+D Debug: Remove all lines
704--------------------------------------------------------------------------------
705function AutoItTools:DebugRemove()
706        -- Callback function.
707        local function pat_match()
708                return ""
709        end
710        -- Remove any commented functions first
711        self:DebugUncomment()
712        -- Perform replacement.
713        self:ReplaceDocByPattern(self:ConsoleWritePattern(), pat_match)
714        self:ReplaceDocByPattern(self:MsgBoxPattern(), pat_match)
715end     -- DebugRemove()
716--------------------------------------------------------------------------------
717-- FunctionTracePattern(with_comment)
718--
719-- Returns the pattern used to find FunctionTrace statements.  This must be
720-- a function so NewLineInUse() can be called on the correct document.
721--
722-- Paramters:
723--      with_comment - If true, returns the pattern with a leading comment.
724--
725-- Returns:
726--      The pattern used to find FunctionTrace statements.
727--------------------------------------------------------------------------------
728function AutoItTools:FunctionTracePattern(with_comment)
729        local nl = self:NewLineInUse()
730        if with_comment then
731                return nl .. "[%s]*;[%s]*(ConsoleWrite%([^" .. nl .. "]-%)[%s]*;### Function Trace[^" .. nl .. "]?)"
732        else
733                return nl .. "[%s]*(ConsoleWrite%([^" .. nl .. "]-%)[%s]*;### Function Trace[^" .. nl .. "]?)"
734        end
735end     -- FunctionTracePattern()
736
737--------------------------------------------------------------------------------
738-- FunctionTraceAdd()
739--
740-- Inserts a ConsoleWrite() for each function.
741--
742-- Tool: AutoItTools.FunctionTraceAdd $(au3) savebefore:no,groupundo:yes Ctrl+T Debug: Add Trace Functions
743--------------------------------------------------------------------------------
744function AutoItTools:FunctionTraceAdd()
745    -- Pattern to match
746--~ local sPattern = "()([Ff][Uu][Nn][Cc][%s]*([%w_]*)%(.-%))([^\r\n]*)"
747    local sPattern = "()([Ff][Uu][Nn][Cc]%s+([%w_]*)%(.-%))([^\r\n]*)"
748
749    -- Used as a counter in pat_match to offset the line numbers
750    local i = 0
751    -- Callback function.  If the comment "FunctionTraceSkip" is found after
752    -- the closing ), then that function will not get a trace statement added.
753    local function pat_match(m1, m2, m3, m4)
754        if editor.StyleAt[m1] == SCE_AU3_COMMENT or
755            editor.StyleAt[m1] == SCE_AU3_COMMENTBLOCK or
756            m4:find(";[%s]*[Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn][Tt][Rr][Aa][Cc][Ee][Ss][Kk][Ii][Pp]") then
757            return m2 .. m4
758        end
759        i = i + 1
760        return m2 .. m4 .. self:NewLineInUse() .. "\tConsoleWrite('@@ (" .. editor:LineFromPosition(m1)+i .. ") :(' & @MIN & ':' & @SEC & ') " .. m3 .. "()' & @CR) ;### Function Trace"
761    end
762    -- Remove any previous traces so we don't get duplicates
763    self:FunctionTraceRemove()
764    -- Perform replacement
765    self:ReplaceDocByPattern(sPattern, pat_match)
766end    -- FunctionTraceAdd()
767--------------------------------------------------------------------------------
768-- FunctionTraceRemove()
769--
770-- Remove all Function Trace statements.
771--
772-- Tool: AutoItTools.FunctionTraceRemove $(au3) savebefore:no,groupundo:yes Ctrl+Alt+Shift+T Debug: Remove Trace Functions
773--------------------------------------------------------------------------------
774function AutoItTools:FunctionTraceRemove()
775        -- Callback function.
776        local function pat_match()
777                return ""
778        end
779        -- Remove any commented functions first
780        self:FunctionTraceUncomment()
781        -- Perform replacement
782        self:ReplaceDocByPattern(self:FunctionTracePattern(), pat_match)
783end     -- FunctionTraceRemove()
784
785--------------------------------------------------------------------------------
786-- FunctionTraceComment()
787--
788-- Comment all Function Trace statements.
789--
790-- Tool: AutoItTools.FunctionTraceComment $(au3) savebefore:no,groupundo:yes Ctrl+Shift+T Debug: Comment Trace Functions
791--------------------------------------------------------------------------------
792function AutoItTools:FunctionTraceComment()
793        -- Callback function.
794        local function pat_match(m1)
795                return self:NewLineInUse() .. ";\t" .. m1
796        end
797        -- Perform replacement
798        self:ReplaceDocByPattern(self:FunctionTracePattern(), pat_match)
799end     -- FunctionTraceComment()
800
801--------------------------------------------------------------------------------
802-- FunctionTraceUncomment()
803--
804-- Uncomment all Function Trace statements.
805-- Tool: AutoItTools.FunctionTraceUncomment $(au3) savebefore:no,groupundo:yes Ctrl+Alt+T Debug: Uncomment Trace Functions
806--------------------------------------------------------------------------------
807function AutoItTools:FunctionTraceUncomment()
808        -- Callback function.
809        local function pat_match(m1)
810                return self:NewLineInUse() .. "\t" .. m1
811        end
812        -- Perform replacement
813        self:ReplaceDocByPattern(self:FunctionTracePattern(true), pat_match)
814end     -- FunctionTraceUncomment()
815
816--------------------------------------------------------------------------------
817-- GetWord2()
818--
819-- Alternate GetWord() implementation specific to AutoIt.  If the caret is on a
820--      function, the entire function call is returned.
821--
822--      If a word can be found, it is returned, otherwise an empty string.
823--------------------------------------------------------------------------------
824function AutoItTools:GetWord2()
825        local word = editor:GetSelText()
826        if word == "" then
827                -- When on an ( or space, go to the start of the previous word.
828                if editor.CharAt[editor.CurrentPos] == 40 or editor.CharAt[editor.CurrentPos] == 32 then
829                        editor:WordLeft()
830                end
831                -- Cache the style as it's used numerous times.
832                local style = editor.StyleAt[editor.CurrentPos]
833                -- The start and end of the text range.
834                local from = editor:WordStartPosition(editor.CurrentPos)
835                local to = editor:WordEndPosition(editor.CurrentPos)
836                -- Use a variable to shorten the for loop code.
837                local line = editor:LineFromPosition(editor.CurrentPos)
838                -- Caret is on a function.
839                if style == SCE_AU3_FUNCTION or style == SCE_AU3_DEFAULT or style == SCE_AU3_UDF then
840                        -- A counter of the number of opening brackets encountered.
841                        local brackets = 0
842                        -- A flag set to true if an opening bracket is encountered.
843                        local found = false
844                        -- Iterate the line looking for the end of the function call.
845                        for i = editor.CurrentPos, editor.LineEndPosition[line] do
846                                -- Make sure we don't count brackets in strings.
847                                if editor.StyleAt[i] ~= SCE_AU3_STRING then
848                                        -- Found an opening bracket, increment counter and set flag.
849                                        if editor.CharAt[i] == 40 then
850                                                brackets = brackets + 1
851                                                found = true
852                                        end
853                                        -- Found a closing bracket, decrement counter.
854                                        if editor.CharAt[i] == 41 then
855                                                brackets = brackets - 1
856                                        end
857                                end
858                                -- We found a bracket and we found the end, set to and break.
859                                if found and brackets == 0 then
860                                        to = i + 1
861                                        break
862                                end
863                        end
864                        -- If we didn't find any brackets, just return the simple GetWord().
865                        if not found then
866                                return self:GetWord()
867                        end
868                -- Caret is in a string.
869                elseif style == SCE_AU3_STRING then
870                        -- Find the start of the string.  To do this, we iterate backwards
871                        -- to the indentation.
872                        for i = editor.CurrentPos, editor.LineIndentPosition[line] - 1, -1 do
873                                if editor.StyleAt[i] ~= SCE_AU3_STRING then
874                                        -- We have to add 1 or we'll pick up the non-string
875                                        -- character as well.
876                                        from = i + 1
877                                        break
878                                end
879                        end
880                        -- Find the end of the string.  To do this, we iterate forwards to
881                        -- the end of the string.
882                        for i = editor.CurrentPos, editor.LineEndPosition[line] do
883                                if editor.StyleAt[i] ~= SCE_AU3_STRING then
884                                        to = i
885                                        break
886                                end
887                        end
888                end
889                -- Get the text range.
890                word = editor:textrange(from, to)
891        end
892        return word
893end    -- GetWord2()
894
895--------------------------------------------------------------------------------
896-- ValidateFunctions()
897--
898-- Validates a function has the proper comment header and #Region section.
899--
900-- Tool: AutoItTools.ValidateFunctions $(au3) savebefore:no Ctrl+Alt+V Validate Functions
901--------------------------------------------------------------------------------
902function AutoItTools:ValidateFunctions()
903        local doc = "\n" .. editor:GetText()
904
905        for pos, str in doc:gmatch(self.Pattern) do
906                -- We need to concatenate multi-line function definitions into a single
907                -- line.
908                str = str:gsub("_%s-" .. self:NewLineInUse() .. "%s*", "")
909                local pattern = "; " .. str .. self:NewLineInUse() .. ";" .. self:NewLineInUse()
910                local func = str:match("^(.-)[%(%s]")
911                local intro = "@@ (" .. editor:LineFromPosition(pos) + 1 .. ") :(" .. os.date("%I:%S") .. ") "
912                -- Validate function header
913                if not doc:find(pattern, 1, true) then
914                        self:DebugPrint("Pattern\r\n|" .. pattern .. "|")
915                        print(intro .. "Function header not present or out of sync for: " .. func)
916                end
917                -- Validate #Region
918                if not doc:find("#Region " .. func .. "()", 1, true) then
919                        print(intro .. "#Region missing for: " .. func)
920                end
921                -- Validate EndFunc
922                if not doc:find("[Ee][Nn][Dd][Ff][Uu][Nn][Cc]\t; " .. func .. "()") then
923                        print(intro .. "Incorrect EndFunc comment for: " .. func .. "\tExpected: EndFunc\t; " .. func .. "()")
924                end
925        end
926        print("Validate Functions for " .. props["FileNameExt"] .. " is complete.")
927end     -- ValidateFunctions()
928
929--------------------------------------------------------------------------------
930-- ExportLibrary()
931--
932-- Creates an exports section in an AutoIt file containing comments describing
933--      the functions in the file.
934--
935-- Tool: AutoItTools.ExportLibrary $(au3) savebefore:no,groupundo:yes Ctrl+Alt+E Export Library
936--------------------------------------------------------------------------------
937function AutoItTools:ExportLibrary()
938        -- These are constants used throughout.
939        local region_text = "#Region Members Exported"
940        local comment_start = "#cs Exported Functions"
941        local comment_end = "#ce Exported Functions"
942        local nl = self:NewLineInUse()
943
944        -- We work over the entire document.
945        local doc = editor:GetText()
946        if not doc:find(region_text, 1, true) then
947                print("Error: Unable to find \"" .. region_text .. "\" in the library, no export list created.")
948        else
949                local from, to, found = false
950                if not doc:find(comment_start, 1, true) then
951                        print("Warning: Unable to find \"" .. comment_start .. "\" in the library, there may be multiple export lists.")
952                        from = doc:match(region_text .. nl .. "()")
953                        to = from
954                else
955                        from = doc:match(comment_start .. nl .. "()")
956                        to = doc:match("()" .. comment_end)
957                        found = true
958                end
959                -- This should never happen due to the checks above.
960                if not from or not to then
961                        print("Error, unable to determine where to add the export list.")
962                else
963                        -- Store the list in this variable.
964                        local text = ""
965                        -- We only build the list for functions we can find in the code.
966                        -- Orphaned comments will not be found.
967                        for pos, str in doc:gmatch(self.Pattern) do
968                                -- Pull the name out of string so we can build a pattern.
969                                local name = str:match("^(.-)[%(%s]")
970                                -- First check that the name doesn't start with __ which means
971                                -- it's private.
972                                if not str:find("^__") then
973                                        -- Build the pattern.  It's a bit complicated to keep it
974                                        -- from running over lines it shoudn't.
975                                        local pattern = ";%s+(" .. name .. "%s*%([^" .. nl .. "]+)" .. nl .. ";%s+;(.-);%s+Parameters"
976                                        -- Get the two parts.
977                                        local func, desc = doc:match(pattern)
978                                        -- Ensure they are valid.
979                                        if func and desc then
980                                                -- Clean up the text, put on a single line, remove trailing spaces.
981                                                func = func:gsub("%s*$", "")    -- Trailing spaces
982                                                desc = desc:gsub("%s*;%s*", " ")        -- Multiple lines
983                                                desc = desc:gsub("^%s*", "")    -- Leading spaces
984                                                desc = desc:gsub("%s*$", "")    -- Trailing spaces
985                                                -- Concatenate the formatted text.
986                                                text = text .. func .. " - " .. desc .. nl
987                                        end
988                                end
989                        end
990                        -- We have to offset our indices because SciTE is 0-based while Lua
991                        -- strings are 1-based.
992                        editor:SetSel(from - 1, to -1)
993                        -- If the exports section already exists, we are replacing it.
994                        if found then
995                                editor:ReplaceSel(text)
996                        -- Otherwise, we have to insert the exports section.
997                        else
998                                editor:ReplaceSel(comment_start .. nl .. text .. comment_end .. nl)
999                        end
1000                        print("Exports list created. ")
1001                end
1002        end
1003end     -- ExportLibrary()
1004
1005-- *****************  Extra's **************************************************************************************************************************************
1006--------------------------------------------------------------------------------
1007-- OnChar(c)
1008--
1009-- Controls propercase Keywords.Functions and Abbreviation expansion
1010--
1011-- Parameters:
1012--      c - The character typed.
1013--------------------------------------------------------------------------------
1014function AutoItTools:OnChar(c)
1015--~     print("Char:" .. c)
1016        if editor.Lexer == SCLEX_AU3 then
1017                -- set propercase
1018                if props['proper.case'] == '1' and string.find(c, "[ =(]") then
1019                        self:ProperCase(c)
1020                end
1021                -- abbreviations logic will auto expand on space when SCE_AU3_EXPAND. written by Jos van der Zande (JdeB)
1022                local ls = editor.StyleAt[editor.CurrentPos-2]
1023                if ls == SCE_AU3_EXPAND and c == " "  then
1024                        self:Abbreviations()
1025                end
1026        end
1027end -- OnChar()
1028
1029
1030--------------------------------------------------------------------------------
1031-- TracePattern(with_comment)
1032--
1033-- Returns the pattern used to find FunctionTrace statements.  This must be
1034-- a function so NewLineInUse() can be called on the correct document.
1035--
1036-- Paramters:
1037--      with_comment - If true, returns the pattern with a leading comment.
1038--
1039-- Returns:
1040--      The pattern used to find FunctionTrace statements.
1041--------------------------------------------------------------------------------
1042function AutoItTools:TracePattern(with_comment)
1043        local nl = self:NewLineInUse()
1044        if with_comment then
1045                return nl .. "[%s]*;[%s]*(ConsoleWrite%([^" .. nl .. "]-%) ;### Trace Console[^" .. nl .. "]?)"
1046        else
1047                return nl .. "[%s]*(ConsoleWrite%([^" .. nl .. "]-%) ;### Trace Console[^" .. nl .. "]?)"
1048        end
1049end     -- TracePattern()
1050
1051--------------------------------------------------------------------------------
1052-- TraceAdd()
1053--
1054-- Inserts a ConsoleWrite() for each function.
1055--
1056-- Tool: AutoItTools.FunctionTraceAdd $(au3) 2 Ctrl+T Debug: Add Trace Functions
1057--------------------------------------------------------------------------------
1058function AutoItTools:TraceAdd()
1059        editor:BeginUndoAction()
1060        local sels = editor.SelectionStart
1061        local sele = editor.SelectionEnd
1062        --   when nothing is selected then Whole script
1063        if sels==sele then
1064                AutoItTools:FunctionTraceRemove()    -- Remove any previous traces so we don't get duplicates
1065                sels = 0
1066                sele = editor.Length
1067        end
1068        local FirstLine = editor:LineFromPosition(sels)
1069        local LastLine = editor:LineFromPosition(sele)
1070        local CurrentLine = FirstLine
1071        editor:GotoLine(FirstLine)
1072        PrevLineCont = 0
1073        while (CurrentLine <= LastLine) do
1074                local LineCode = editor:GetLine(editor:LineFromPosition(editor.CurrentPos))
1075                local LineCodeprev = editor:GetLine(editor:LineFromPosition(editor.CurrentPos)-1)
1076                -- Avoid adding a line ontop on the first line in the editor.Anchor
1077                if CurrentLine == 0 then
1078                        LineCode = ""
1079                        LineCodeprev = ""
1080                end
1081                -- fill LineCode with "" when nul to avoid function errors
1082                if LineCode == nul then LineCode = "" end
1083                -- Skip the Select and Switch statements since the trow an error with AU3Check
1084                place = string.find(LineCodeprev, "%#*[Ss][Ee][Ll][Ee][Cc][Tt]" )
1085                if place then LineCode = ""  end
1086                place = string.find(LineCodeprev, "%#*[Ss][Ww][Ii][Tt][Cc][Hh]" )
1087                if place then LineCode = ""  end
1088                -- Skip the debug consolewrite lines
1089                place = string.find(LineCode, "ConsoleWrite%('@@" )
1090                if place then LineCode = "" end
1091                -- Skip the line contains test for @error else it could break logic
1092                place = string.find(LineCode, "@[Ee][Rr][Rr][Oo][Rr]" )
1093                if place then LineCode = "" end
1094                -- Remove CRLF
1095                LineCode = string.gsub(LineCode,"\r\n","")
1096                -- Only go WordRight when its not already on a Keyword and LineCode not Empty
1097                if editor.StyleAt[editor.CurrentPos] ~= SCE_AU3_KEYWORD and LineCode ~= "" then
1098                        editor:WordRight()
1099                end
1100                ls = editor.StyleAt[editor.CurrentPos]
1101                --_ALERT("ls:" .. ls .. "   line:|" .. LineCode .. "|")
1102                if LineCode ~= "" and ls ~= SCE_AU3_COMMENTBLOCK and ls ~= SCE_AU3_COMMENT and ls ~= SCE_AU3_STRING and ls ~= SCE_AU3_PREPROCESSOR and ls ~= SCE_AU3_SPECIAL then
1103                        editor:LineEnd()
1104                        editor:CharLeft()
1105                        -- check for continuation lines since that would create a syntax error
1106                        if editor.CharAt[editor.CurrentPos] == 95 and editor.StyleAt[editor.CurrentPos] ~= SCE_AU3_COMMENT then
1107                                CurLineCont = 1
1108                        else
1109                                CurLineCont = 0
1110                        end
1111                        if LineCode ~= "" and PrevLineCont == 0 then
1112                                LineCode =      string.gsub(LineCode,"'","''")
1113                                cl = editor:LineFromPosition(editor.CurrentPos) +2
1114                                editor:Home()
1115                                --- mhz's proposal
1116                                local option = tonumber(props['debug.trace.option'])
1117                                if option == 3 then
1118                                        editor:AddText("ConsoleWrite('>Error code: ' & @error & '    Extended code: ' & @extended & '    SystemTime: ' & @hour & ':' & @min & ':' & @sec & @CRLF & @CRLF & '@@ Trace(" .. cl .. ") :    " .. LineCode .. "'  & @CRLF) ;### Trace Console\r\n" )
1119                                elseif option == 2 then
1120                                        editor:AddText("ConsoleWrite('>Error code: ' & @error & '    Extended code: ' & @extended & @CRLF & @CRLF & '@@ Trace(" .. cl .. ") :    " .. LineCode .. "'  & @CRLF) ;### Trace Console\r\n" )
1121                                elseif option == 1 then
1122                                        editor:AddText("ConsoleWrite('>Error code: ' & @error & @CRLF & @CRLF & '@@ Trace(" .. cl .. ") :    " .. LineCode .. "'  & @CRLF) ;### Trace Console\r\n" )
1123                                elseif option == 0 then
1124                                        editor:AddText("ConsoleWrite('@@ Trace(" .. cl .. ") :    " .. LineCode .. "'  & @CRLF) ;### Trace Console\r\n" )
1125                                elseif option == -1 then
1126                                        editor:AddText("ConsoleWrite('@@ (" .. cl .. ") : ***Trace :" .. LineCode .. "'  & @CRLF) ;### Trace Console\r\n" )
1127                                end
1128                                editor:LineDown()
1129                                editor:Home()
1130                        else
1131                                -- If continuation line then just move down
1132                                editor:LineDown()
1133                                editor:Home()
1134                        end
1135                        PrevLineCont = CurLineCont
1136                        CurrentLine = CurrentLine + 1
1137                else
1138                        -- just move down on comment and empty lines
1139                        editor:LineDown()
1140                        editor:Home()
1141                        CurrentLine = CurrentLine + 1
1142                end
1143        end
1144        editor:EndUndoAction()
1145end     -- TraceAdd()
1146
1147--------------------------------------------------------------------------------
1148-- TraceRemove()
1149--
1150-- Remove all Trace statements.
1151--
1152-- Tool: AutoItTools.TraceRemove $(au3) 1 * Debug: Remove Trace Functions
1153--------------------------------------------------------------------------------
1154function AutoItTools:TraceRemove()
1155        -- Callback function.
1156        local function pat_match()
1157                return ""
1158        end
1159        editor:BeginUndoAction()
1160        -- Remove any commented functions first
1161        self:TraceUncomment()
1162        -- Perform replacement
1163        self:ReplaceDocByPattern(self:TracePattern(), pat_match)
1164        editor:EndUndoAction()
1165end     -- TraceRemove()
1166
1167--------------------------------------------------------------------------------
1168-- TraceComment()
1169--
1170-- Comment all Function Trace statements.
1171--
1172-- Tool: AutoItTools.TraceComment $(au3) 1 * Debug: Comment Trace Functions
1173--------------------------------------------------------------------------------
1174function AutoItTools:TraceComment()
1175        -- Callback function.
1176        local function pat_match(m1)
1177                return self:NewLineInUse() .. ";\t" .. m1
1178        end
1179        editor:BeginUndoAction()
1180        -- Perform replacement
1181        self:ReplaceDocByPattern(self:TracePattern(), pat_match)
1182        editor:EndUndoAction()
1183end     -- TraceComment()
1184
1185--------------------------------------------------------------------------------
1186-- TraceUncomment()
1187--
1188-- Uncomment all Function Trace statements.
1189-- Tool: AutoItTools.TraceUncomment $(au3) 1 * Debug: Uncomment Trace Functions
1190--------------------------------------------------------------------------------
1191function AutoItTools:TraceUncomment()
1192        -- Callback function.
1193        local function pat_match(m1)
1194                --return self:NewLineInUse() .. "\t" .. m1
1195                return self:NewLineInUse() .. "" .. m1
1196        end
1197        editor:BeginUndoAction()
1198        -- Perform replacement
1199        self:ReplaceDocByPattern(self:TracePattern(true), pat_match)
1200        editor:EndUndoAction()
1201end     -- TraceUncomment()
1202
1203
1204--------------------------------------------------------------------------------
1205-- AllComment()
1206--
1207-- Comment all Debug and Trace statements.
1208-- Tool: AutoItTools.AllComment $(au3) 2 Alt+Ctrl+D Debug: Comment ALL lines
1209--------------------------------------------------------------------------------
1210function AutoItTools:AllComment()
1211        self:TraceComment()
1212        self:FunctionTraceComment()
1213        self:DebugComment()
1214end     -- TraceComment()
1215
1216--------------------------------------------------------------------------------
1217-- AllUncomment()
1218--
1219-- Uncomment all Debug and Trace statements.
1220-- Tool: AutoItTools.AllUncomment $(au3) 2 Alt+Ctrl+D Debug: UnComment ALL lines
1221--------------------------------------------------------------------------------
1222function AutoItTools:AllUncomment()
1223        self:TraceUncomment()
1224        self:FunctionTraceUncomment()
1225        self:DebugUncomment()
1226end     -- TraceUncomment()
1227
1228--------------------------------------------------------------------------------
1229-- AllTraceRemove()
1230--
1231-- Remove all Trace statements.
1232-- Tool: AutoItTools.AllTraceRemove $(au3) 2 Alt+Ctrl+D Debug: UnComment ALL lines
1233--------------------------------------------------------------------------------
1234function AutoItTools:AllTraceRemove()
1235        self:TraceRemove()
1236        self:FunctionTraceRemove()
1237end     -- AllTraceRemove()
1238
1239--------------------------------------------------------------------------------
1240-- OpenInclude(version)
1241--
1242-- Open the #Include file from your script.
1243--
1244-- Tool: AutoItTools.OpenInclude $(au3) 2 Alt+I Open Include
1245--------------------------------------------------------------------------------
1246function AutoItTools:OpenInclude(version)
1247    local IncFile, Filename
1248        -- currentline text
1249        local CurrentLine = editor:GetLine(editor:LineFromPosition(editor.CurrentPos))
1250        -- Exclude #include-once
1251        if CurrentLine == nil then
1252            print("Not on #include line.")
1253                return true
1254        end
1255        if string.find(CurrentLine, "%#[Ii][Nn][Cc][Ll][Uu][Dd][Ee][-][Oo][Nn][Cc][Ee]" ) then
1256                return true
1257        end
1258        -- find #include
1259        local place = string.find(CurrentLine, "%#[Ii][Nn][Cc][Ll][Uu][Dd][Ee]" )
1260        -- strip every thing after opening bracket when found
1261        if place then
1262                IncFile = string.sub(CurrentLine,place + 8)
1263                IncFile = string.gsub(IncFile,"\t", " ")  -- replace Tabs with space
1264                IncFile = string.gsub(IncFile,"\r","")  -- strip CR characters
1265                IncFile = string.gsub(IncFile,"\n","")  -- strip LF characters
1266                IncFile = string.gsub(IncFile, "^%s*(.-)%s*$", "%1")    -- strip leading and trailing whitespace characters
1267        else
1268            print("Not on #include line.")
1269                return true
1270        end
1271        --
1272        if version ~= "beta" then
1273                version = ""
1274        end
1275        --
1276        IncFile = string.gsub(IncFile,";(.*)","")
1277        -- get list of directories to check
1278        local directories = AutoItGotoDefinition:GetDirectories(version)
1279        local start, stop, step, found
1280        if string.find(IncFile, "<" ) then
1281                IncFile = string.gsub(IncFile,"\<","")
1282                IncFile = string.gsub(IncFile,"\>","")
1283                start = 1
1284                stop = #directories
1285                step = 1
1286        else  -- Else it is a include file in the script dir
1287                IncFile = string.gsub(IncFile,"\"","")
1288                IncFile = string.gsub(IncFile,"'","")
1289                start = #directories
1290                stop = 1
1291                step = -1
1292        end
1293        -- loop through the defined directories
1294        found = false
1295        for i = start, stop, step do
1296                Filename = directories[i] .. IncFile
1297                self:DebugPrint("Checking: " .. Filename)
1298                if self:FileExists(Filename) then
1299                        -- If we found the include file so open it
1300                        print("Opened: " .. Filename)
1301                        AutoItGotoDefinition:ShowFunction("", Filename)
1302                        found = true
1303                        break
1304                end
1305        end
1306        if not found then
1307                print("Couldn't locate include file: " .. IncFile)
1308        end
1309end
1310
1311--------------------------------------------------------------------------------
1312-- OpenInclude(version)
1313--
1314-- Open the #Include file from your script.
1315--
1316-- Tool: AutoItTools.OpenInclude $(au3) 2 Alt+Shift+I Open Beta Include
1317--------------------------------------------------------------------------------
1318function AutoItTools:OpenBetaInclude()
1319        self:OpenInclude("beta")
1320end
1321
1322--------------------------------------------------------------------------------
1323-- OnBeforeSave(filename)
1324--
1325-- keep the number of backups as defined by backup.files = ?    by Jos van der Zande (JdeB)
1326--
1327-- AutoItTools.OnBeforeSave $(au3) 2 Alt+Shift+I Open Beta Include
1328--------------------------------------------------------------------------------
1329function AutoItTools:OnBeforeSave(filename)
1330        local sbck = tonumber(props['backup.files'])
1331        -- backup specified and bigger than 0 ?
1332        if sbck == nil or sbck == 0 then
1333                return false
1334        end
1335        local nbck = 1
1336        local bfil1 = ""
1337        if sbck > 1 then
1338                bfil1 = ".1"
1339        end
1340        -- check first file backup file format without number and rename it to *.1.bak
1341        if sbck > 1 and io.open (filename.. "." .. ".bak", "r") == nil and io.open (filename.. "." .. ".1.bak", "r") == nil then
1342                os.rename (filename .. ".bak", filename .. ".1.bak")
1343        end
1344        -- rename all files to +1
1345        while (sbck > nbck ) do
1346                local fn1 = sbck-nbck
1347                local fn2 = sbck-nbck+1
1348                os.remove (filename.. "." .. fn2 .. ".bak")
1349                os.rename (filename .. "." .. fn1 .. ".bak", filename .. "." .. fn2 .. ".bak")
1350                nbck = nbck + 1
1351        end
1352        -- rename original to .1.bak or .bak depending on number of backups
1353        os.remove (filename.. bfil1 .. ".bak")
1354        os.rename (filename, filename .. bfil1 .. ".bak")
1355        return false
1356end
1357
1358--------------------------------------------------------------------------------
1359-- AutoItTools:ProperCase(c)
1360--
1361-- Function which will Proper case keywords/functions as defined in au3.api.
1362--------------------------------------------------------------------------------
1363function AutoItTools:ProperCase(c)
1364        local repword = ""
1365    -- get word infront of cursor
1366        local from = editor:WordStartPosition(editor.CurrentPos-1)
1367        local to = editor:WordEndPosition(from)
1368        local word = editor:textrange(from, to)
1369        style = editor.StyleAt[from]
1370        if (style == SCE_AU3_DEFAULT) or (style == SCE_AU3_FUNCTION) or (style == SCE_AU3_KEYWORD) or (style == SCE_AU3_MACRO) then
1371                word= string.gsub(word,"%s","") -- strip whitespace characters
1372                word= string.gsub(word,"%s","") -- strip whitespace characters
1373                --print("Word:" .. word .. "|")
1374                if word == nil or string.len(word) < 2 then return true end
1375                --print("Word:" .. word .. "|  Style:" .. style)
1376                if self.ProperWords ~= nil and self.ProperWords ~= "" then
1377                        local rep_start = string.find("\n" .. self.l_ProperWords  .. "\n", "\n" .. string.lower(word)  .. "\n")
1378                        if rep_start == nil then
1379                                rep_start = string.find("\n" .. self.l_ProperWords .. "\n","\n" .. string.lower(word) .. " ")
1380                        end
1381                        if rep_start ~= nil and rep_start ~= 0 then
1382                                rep_start = rep_start
1383                           repword = string.sub(self.ProperWords .. "\n",rep_start,rep_start + string.len(word) -1)
1384                        else
1385                                return true
1386                        end
1387                end
1388                -- if found process it
1389                repword = string.gsub(repword,"%s","")
1390                repword = string.gsub(repword,"\n","")
1391                if repword ~= nil and repword ~= word and repword ~= "" then
1392                        local savepos = editor.CurrentPos
1393                        editor:remove(from, to)
1394                        editor:insert(from, repword)
1395                        editor:GotoPos(savepos)
1396                end
1397        end
1398        return true
1399end
1400
1401
1402--------------------------------------------------------------------------------
1403-- AutoItTools:Abbreviations()
1404--
1405-- Expand abbreviations  by Jos van der Zande (JdeB)
1406--------------------------------------------------------------------------------
1407--
1408function AutoItTools:Abbreviations()
1409        editor:DeleteBack()
1410        scite.MenuCommand(IDM_ABBREV)
1411end