Jump to content

plys – redesigns AutoIt for comfortable coding (file scope namespaces and stuff)

Recommended Posts

- file scope in AutoIt programs

- module-private functions and variables

- python-like import operator

Code is 10% lighter!

This inconspicuous wrapper complements the AutoIt language with

  1. preprocessor keyword #import in addition to #include similar to import in Python
  2. Python-like blocking by lines indentation (without endfunc, wend etc.)
  3. dim and const outside of functions means global and global const respectively, inside of functions means local and local const
  4. arguments of function are const by default, but with dim prefix it becomes variable
  5. short synonyms for functions as a rule using in large projects: for arrays, files and strings
  6. no “$”-prefix in variable names
; file “mylib.aup”

dim bar, _bar

func foo()
    bar = _foo()

func _foo(dim str="word/number/space")
    _bar = Sort(Split(str, "/", @NoCount))
; file “main.aup”

#import "mylib.aup"

In this example variable _bar and function _foo() are private for module mylib.aup (names begin with an underscore) and not visible in main.aup. Variable bar and function foo() will be visible with the “mylib:” prefix:

; file “main.aup”

#import "mylib.aup"

bar = foo()                 ; error: no bar and foo() in this scope
mylib:bar = mylib:foo()     ; OK: bar and foo() are public in “mylib” scope
mylib:_bar = mylib:_foo()       ; error: _bar and _foo() are private in “mylib” scope

Sort is synonym for _ArraySort, Split is synonym for StringSplit, @NoCount is synonym for $STR_NOCOUNT.

All synonyms


Print → ConsoleWrite

Struct → DllStructCreate
StructGet → DllStructGetData
StructGetSize → DllStructGetSize
StructGetPtr → DllStructGetPtr
StructSet → DllStructSetData

ChangeDir Copy CreateShortcut Flush GetAttrib GetEncoding GetLongName GetShortcut GetShortName GetSize GetTime GetVersion Open Opendialog Read ReadLine ReadToArray Recycle RecycleEmpty SaveDialog SelectFolder SetAttrib SetEnd SetPos SetTime Write WriteLine → File*
CreateLink → FileCreateNTFSLink
FirstFile → FileFindFirstFile
NextFile → FileFindNextFile

AddCR Format InStr IsAlNum IsAlpha IsASCII IsDigit IsLower IsSpace IsUpper IsXDigit Left Len Lower Mid Replace Right Split StripCR StripWS TrimLeft TrimRight Upper → String*
reFind → StringRegExp
reRepl → StringRegExpReplace

Activate Active Flash GetCaretPos GetClassList GetClientSize GetProcess GetTitle Kill List MenuSelectItem MinimizeAll MinimizeAllUndo SetOnTop SetTitle SetTrans Wait WaitActive WaitClose WaitNotActive → Win*

@NoCaseSense @CaseSense @NoCaseSenseBasic @StripLeading @StripTrailing @StripSpaces @StripAll @ChrSplit @EntireSplit @NoCount @EndNotStart @UTF16 @USC2 → $STR_*

@reArray @reArrayFull @reArrayGlobal @reArrayGlobalFull → $STR_REGEXP*MATCH

@ActiveWin → WinGetHandle("[ACTIVE]")

Add ColDelete ColInsert Combinations Display Extract FindAll Insert Max MaxIndex Min MinIndex Permute Pop Push Search Shuffle Sort Swap ToClip Transpose Trim Unique → _Array*
ToHist → _Array1DToHistogram
BinSearch → _ArrayBinarySearch
Concat → _ArrayConcatenate

How to use this wrapper

  1. Place the “plys.au3” file in the “Include” folder (C:\Program Files (x86)\AutoIt3\Include\).
  2. Make in your project folder au3-file with this content
    #include <plys.au3>
    #plys "MainFileOfMyProject.aup"
    ; run me!


  3. Then, if you have the files module1.aup and module2.au3 with the same names
    ; module1.aup
    dim bar, _bar
    func foo()
        ; instructions
    ; module2.au3
    global $bar
    func foo()
        ; instructions
    func _foo()
        ; instructions
    you can write in your program like this
    ; MainFileOfMyProject.aup
    #import "module1.aup"
    #import "module2.au3"
    module1:bar = module2:foo()
    ;module1:_bar = module2:_foo()      ; error because _bar and _foo() are private (with underscore prefix)
    #import "module2.au3"       ; re-importing files without "#include-once" will not lead to errors


