From a288686bd56ff863dab908fe328f9804eadb0ba0 Mon Sep 17 00:00:00 2001 From: andymbody Date: Sun, 7 Jul 2024 18:11:14 -0500 Subject: [PATCH] Fix V1 to V2 label name conversion #48, #201 Fix V1 to V2 label name conversion. Does not address variable names, that will be handled separately --- ConvertFuncs.ahk | 263 ++++++++++++------ QuickConvertorV2.ahk | 2 +- convert/1Commands.ahk | 48 ++-- convert/MaskCode.ahk | 87 ++++-- .../Test_Folder/Environment/LabelNames_01.ah1 | 40 +++ .../Test_Folder/Environment/LabelNames_01.ah2 | 40 +++ .../Test_Folder/Environment/LabelNames_02.ah1 | 13 + .../Test_Folder/Environment/LabelNames_02.ah2 | 16 ++ 8 files changed, 377 insertions(+), 132 deletions(-) create mode 100644 tests/Test_Folder/Environment/LabelNames_01.ah1 create mode 100644 tests/Test_Folder/Environment/LabelNames_01.ah2 create mode 100644 tests/Test_Folder/Environment/LabelNames_02.ah1 create mode 100644 tests/Test_Folder/Environment/LabelNames_02.ah2 diff --git a/ConvertFuncs.ahk b/ConvertFuncs.ahk index e384d12b..97e6846d 100644 --- a/ConvertFuncs.ahk +++ b/ConvertFuncs.ahk @@ -1,10 +1,9 @@ -#Requires AutoHotKey v2.0 +#Requires AutoHotKey v2.0 #SingleInstance Force ; to do: strsplit (old command) ; requires should change the version :D -global dbg := 0 -global gUseMasking := 1 ; 2024-06-26 - set to 0 to test without masking applied +global dbg := 0 #Include lib/ClassOrderedMap.ahk #Include lib/dbg.ahk @@ -40,10 +39,19 @@ Before_LineConverts(&code) { ;#### Please place CALLS TO YOUR FUNCTIONS here - not boilerplate code ##### + ; these must be initialized prior to entering _convertLines() + global gUseMasking := 1 ; 2024-06-26 - set to 0 to test without masking applied + + ; 2024-07-07 AMB, ADDED - captures all v1 labels from script... + ; ... converts v1 names to v2 compatible... + ; ... and places them in gmAllLabelsV1toV2 map for easy access + global gmAllLabelsV1toV2 := map() + getScriptLabels(code) + ; 2024-07-02 AMB, for support of MenuBar detection global gMenuBarName := getMenuBarName(code) ; name of GUI main menubar - ; turn on/off at top of script + ; can turn masking on/off at top of Before_LineConverts() if (gUseMasking) { ; 2024-07-01 ADDED, AMB - For fix of #74 @@ -53,15 +61,14 @@ Before_LineConverts(&code) ; convert and mask classes and functions maskBlocks(&code) ; see MaskCode.ahk } - - return ; code by reference + return ; code by reference } ;################################################################################ After_LineConverts(&code) { ;#### Please place CALLS TO YOUR FUNCTIONS here - not boilerplate code ##### - ; turn on/off at top of script + ; can turn masking on/off at top of Before_LineConverts() if (gUseMasking) { ; remove masking from classes, functions, multiline string @@ -71,9 +78,9 @@ After_LineConverts(&code) } ; inspect to see whether your code is best placed here or in FinalizeConvert() - ; operations that must be performed last + ; operations that must be performed last FinalizeConvert(&code) ; perform all final operations - return + return ; code by reference } ;################################################################################ ; MAIN CONVERSION LOOP - handles each line separately @@ -103,6 +110,7 @@ _convertLines(ScriptString, finalize:=!gUseMasking) ; 2024-06-26 RENAMED to ac global gmMenuCBChecks := map() ; 2024-06-26 AMB, for fix #131 global gmGuiCtrlType := map() ; Create a map to return the type of control global gmGuiCtrlObj := map() ; Create a map to return the object of a control + global gmAllLabelsV1toV2 ; already set ; captures/converts all v1 label NAMES (not labels) within script - see getScriptLabels() global gUseLastName := False ; Keep track of if we use the last set name in gGuiList global gmOnMessageMap := map() ; Create a map of OnMessage listeners global gNL_Func := "" ; _Funcs can use this to add New Previous Line @@ -114,39 +122,20 @@ _convertLines(ScriptString, finalize:=!gUseMasking) ; 2024-06-26 RENAMED to ac global gTVNameDefault := "TV" global gSBNameDefault := "SB" global gFuncParams - - global gmAhkCmdsToConvert, gmAhkFuncsToConvert, gmAhkMethsToConvert + global gAhkCmdsToRemove, gmAhkCmdsToConvert, gmAhkFuncsToConvert, gmAhkMethsToConvert , gmAhkArrMethsToConvert, gmAhkKeywdsToRename, gmAhkLoopRegKeywds ; Splashtexton and Splashtextoff is removed, but alternative gui code is available - global ahkCmdsToRemove := " - ( - #AllowSameLineComments - #CommentFlag - #Delimiter - #DerefChar - #EscapeChar - #LTrim - #MaxMem - #NoEnv - SetBatchLines - SetFormat - SoundGetWaveVolume - SoundSetWaveVolume - SplashImage - A_FormatInteger - A_FormatFloat - AutoTrim - )" ScriptOutput := "" lastLine := "" InCommentBlock := false InCont := 0 Cont_String := 0 - gOScriptStr := {} gOScriptStr := StrSplit(ScriptString, "`n", "`r") + + ;################################################################################ ; parse each line of the input script Loop { @@ -161,7 +150,6 @@ _convertLines(ScriptString, finalize:=!gUseMasking) ; 2024-06-26 RENAMED to ac O_Loopfield := gOScriptStr[gO_Index] Skip := false - Line := O_Loopfield gOrig_Line := Line RegExMatch(Line, "^(\s*)", &gIndentation) @@ -718,7 +706,9 @@ _convertLines(ScriptString, finalize:=!gUseMasking) ; 2024-06-26 RENAMED to ac Param.Push(oParam[A_index]) ; Checks for continuation section - if (gOScriptStr.Length > gO_Index and (SubStr(Trim(gOScriptStr[gO_Index + 1]), 1, 1) = "(" or RegExMatch(Trim(gOScriptStr[gO_Index + 1]), "i)^\s*\((?:\s*(?(?<=\s)(?!;)|(?<=\())(\bJoin\S*|[^\s)]+))*(? gO_Index + && (SubStr(Trim(gOScriptStr[gO_Index + 1]), 1, 1) = "(" + || RegExMatch(Trim(gOScriptStr[gO_Index + 1]), "i)^\s*\((?:\s*(?(?<=\s)(?!;)|(?<=\())(\bJoin\S*|[^\s)]+))*(? 0 and RegExMatch(gOScriptStr[A_Index - 1], "is)^[\s`n`r\t]*(return|exitapp|exit|reload).*") > 0) { ; Label + } else if (RegExMatch(RestString, "is)^(|;[^\n]*\n)*[\s`n`r\t]*\}?[\s`n`r\t]*([^;`n`r\s\{}\[\]\=:]+?\:\s).*") > 0 + and RegExMatch(gOScriptStr[A_Index - 1], "is)^[\s`n`r\t]*(return|exitapp|exit|reload).*") > 0) { ; Label Result .= LabelPointer = 1 ? "} `; V1toV2: Added Bracket before label`r`n" : "" LabelPointer := 0 RegexPointer := 0 - } else if (RegExMatch(RestString, "is)^[\s`n`r\t]*\}?[\s`n`r\t]*(`;[^\r\n]*|)([\s\n\r\t]*)$") > 0 and RegExMatch(gOScriptStr[A_Index - 1], "is)^[\s`n`r\t]*(return).*") > 0) { ; Label + } else if (RegExMatch(RestString, "is)^[\s`n`r\t]*\}?[\s`n`r\t]*(`;[^\r\n]*|)([\s\n\r\t]*)$") > 0 + and RegExMatch(gOScriptStr[A_Index - 1], "is)^[\s`n`r\t]*(return).*") > 0) { ; Label Result .= LabelPointer = 1 ? "} `; V1toV2: Added bracket in the end`r`n" : "" LabelPointer := 0 RegexPointer := 0 @@ -3803,21 +3826,21 @@ AddBracket(ScriptString) { } if (CommentCode=0){ if (HotkeyPointer = 1) { - if RegExMatch(RestString, "is)^\s*([\w]+?\([^\)]*\)[\s\n\r]*(`;[^\r\n]*|)([\s\n\r]*){).*") { ; Function declaration detection + if RegExMatch(RestString, "is)^\s*([\w]+?\([^\)]*\)\s*(`;[^\v]*|)(\s*){).*") { ; Function declaration detection ; not bulletproof perfect, but a start Result .= "} `; Added bracket before function`r`n" HotkeyPointer := 0 } } if (RegExMatch(Line, "i)^(\s*;).*") or RegExMatch(Line, "i)^(\s*)$")) { ; comment or empty - ; Do noting - } else if (RegExMatch(Line, "i)^\s*[\s\n\r\t]*((:[\s\*\?BCKOPRSIETXZ0-9]*:|)[^;\n\r\{}\[\:]+?\:\:).*") > 0) { ; Hotkey or string + ; Do nothing + } else if (RegExMatch(Line, "i)^\s*\s*((:[\s\*\?BCKOPRSIETXZ0-9]*:|)[^;\n\r\{}\[\:]+?\:\:).*") > 0) { ; Hotkey or string if (HotkeyPointer = 1) { Result .= "} `; V1toV2: Added Bracket before hotkey or Hotstring`r`n" HotkeyPointer := 0 } - if (RegExMatch(Line, "i)^\s*[\s\n\r\t]*((:[\s\*\?BCKOPRSIETXZ0-9]*:|)[^;\n\r\{}\[\:]+?\:\:\s*[^\s;].+)") > 0) { - ; oneline detected do noting + if (RegExMatch(Line, "i)^\s*\s*((:[\s\*\?BCKOPRSIETXZ0-9]*:|)[^;\n\r\{}\[\:]+?\:\:\s*[^\s;].+)") > 0) { + ; oneline detected do nothing } else { ; Hotkey detected start searching for start HotkeyStart := 1 @@ -3828,7 +3851,7 @@ AddBracket(ScriptString) { } else { if (RegExMatch(Line, "i)^\s*([{\(]).*")) { ; Hotkey is already good :) HotkeyPointer := 0 - } else if RegExMatch(RestString, "is)^\s*([\w]+?\([^\)]*\)[\s\n\r]*(`;[^\r\n]*|)([\s\n\r]*){).*") { ; Function declaration detection + } else if RegExMatch(RestString, "is)^\s*([\w]+?\([^\)]*\)\s*(`;[^\v]*|)(\s*){).*") { ; Function declaration detection ; Named Function Hotkeys do not need brackets ; https://lexikos.github.io/v2/docs/Hotstrings.htm ; Maybe add an * to the function? @@ -3842,7 +3865,7 @@ AddBracket(ScriptString) { Break } } - RegExReplace(RestString, "is)^(\s*)([\w]+?\([^\)]*\)[\s\n\r]*(`;[^\r\n]*|)([\s\n\r]*){).*", "$1") + RegExReplace(RestString, "is)^(\s*)([\w]+?\([^\)]*\)\s*(`;[^\v]*|)(\s*){).*", "$1") HotkeyPointer := 0 } else { Result .= "{ `; V1toV2: Added bracket`r`nglobal `; V1toV2: Made function global`r`n" ; Global - See #49 @@ -3852,16 +3875,18 @@ AddBracket(ScriptString) { } } if (HotkeyPointer = 1) { - if (RegExMatch(RestString, "is)^[\s\n\r\t]*((:[\s\*\?BCKOPRSIETXZ0-9]*:|)[^;\n\r\{}\[\]\=:]+?\:\:).*") > 0) { ; Hotkey or string + if (RegExMatch(RestString, "is)^\s*((:[\s\*\?BCKOPRSIETXZ0-9]*:|)[^;\n\r\{}\[\]\=:]+?\:\:).*") > 0) { ; Hotkey or string Result .= "} `; V1toV2: Added Bracket before hotkey or Hotstring`r`n" HotkeyPointer := 0 - } else if (RegExMatch(RestString, "is)^[\s\n\r\t]*((:[\s\*\?BCKOPRSIETXZ0-9]*:|)[^;\n\r\s\{}\[\:]+?\:\:?\s).*") > 0 and RegExMatch(gOScriptStr[A_Index - 1], "is)^[\s\n\r\t]*(return|exitapp|exit|reload).*") > 0) { ; Label + } else if (RegExMatch(RestString, "is)^\s*((:[\s\*\?BCKOPRSIETXZ0-9]*:|)[^;\n\r\s\{}\[\:]+?\:\:?\s).*") > 0 + && RegExMatch(gOScriptStr[A_Index - 1], "is)^\s*(return|exitapp|exit|reload).*") > 0) { ; Label Result .= "} `; V1toV2: Added Bracket before label`r`n" HotkeyPointer := 0 - } else if (RegExMatch(RestString, "is)^[\s\n\r\t]*(`;[^\r\n]*|)([\s\n\r\t]*)$") > 0 and RegExMatch(gOScriptStr[A_Index - 1], "is)^[\s\n\r\t]*(return|exitapp|exit|reload).*") > 0) { ; Label + } else if (RegExMatch(RestString, "is)^\s*(`;[^\v]*|)(\s*)$") > 0 + && RegExMatch(gOScriptStr[A_Index - 1], "is)^\s*(return|exitapp|exit|reload).*") > 0) { ; Label Result .= "} `; V1toV2: Added bracket in the end`r`n" HotkeyPointer := 0 - } else if (RegExMatch(RestString, "is)^[\s\n\r\t]*(#hotif).*") > 0){ ; #Hotif statement + } else if (RegExMatch(RestString, "is)^\s*(#hotif).*") > 0){ ; #Hotif statement Result .= "} `; V1toV2: Added bracket in the end`r`n" HotkeyPointer := 0 } @@ -3873,14 +3898,15 @@ AddBracket(ScriptString) { } ; Convert wrong labels - if RegexMatch(Line, "is)^\s*([^:\s\t,\{\}\[\]\(\)]+):(\s.*|)$") { - Label := GetV2Label(RegExReplace(Line, "is)(^\s*)([^:\s\t,\{\}\[\]\(\)]+):(\s.*|)$", "$2")) - Line := Regexreplace(Line, "is)(^\s*)([^:\s\t,\{\}\[\]\(\)]+):(\s.*$|$)", "$1" Label ":$3") + ; 2024-07-07 AMB CHANGED to detect all v1 valid characters, and convert to valid v2 labels + if (v1Label := getV1Label(Line)) { + Label := v1ToV2Label(v1Label) + Line := RegexReplace(Line, "(\h*)\Q" v1Label "\E(.*)", "$1" Label "$2") } - RestString := SubStr(RestString, InStr(RestString, "`n") + 1) - Result .= Line - Result .= A_Index != gOScriptStr.Length ? "`r`n" : "" + RestString := SubStr(RestString, InStr(RestString, "`n") + 1) + Result .= Line + Result .= A_Index != gOScriptStr.Length ? "`r`n" : "" } if (HotkeyPointer = 1) { Result .= "`r`n} `; V1toV2: Added bracket in the end`r`n" @@ -3892,23 +3918,23 @@ AddBracket(ScriptString) { /** * Creates a Map of labels who can be replaced by other labels (if labels are defined above each other) * @param {*} ScriptString string containing a script of multiple lines + * 2024-07-07, UPDATED to use common getV1Label() function that covers detection of all valid v1 label chars */ GetAltLabelsMap(ScriptString) { + gOScriptStr := StrSplit(ScriptString, "`n", "`r") LabelPrev := "" mAltLabels := Map() loop gOScriptStr.Length { Line := gOScriptStr[A_Index] - - if (RegExMatch(Line, "i)^(\s*;).*") or RegExMatch(Line, "i)^(\s*)$")) { ; comment or empty - continue - } else if (RegExMatch(Line, "is)^[\s\t]*([^;`n`r\s\{}\[\]\=:]+?\:)\s*(;.*|)$") > 0) { ; Label (no oneline) - Label := RegExReplace(Line, "is)^[\s\t]*([^;`n`r\s\{}\[\]\=:]+?)\:\s*(;.*|)$", "$1") - Result .= Label "-" LabelPrev "`r`n" + if (trim(removeLCs(line))='') { ; remove any line comments and whitespace + continue ; is blank line or line comment + } else if (v1Label := getV1Label(line)) { + LabelName := SubStr(v1Label, 1, -1) ; remove colon if (LabelPrev = "") { - LabelPrev := Label + LabelPrev := LabelName } else { - mAltLabels[Label] := LabelPrev + mAltLabels[LabelName] := LabelPrev } } else { LabelPrev := "" @@ -3922,10 +3948,57 @@ GetAltLabelsMap(ScriptString) { return mAltLabels } ;################################################################################ -; Corrects labels by adding "_" before it if it is not allowed. Other rules can be added later on like replacement of forbidden characters -GetV2Label(LabelName) { - NewLabelName := RegExReplace(LabelName, "^(\d.*)", "_$1") ; adds "_" before label if first char is number - return NewLabelName +v1ToV2Label(srcStr, returnColon:=true) { +; 2024-07-07 AMB, ADDED +; srcStr label MUST HAVE TRAILING COLON to be considered valid +; returns valid v2 label with or without colon based on flag [returnColon] + + ; makes sure it is a valid v1 label first + if (!v1Label := getV1Label(srcStr)) + return '' + + ; convert to valid v2 label + LabelName := RegExReplace(v1Label, "^(.*):$", "$1") ; remove colon if present + newName := "" + Loop Parse LabelName { + char := A_LoopField ; inspect one char at a time + needle := (A_Index=1) ? "(?i)(?:[^[:ascii:]]|[a-z_])" : "(?i)(?:[^[:ascii:]]|\w)" ; is char valid v2 char? + newName .= ((char~=needle) ? char : ((A_Index=1 && char~="\d") ? "_" char : "_")) ; replace invalid chars + } + return (newName . ((newName!="" && returnColon) ? ":" : "")) +} +;################################################################################ +isValidV2Label(srcStr, returnColon:=true, fix:=false) { +; 2024-07-07 AMB, ADDED +; srcStr label MUST HAVE TRAILING COLON to be considered valid +; returns extracted label if it is a valid V2 label +; or returns a label that has been corrected (if requested) +; or returns empty string if invalid + + srcStr := trim(removeLCs(srcStr)) ; remove line comments and trim ws + if ((srcStr~="i)^(?:[^[:ascii:]]|[a-z_])(?:[^[:ascii:]]|\w)*:$")) + return ((returnColon) ? srcStr : SubStr(srcStr, 1, -1)) + else if (fix) + return v1ToV2Label(srcStr, returnColon) + return '' +} +;################################################################################ +getV1Label(srcStr, returnColon:=true) { +; 2024-07-07 AMB, ADDED +; srcStr label MUST HAVE TRAILING COLON to be considered valid +; returns extracted label if it resembles a valid v1 label + + srcStr := trim(removeLCs(srcStr)) ; remove line comments and trim ws + if ((srcStr ~= '(?[^*/]+|\*[^/]|/[^*])*)(?>(?-2)(?-1))*(?:\*/|\Z))' ; block comments , gQSPtn := '(*UCP)(?m)(?:`'`'|`'(?>[^`'\v]+(?:(?<=``)`')?)+`'|""|"(?>[^"\v]+(?:(?<=``)")?)+")' ; quoted string (UPDATED 2024-06-17) - , gMQSPtn := buildPtn_MStr() ; v1 multiline string (non expression) ; , gBracePtn := '(\{(?>[^}{]+|(?-1))*\})' ; nested brace blocks (for future support) ;################################################################################ @@ -149,7 +148,7 @@ class NodeMap { mCode := m[], doPreMask_remove(&mCode) ; remove premask of comments and strings ;node.taggedCode := mCode ; (not used) - node.ConvCode := _convertLines(mCode,finalize:=1) ; now convert code to v2 + node.ConvCode := _convertLines(mCode,finalize:=1) ; now convert code to v2 code := RegExReplace(code, "\Q" mCode "\E", tag,,1,pos) } } @@ -416,6 +415,7 @@ class MLSTR extends PreMask ; 2024-06-30 ADDED, AMB ; masks multiline strings ; MLSTR class is custom masking and convert class for multiline strings +; called from Before_LineConverts() of ConvertFuncs.ahk doPreMask(&code) ; restore is handled in Convert() of ConvertFuncs.ahk MLSTR.MaskAll(&code, 'MQS', gMQSPtn) @@ -427,7 +427,7 @@ class MLSTR extends PreMask { ; 2024-06-30 ADDED, AMB ; restore multiline strings -; called from Convert() of ConvertFuncs.ahk +; called from After_LineConverts() of ConvertFuncs.ahk MLSTR.RestoreAll(&code, 'MQS') ; converts multiline string code as part of restore return @@ -440,6 +440,7 @@ class MLSTR extends PreMask ; 2024-06-02 UPDATED ; 2024-06-26 MOVED from ConvertFuncs.ahk. Just a proxy now ; masks quoted-strings + PreMask.MaskQS(&code) return } @@ -450,6 +451,7 @@ class MLSTR extends PreMask ; 2024-04-08 ADDED, andymbody ; 2024-06-26 MOVED from ConvertFuncs.ahk. Just a proxy now ; restores orig strings that were masked by maskStrings() + PreMask.RestoreQS(&code) return } @@ -457,7 +459,8 @@ class MLSTR extends PreMask maskBlocks(&code) ;################################################################################ { -; proxy to mask classes and functions +; proxy func to mask classes and functions + NodeMap.MaskBlocks(&code) return } @@ -465,7 +468,8 @@ class MLSTR extends PreMask restoreBlocks(&code) ;################################################################################ { -; proxy to restore classes and functions +; proxy func to restore classes and functions + NodeMap.RestoreBlocks(&code) return } @@ -495,14 +499,48 @@ class MLSTR extends PreMask PreMask.RestoreBC(&code) ; restore block comments return } +;################################################################################ + removeBCs(code) +;################################################################################ +{ +; 2024-07-07 AMB, ADDED - remove block comments from passed code + + return RegExReplace(code,gBCPtn) ; remove block comments +} +;################################################################################ + removeLCs(code) +;################################################################################ +{ +; 2024-07-07 AMB, ADDED - remove line comments from passed code + + return RegExReplace(code,gLCPtn) ; remove line comments +} +;################################################################################ + removeComments(code) +;################################################################################ +{ +; 2024-07-07 AMB, ADDED - remove block and line comments from passed code + + code := removeBCs(code) ; remove block comments + return removeLCs(code) ; remove line comments +} +;################################################################################ + removeMLStr(code) +;################################################################################ +{ +; 2024-07-07 AMB, ADDED - remove multi-line strings from passed code + + return RegExReplace(code, gMQSPtn) +} ;################################################################################ buildPtn_CLS() ;################################################################################ { -; CLASS-BLOCK pattern of my own design +; CLASS-BLOCK pattern + ; 2024-07-07 UPDATED comment needle to bypass escaped semicolon opt := '(*UCP)(?im)' ; pattern options - LC := '(?:(?<=\s|);[^\v]*)' ; line comment (allows lead ws to be consumed already) + LC := '(?:(?<=\s|)(?\s*' . CT . ')*' ; optional trailing comment or tag (MUST BE ATOMIC) - exclude := '(?:\b(?:IF|WHILE|LOOP)\b)(?=\()\K|' ; \K| - cool trick I made to prevent If/While/Loop from being captured + exclude := '(?:\b(?:IF|WHILE|LOOP)\b)(?=\()\K|' ; \K| - added to prevent If/While/Loop from being captured fName := '(?[_a-z]\w*)' ; fName - captures function/method name fArgG := '(?\((?(?>[^()]|\((?&Args)\))*+)\))' ; fArgG - argument group (in parenth), Args - indv args (allows multiline span) declare := fName . fArgG . TCT ; declare - function declaration @@ -543,21 +581,20 @@ class MLSTR extends PreMask { ; Multi-line string block ; non-expression version [ = ], not [ := ] -; does not support block comments between declaration and opening parenthesis +; does not currently support block comments between declaration and opening parenthesis ; can using masking to support them, or update needle to support raw block comments - ; 2024-07-06, UPDATED for better performance + ; 2024-07-07, UPDATED for better performance, updated comment needle to bypass escaped semicolon opt := '(*UCP)(?ims)' ; pattern options - LC := '(?:(?<=\s);[^\v]*)' ; line comment (allows lead ws to be consumed already) + LC := '(?:(?<=\s)(?(?:\s*+(?:' LC '|' TG '))*)' ; optional line comment OR tag var := '(?[_a-z]\w*)\h*=\h*' ; var - variable name body := '\h*\R+(?\h*\((?(?:\R*(?>[^\v]*))*?)\R+\h*+\))' ; body - block body with parentheses and guts pattern := opt . var . CT . body - ; changed to line-at-a-time vs character-at-a-time -> 4-5 times faster, only fooled if original code syntax is incorrect - ; (*UCP)(?ims)(?[_a-z]\w*)\h*=\h*(?(?:\s*+(?:(?:(?<=\s);[^\v]*)|(?:#TAG★\w+★#)))*+)\h*\R+(?\h*\((?(?:\R*(?>[^\v]*))*?)\R+\h*+\)) + ; changed to line-at-a-time rather than char-at-a-time -> 4-5 times faster, only fooled if original code syntax is incorrect + ; (*UCP)(?ims)(?[_a-z]\w*)\h*=\h*(?(?:\s*+(?:(?:(?<=\s)(?\h*\((?(?:\R*(?>[^\v]*))*?)\R+\h*+\)) ; A_Clipboard := pattern -; ExitApp return pattern } \ No newline at end of file diff --git a/tests/Test_Folder/Environment/LabelNames_01.ah1 b/tests/Test_Folder/Environment/LabelNames_01.ah1 new file mode 100644 index 00000000..cd0b2980 --- /dev/null +++ b/tests/Test_Folder/Environment/LabelNames_01.ah1 @@ -0,0 +1,40 @@ + +; these are all VALID V1 label names +; V1 allows all character except whitespace, comma, and escape char. +; V2 allows ascii alphanumeric and underscore. But cannot start with a number. Does allow non-ascii characters. + +; looks like a comment + `;notACommentAnymore: + +; looks like variable de-reference path + %A_Desktop%\List.txt: + +; looks like ahk directive + #Persistent: + +; begins with digit and has dot + 3.14: + +; valid in v2 + MYLABEL: + +; non-ascii characters (Valid in v2) + ★a★b★c: + +; non-ascii characters (NOT valid due to digit prefix) + 1★a★b★c: + +; begins with colon FIXED + :a: + +; looks like file path FIXED + c:\user\desktop\List.txt: + +; looks like regex needle FIXED + \w+\(.*?\): + +; looks like an if statement FIXED + if(a&&b){: + +; looks like a function FIXED + IThoughtIWasAFunc(param1:=""){: \ No newline at end of file diff --git a/tests/Test_Folder/Environment/LabelNames_01.ah2 b/tests/Test_Folder/Environment/LabelNames_01.ah2 new file mode 100644 index 00000000..426ef005 --- /dev/null +++ b/tests/Test_Folder/Environment/LabelNames_01.ah2 @@ -0,0 +1,40 @@ + +; these are all VALID V1 label names +; V1 allows all character except whitespace, comma, and escape char. +; V2 allows ascii alphanumeric and underscore. But cannot start with a number. Does allow non-ascii characters. + +; looks like a comment + __notACommentAnymore: + +; looks like variable de-reference path + _A_Desktop__List_txt: + +; looks like ahk directive + _Persistent: + +; begins with digit and has dot + _3_14: + +; valid in v2 + MYLABEL: + +; non-ascii characters (Valid in v2) + ★a★b★c: + +; non-ascii characters (NOT valid due to digit prefix) + _1★a★b★c: + +; begins with colon FIXED + _a: + +; looks like file path FIXED + c__user_desktop_List_txt: + +; looks like regex needle FIXED + _w________: + +; looks like an if statement FIXED + if_a__b__: + +; looks like a function FIXED + IThoughtIWasAFunc_param1______: \ No newline at end of file diff --git a/tests/Test_Folder/Environment/LabelNames_02.ah1 b/tests/Test_Folder/Environment/LabelNames_02.ah1 new file mode 100644 index 00000000..7525d16b --- /dev/null +++ b/tests/Test_Folder/Environment/LabelNames_02.ah1 @@ -0,0 +1,13 @@ +; Part of issue #201 +#Requires AutoHotkey v1.1.33+ +; show foo bar + +gosub 1)(miro#_r + +MsgBox, % "bar" +Return + +; label +1)(miro#_r: +MsgBox, % "foo" +Return \ No newline at end of file diff --git a/tests/Test_Folder/Environment/LabelNames_02.ah2 b/tests/Test_Folder/Environment/LabelNames_02.ah2 new file mode 100644 index 00000000..58f87e5d --- /dev/null +++ b/tests/Test_Folder/Environment/LabelNames_02.ah2 @@ -0,0 +1,16 @@ +; Part of issue #201 +#Requires Autohotkey v2.0 +; show foo bar + +_1__miro__r() + +MsgBox("bar") +Return + +; label +_1__miro__r() +{ ; V1toV2: Added bracket +global ; V1toV2: Made function global +MsgBox("foo") +Return +} ; V1toV2: Added bracket in the end \ No newline at end of file