You can turn off data exchange through standard input/output streams, then the shell process will not hang in memory, but then you will not be able to observe the output of your program in the output window of your development environment. You can do this by adding a line to the main file of your program

#plys nostdio

You can disable autorun of your program altogether, keeping only the generation of executable files, for example, for further compilation, adding the line to the main file of your program

#plys norun

Then you can compile the program, specifying to the compiler the resulting file main.aup.au3, if the main file of your program is called main.aup.

File processing is pretty dumb, so bugs are possible.

How it works

The plys.au3 file contains the code that is run immediately after the launch of your program: files are automatically processed, after which the new AutoIt process interprets the already converted code, and the current process remains cycle to continue data exchange with the new process via standard streams. This handler replaces all #import with #include. The processed files get the extension .aup.au3 and are placed in the folder of the original script with hidden attribute.

One more example


It was

func BaseMap(const $k)
    local const $key = IsDeclared("k") ? _
        ($k=0x0473 ? "!{F4}" : $k) : @HotKeyPressed
    local const $index = _
        _ArrayBinarySearch($BASE_KEYMAP, $key, 1, 0, 1)
    if $index = -1 then return False
    local const $action = $BASE_KEYMAP[$index][0]
    switch $action
        case "RestartProcess"
        case "SwitchHelp"
        case else
            Components_Perform("", $action)
    HotKeysSet($BASE_KEYMAP, FuncName(BaseMap))
    return True

and it became

func BaseMap(k)
    const key = IsDeclared("k") ? _
        (k=0x0473 ? "!{F4}" : k) : @HotKeyPressed
    const index = _
        BinSearch(BASE_KEYMAP, key, 1, 0, 1)
    if index = -1 then return False
    const action = BASE_KEYMAP[index][0]
    switch action
        case "RestartProcess"
        case "SwitchHelp"
        case else
            Components:Perform("", action)
    HotKeysSet(BASE_KEYMAP, FuncName(BaseMap))
    return True



  • #import from "filename.aup"
#import from "mylib.aup"

bar = foo()     ; bar and foo will be taken from the "mylib.aup"
  • #import "filename.aup" as alias
#import "mylib.aup" as ml

ml:bar = ml:foo()       ; bar and foo will be taken from the "mylib.aup"
  • Optimize translation speed


Current version https://github.com/NSUSpray/plys

Old version (import only): import

Edited by NSUSpray
no dollar prefix

GoodKeys is my main product made using Python and AutoIt https://forum.ableton.com/viewtopic.php?t=220718

Link to post
Share on other sites

Fixed: Wrapper used case-sensitive mode instead insensitive (could found “local …” but not “Local …”).

Critical! The algorithm did not work correctly for programs written in the generally accepted style (!), when keywords are started with a capital letter.

GoodKeys is my main product made using Python and AutoIt https://forum.ableton.com/viewtopic.php?t=220718

Link to post
Share on other sites

Massive update!

  • Python-like blocking by lines indentation (without endfunc, wend etc.)
  • dim and const outside of functions means global and global const respectively, inside of functions means local and local const
  • arguments of function are const by default, but with dim prefix it becomes variable
  • short synonyms for functions as a rule using in large projects: for arrays, files and strings
Edited by NSUSpray

GoodKeys is my main product made using Python and AutoIt https://forum.ableton.com/viewtopic.php?t=220718

Link to post
Share on other sites
  • NSUSpray changed the title to AutoIt plys – syntax additions for comfortable coding (file scope namespaces and stuff)

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By DanielRossinsky
      I've been working for quite a while on an automated installer for python3.8.3 and Thonny3.2.7 and encountered a pretty strange problem - automated python install work perfectly. However using pip to install esptool returns error code 1. The strange thing is if i manually install it after running the python installer it does indeed install correctly (returns 0 instead).
      The code i was using:
      Local Const $sInstallerPath = @ScriptDir & "\python-3.8.3.exe" Local $PythonResult = RunWait($sInstallerPath & " /quiet") Local $ESPToolResult = RunWait(@ComSpec & " /c " & "pip install esptool") MsgBox(0, "Installer returns", "Python result: " & $PythonResult & @CRLF & "esptool result: " & $ESPToolResult) Than I thought that maybe python installer fires off multiple processes during installation and tried :
      Local Const $sInstallerPath = @ScriptDir & "\python-3.8.3.exe" Local $iPID = Run($sInstallerPath & " /quiet") Local $PythonResult = ProcessWaitClose($iPID) Local $ESPToolResult = RunWait(@ComSpec & " /c " & "pip install esptool") MsgBox(0, "Installer returns", "Python result: " & $PythonResult & @CRLF & "esptool result: " & $ESPToolResult) However, The problem still remains. some-why esptool install refuses to be automated with python but if i comment out the python install part it does work ?! (note that i comment it out after the script already installed python and did not manually install it myself).
      Any idea why this happens ?
      NOTE: I added the unattend.xml file im using but python.exe was too big - I'm using python3.8.3 for compatibility with thonny and the unattend files makes a minimal install just for thonny to work (target platform esp32 with micopython)
    • By pete_wilde
      Hi Guys,
      I am trying to convert a python script to AutoIT, but it is not returning any data.

      My aim is to eventually have a script which sends me an email whenever a goal is scored in the English Premiership.
      Is there any guru who can have a quick look over the below script and see if there are any obvious errors?
      To use a football analogy, I think that I have hit the bar a couple of times, but not yet found the back of the net! 
      #cs ---------------------------------------------------------------------------- PYTHON CODE: import requests import json endpoint = "https://api.betfair.com/exchange/betting/rest/v1.0/" header = { 'X-Application' : 'APP_KEY_HERE', 'X-Authentication' : 'SESSION_TOKEN_HERE' ,'content-type' : 'application/json' } json_req='{"filter":{ }}' url = endpoint + "listEventTypes/" response = requests.post(url, data=json_req, headers=header) print json.dumps(json.loads(response.text), indent=3) #ce ---------------------------------------------------------------------------- #include <WinHttp.au3> Opt("MustDeclareVars", 1) Opt("TrayIconDebug", 1) Global $sAddress = 'https://api.betfair.com/exchange/betting/json-rpc/v1/' Global $sPostData = 'https://api.betfair.com/exchange/betting/json-rpc/v1/listEventTypes/' Global $sAppKey = '4YpsEhdsgtedjd' Global $sSession_key = 'BhKl7Ijdu4E3pzHhKu7K5fQrvzf9p3wq/diRMt7bZka7' Global $sjson_req = '{"filter":{ }}' Global $hOpen = _WinHttpOpen() ; Get Session handle ; ##### CHECKED AND VALID HANDLE IS RETURNED ##### Global $hConnect = _WinHttpConnect($hOpen, $sAddress) ; Get connection handle ; ##### CHECKED AND VALID HANDLE IS RETURNED ##### Global $hRequest = _WinHttpOpenRequest($hConnect, 'POST') ; Make a request ; ##### CHECKED AND VALID HANDLE IS RETURNED ##### ; Add header fields to the request _WinHttpAddRequestHeaders($hRequest, 'X-Application: ' & $sAppKey) _WinHttpAddRequestHeaders($hRequest, 'X-Authentication: ' & $sSession_key) _WinHttpAddRequestHeaders($hRequest, 'Accept: application/json') _WinHttpAddRequestHeaders($hRequest, 'Content-Type: application/json') _WinHttpSendRequest($sPostData, 'Data=' & $sjson_req, $hRequest) ; Send it _WinHttpReceiveResponse($hRequest) ; Wait for the response ; Check if there is a response Global $sHeader, $sReturned If _WinHttpQueryDataAvailable($hRequest) Then $sHeader = _WinHttpQueryHeaders($hRequest) MsgBox(64, 'Header', $sHeader) Do $sReturned &= _WinHttpReadData($hRequest) Until @error ConsoleWrite($sReturned) ; Print returned Else ConsoleWriteError('!No data available.' & @CRLF) MsgBox(48, 'Failure', 'No data available.') ;##### <==== ALWAYS FAILS HERE! ##### EndIf ; Close handles _WinHttpCloseHandle($hRequest) _WinHttpCloseHandle($hConnect) _WinHttpCloseHandle($hOpen) I am sure that I have probably missed out a vital line, but for the life of me I can't see the wood for the trees anymore.
      Anyone got any suggestions?
      Many thanks,
    • By gahhon
      I only found that AutoIt can actually execute the entire python script or execute the .exe (converted to .exe from .py)
      But what if I just want call the particular function? If that possible to do so?
      This is because python can't create fancy GUI like AutoIT does. So my plan is use AutoIT to have fancy GUI.
      Then each buttons will trigger specific function in the python script or .exe file.
      For instances:
      btnSum - trigger function in python script or .exe file (funcSum)
      btnMinus - trigger function in python script or .exe file (funcMinus)
      Thanks for advance information.
    • By Ascer
      Hello mates.
      I would like to share simple but very important function required durning code many *au3 files.
      Such as function is used by a few scripts developers on forum but most of users waste a lot of time to make his functions/tool free from errors and bugs.
      How is working?
      This function do not check errors like Scite debugger. You can be able to make something like call exceptions in Python.
      Think about this and think when you ran some code, no error but also do nothing. 0 information and you have to jump into own or other script to find out reason.
      Function: Updated 2018-02-04, 08:47 (fixed AutoIt problem with dedection @ScriptName)
      ;============================================================================================================================================================== ; Function: Exception ([ $sInfo = "" [, $vReturnValue = Null [, $vExtended = @extended [, $iErrorNr = @error [, $iErrorLine = @ScriptLineNumber ]]]]]) ; ; Description: Call exceptions in different *au3 files located in this same Folder. ; ; Parameter(s): $sInfo - Information about exception in code, created by yourself. ; $vReturnValue - (Default=Null) Set value to return durning exception. ; $iErrorNr - (Default=@error) Set the error manually by adding a number. ; $vExtended - (Default=@extended) Set extended manually. ; $iErrorLine - Internal use do not change! ; ; Return Value(s): $vReturnValue, ; Additional: Output string in Scite Console about debug trace. ; ; Author (s): Who cares? ;============================================================================================================================================================== Func Exception($sInfo="", $vReturnValue = Null, $iErrorLine = @ScriptLineNumber, $iErrorNr = @error, $vExtended = @extended) Dim $aArray[0] Local $sScriptPath = @ScriptFullPath Local $sCurrentScriptLine = StringLower(FileReadLine($sScriptPath, $iErrorLine)) If Not StringInStr($sCurrentScriptLine, "exception") Then Local $aInclude = FileReadToArray($sScriptPath) For $sItem In $aInclude Local $sLowerLine = StringLower($sItem) If StringInStr($sLowerLine, "#include") Then Local $sIncludeName = StringTrimLeft($sItem, 8) Local $sConvertedName = "" Local $bAdd = False Local $aDelimeter = ["<", ">"] If StringInStr($sIncludeName , "'") Then $aDelimeter[0] = "'" $aDelimeter[1] = "'" ElseIf StringInStr($sIncludeName , '"') Then $aDelimeter[0] = '"' $aDelimeter[1] = '"' EndIf Local $aSplitInclude = StringSplit($sIncludeName, "") For $sSign In $aSplitInclude If $sSign = $aDelimeter[0] And Not $bAdd Then $bAdd = True ContinueLoop ElseIf $sSign = $aDelimeter[1] And $bAdd Then ReDim $aArray[UBound($aArray) + 1] $aArray[UBound($aArray) - 1] = $sConvertedName ExitLoop EndIf If $bAdd Then $sConvertedName &= $sSign Next EndIf Next EndIf If UBound($aArray) > 0 Then For $sName In $aArray Local $sPath = @ScriptDir & "\" & $sName If FileExists($sPath) Then $sCurrentScriptLine = StringLower(FileReadLine($sPath, $iErrorLine)) If StringInStr($sCurrentScriptLine, "exception") Then $sScriptPath = $sPath ExitLoop EndIf EndIf Next EndIf Local $aFile = FileReadToArray($sScriptPath) Local $sFunctionName, $sLine Local $bFound = False For $i = 0 To $iErrorLine - 1 If $bFound Or $iErrorLine <= 0 Then ExitLoop $sLine = StringReplace($aFile[$iErrorLine - $i], @TAB, "") If StringInStr(StringLower($sLine), "func ") Then Local $aSortLine = StringSplit($sLine, '') $sLine = "" For $h = 1 To $aSortLine[0] - 1 Local $sLowerSort = StringLower($aSortLine[$h]) If $sLowerSort = "(" Then $bFound = True ExitLoop ElseIf $sLowerSort <> @TAB And $sLowerSort <> " " Then If $sLowerSort = "f" Or $sLowerSort = "u" Or $sLowerSort = "n" Or $sLowerSort = "c" Then $sLine &= $aSortLine[$h] Else If Not StringInStr($sLine, "func") Then $sLine = "" ExitLoop Else $sLine &= $aSortLine[$h] EndIf EndIf EndIf Next EndIf Next If StringLeft(StringLower($sLine), 4) <> "func" Then $sLine = "" EndIf $sFunctionName = StringTrimLeft($sLine, 4) If StringLen($sFunctionName) < 1 Then $sFunctionName = "not recognized" Else $sFunctionName &= " ( ... )" EndIf If StringLen($sInfo) < 1 Then $sInfo = "nothing about" EndIf $vRet = $vReturnValue If $vRet = Null Then $vRet = "Null" ElseIf IsArray($vRet) Then $vRet = "an Array with " & UBound($vRet) & " items" ElseIf IsBinary($vRet) Then $vRet = "binary " & $vRet ElseIf IsBool($vRet) Then $vRet = "bool " & $vRet ElseIf IsDllStruct($vRet) Then $vRet = "dll struct " & $vRet ElseIf IsFloat($vRet) Then $vRet = "float " & $vRet ElseIf IsHWnd($vRet) Then $vRet = "hwnd " & $vRet ElseIf IsInt($vRet) Then $vRet = "int " & $vRet ElseIf IsKeyword($vRet) Then $vRet = "keyword " & $vRet ElseIf IsNumber($vRet) Then $vRet = "number " & $vRet ElseIf IsObj($vRet) Then $vRet = "object " & $vRet ElseIf IsPtr($vRet) Then $vRet = "ptr " & $vRet ElseIf IsString($vRet) Then If $vReturnValue = "" or StringReplace($vRet, " ", "") = "" Then $vRet = 'empty string ""' Else $vRet = 'string "' & $vRet & '"' EndIf EndIf Local $sStruct $sStruct &= "! Exception = {" & @CRLF $sStruct &= "!" & @CRLF $sStruct &= "!" & @TAB & '"date" = ' & @YEAR & "-" & @MON & "-" & @MDAY & ", " & @HOUR & ":" & @MIN & ":" & @SEC & ", " & @MSEC & "ms," & @CRLF $sStruct &= "!" & @TAB & '"path" = ' & $sScriptPath & "," & @CRLF $sStruct &= "!" & @TAB & '"line" = ' & $iErrorLine & "," & @CRLF $sStruct &= "!" & @TAB & '"func" = ' & $sFunctionName & "," & @CRLF $sStruct &= "!" & @TAB & '"retn" = ' & $vRet & "," & @CRLF $sStruct &= "!" & @TAB & '"exten" = ' & $vExtended & "," & @CRLF $sStruct &= "!" & @TAB & '"error" = ' & $iErrorNr & "," & @CRLF $sStruct &= "!" & @TAB & '"info" = ' & $sInfo $sStruct &= @CRLF $sStruct &= "!" & @CRLF $sStruct &= "! }" & @CRLF & @CRLF ConsoleWrite($sStruct) Return $vReturnValue EndFunc ;==> Exception  
      How to use? - Example 1
      Func Example() Local $sFile = FileOpen(@ScriptDir & "\example.py") If $sFile = -1 Then Return Exception("Failed to open 'example.py', File not exist!") EndIf ; continue working EndFunc Example() Example 1 Output in Scite console:

      Example 2
      Func Example2() Local $oHttp = ObjCreate("WinHttp.WinHttpRequest.5.1.Fake") ; added .Fake to make object wrong. If Not IsObj($oHttp) Then Return Exception("Failed to create Object in variable $oHttp.", 2.2) EndIf ; continue working EndFunc Local $vRet = Example2() ConsoleWrite("$vRet = " & $vRet & @CRLF) Example 2 Output in Scite console:

    • By n3wbie
      Hello m trying to learn python 
      m interested in knowing if there is koda like gui designer for python
      please also help me what all additional modules i require
      like ones which are famous
      i have already done with
  • Create New...