v1 -> v2 Script Converter

Post your working scripts, libraries and tools for AHK v1.1 and older
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

27 Jul 2021, 17:37

AHK_user wrote:
27 Jul 2021, 16:53
Is somebody planning of updating this convertor to the new AHK V2 Beta?

I tried it out on a script, it did some conversion wel, but failed in a lot of lines. (msgbox, iniRead, loop read, iniwrite,inputbox,...)
This is of course normal because the AHK V2 Beta is just released and this convetor is 4 years old.
its open source, submit pull requests on github and i will accept them

the conversion format is described at the top of this file:

https://github.com/mmikeww/AHK-v2-script-converter/blob/master/ConvertFuncs.ahk

sometimes editing one line might fix the issue, other times the internals of the conversion might be required

be sure to also include updated tests with any submission

AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: v1 -> v2 Script Converter

28 Jul 2021, 16:17

guest3456 wrote:
27 Jul 2021, 17:37
AHK_user wrote:
27 Jul 2021, 16:53
Is somebody planning of updating this convertor to the new AHK V2 Beta?

I tried it out on a script, it did some conversion wel, but failed in a lot of lines. (msgbox, iniRead, loop read, iniwrite,inputbox,...)
This is of course normal because the AHK V2 Beta is just released and this convetor is 4 years old.
its open source, submit pull requests on github and i will accept them

the conversion format is described at the top of this file:

https://github.com/mmikeww/AHK-v2-script-converter/blob/master/ConvertFuncs.ahk

sometimes editing one line might fix the issue, other times the internals of the conversion might be required

be sure to also include updated tests with any submission
I Tried to convert it to AHK V2 Beta, but found it hard to convert it :facepalm:
I have added an alternative IsFunc to Github, because it is not supported anymore. And added some & prefix before ByRef variables.

I Think v2converter.ahk is now fully converted to Beta, but not the other libraries.

In the end, I finaly got it to work without errors, but the conversion dit not work anymore... :facepalm:

I hope it helps a little. It would be a nice script to make it easier to learn.
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

29 Jul 2021, 02:09

i didnt see your changes anywhere. can you link?

AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: v1 -> v2 Script Converter

01 Aug 2021, 23:15

guest3456 wrote:
29 Jul 2021, 02:09
i didnt see your changes anywhere. can you link?
I am a Github noob :lol: I tried to post them agian on Github.

But I decided to focus on the convert function, as it is the heart of the script.

I still cant get it to work, (I think I almost fixed it, but I find It quite complicated )

I began writing my own fuction convert2, with the focus on converting v1 gui and menu code to V2 beta, as this was not yet Implemented.
It is not at all complete, but already works quite well for simple code, you can test it out :D :D :D

It would be nice if the convert function would be fixed. Then I would probably be able to figure out how to update it to change it so It`s converts to V2 beta.

Code: Select all

#Requires AutoHotKey v2.0-beta.1
#SingleInstance Force

XButton1::
{
	ClipSaved := ClipboardAll()   ; Save the entire clipboard to a variable of your choice.
	A_Clipboard := ""
	Send "^c"
	
	if !ClipWait(3){
		DebugWindow( "error`n",Clear:=0)
		return
	}
	Clipboard1 := A_Clipboard
	A_Clipboard := ClipSaved   ; Restore the original clipboard. Note the use of A_Clipboard (not ClipboardAll).
	ClipSaved := ""  ; Free the memory in case the clipboard was very large.
	
	ConvertedCode := Convert2(Clipboard1)
	;DebugWindow(ConvertedCode "`n",Clear:=0) ; For AHK Studio Users
	MsgBox(ConvertedCode)
	A_Clipboard := ConvertedCode
	return
}	

DebugWindow(Text,Clear:=0,LineBreak:=0,Sleep:=0,AutoHide:=0){
	x:=ComObjActive("{DBD5A90A-A85C-11E4-B0C7-43449580656B}")
	x.DebugWindow(Text,Clear,LineBreak,Sleep,AutoHide)
}


Convert2(ScriptString){
	ScriptStringResult:=""
	; Default Gui name
	GuiNameDefault := "MyGui"
	GuiList := "|"
	MenuList := "|"
	
	Loop Parse ScriptString, "`n", "`r"
	{
		Line := A_LoopField
		
		if RegExMatch(Line, "^.*?[^``];(.*)$")
		{
			Comment := RegExReplace(Line, "i)^.*?[^``];(.*)$", "$1", &RegExCount1)
			Line := RegExReplace(Line, "i)^(.*?[^``])\s*;(.*)$", "$1", &RegExCount1)
		}
		else{
			Comment := ""
		}
		
		if RegExMatch(Line, "i)^\s*Gui\s*[,\s]\s*.*$"){
			ControlLabel:=""
			ControlName:=""
			ControlObject:=""
			if RegExMatch(Line, "i)^\s*Gui\s*[\s,]\s*[^,\s]*:.*$")
			{
				GuiNameLine := RegExReplace(Line, "i)^\s*Gui\s*[\s,]\s*([^,\s]*):.*$", "$1", &RegExCount1)
				Line := RegExReplace(Line, "i)^(\s*Gui\s*[\s,]\s*)([^,\s]*):(.*)$", "$1$3", &RegExCount1)	
			}
			Else{
				GuiNameLine:= GuiNameDefault
			}
			if (RegExMatch(GuiNameLine, "^\d$")){
				GuiNameLine := "Gui" GuiNameLine
			}
			Var1 := RegExReplace(Line, "i)^\s*Gui\s*[,\s]\s*([^,]*).*$", "$1", &RegExCount1)
			Var2 := RegExReplace(Line, "i)^\s*Gui\s*,\s*([^,]*)\s*,\s*([^,]*).*", "$2", &RegExCount2)
			Var3 := RegExReplace(Line, "i)^\s*Gui\s*,\s*([^,]*),\s*([^,]*)\s*,\s*([^,]*).*$", "$3", &RegExCount3)
			Var4 := RegExReplace(Line, "i)^\s*Gui\s*,\s*([^,]*),\s*([^,]*)\s*,\s*([^,]*),([^;]*).*", "$4", &RegExCount4)
			Var1 := Trim(Var1)
			Var2 := Trim(Var2)
			Var3 := Trim(Var3)
			Var4 := Trim(Var4)
			
			if RegExMatch(Var3, "\bg[\w]*\b"){
				ControlLabel:= RegExReplace(Var3, "^.*\bg([\w]*)\b.*$", "$1")
				Var3:= RegExReplace(Var3, "^(.*)\bg([\w]*)\b(.*)$", "$1$3")
			}
			else if (RegExMatch(Var3, "\bDefault\b") and RegExCount4){
				ControlLabel:= var2 RegExReplace(Var4, "\s", "")
			}
			if RegExMatch(Var3, "\vg[\w]*\b"){
				ControlName:= RegExReplace(Var3, "^.*\vg([\w]*)\b.*$", "$1")
			}
			
			if !InStr(GuiList, "|" GuiNameLine "|"){
				GuiList.= GuiNameLine "|"
				ScriptStringResult.= GuiNameLine ":= Gui()`n"
			}
			
			if(RegExMatch(Var1, "i)^tab[23]?$")){
				ScriptStringResult.= "Tab.UseTab(" Var2 ")`n"
				continue
			}
			if(Var1="Show"){
				if (RegExCount3){
					ScriptStringResult.= GuiNameLine ".Name :=" ToStringExpr(Var3) "`n"
					Var3:=""
					RegExCount3:=0
				}
				Var1 := "Show"
			}
			
			if(RegExMatch(Var2, "i)^tab[23]?$")){
				ScriptStringResult.= "Tab := " 
			}
			if(var1 = "Submit"){
				ScriptStringResult.= "oSaved := " 
			}
			
			if(var1 = "Add" and (var2="Button" or ControlLabel!="")){
				ControlObject := "my" var2
				ScriptStringResult.= ControlObject " := " 
			}
			ScriptStringResult.= GuiNameLine "." 
			
			if (Var1="Menu"){
				ScriptStringResult.=  "MenuBar := " Var2
			}
			else{
				if (RegExCount1){
					if (RegExMatch(Var1, "^\s*[-\+]\w*")){
						ScriptStringResult.= "Opt(" ToStringExpr(Var1)
					}
					Else{
						ScriptStringResult.= Var1 "("
					}
				}
				if (RegExCount2){
					ScriptStringResult.= ToStringExpr(Var2)
				}
				if (RegExCount3){
					ScriptStringResult.= ", " ToStringExpr(Var3)
				}
				else if (RegExCount4){
					ScriptStringResult.= ", "
				}
				if (RegExCount4){
					if(RegExMatch(Var2, "i)^tab[23]?$") or Var2="ListView"){
						ScriptStringResult.= ", [" 
						oVar4 :=""
						Loop Parse Var4, "|", " "
						{
							oVar4.= oVar4="" ? ToStringExpr(A_LoopField) : ", " ToStringExpr(A_LoopField)
						}
						ScriptStringResult.= oVar4 "]"
					}
					else{
						ScriptStringResult.= ", " ToStringExpr(Var4)
					}
				}
				if (RegExCount1){
					ScriptStringResult.= ")"
				}
				
			}
			ScriptStringResult.= Comment!="" ? " `;" Comment : ""
			
			if(ControlObject!=""){
				ScriptStringResult.= "`n" ControlObject ".OnEvent(`"Click`", " ControlLabel ")"
			}
			
		}
		else if RegExMatch(Line, "i)^\s*Menu\s*[,\s]\s*.*$"){
			
			menuNameLine := RegExReplace(Line, "i)^\s*Menu\s*[,\s]\s*([^,]*).*$", "$1", &RegExCount1)
			Var2 := RegExReplace(Line, "i)^\s*Menu\s*[,\s]\s*([^,]*)\s*,\s*([^,]*).*", "$2", &RegExCount2)
			Var3 := RegExReplace(Line, "i)^\s*Menu\s*[,\s]\s*([^,]*),\s*([^,]*)\s*,\s*([^,]*).*$", "$3", &RegExCount3)
			Var4 := RegExReplace(Line, "i)^\s*Menu\s*[,\s]\s*([^,]*),\s*([^,]*)\s*,\s*([^,]*),\s*:?([^;,]*).*", "$4", &RegExCount4)
			Var5 := RegExReplace(Line, "i)^\s*Menu\s*[,\s]\s*([^,]*),\s*([^,]*)\s*,\s*([^,]*),\s*:?([^;,]*)\s*,\s*([^,]*).*", "$5", &RegExCount5)
			menuNameLine := Trim(menuNameLine)
			Var2 := Trim(Var2)
			Var3 := Trim(Var3)
			Var4 := Trim(Var4)
			
			if (Var2="Add" and RegExCount3 and !RegExCount4){
				Var4 := Var3
				RegExCount4 := RegExCount3
			}
			if (Var3="Icon"){
				Var3 := "SetIcon"
			}
			if !InStr(menuList, "|" menuNameLine "|"){
				menuList.= menuNameLine "|"
				
				if (menuNameLine="Tray"){
					ScriptStringResult.= menuNameLine ":= A_TrayMenu`n"
				}
				else{
					ScriptStringResult.= menuNameLine ":= Menu()`n"
				}
			}
			
			ScriptStringResult.= menuNameLine "." 
			
			if (RegExCount2){
				ScriptStringResult.= Var2 "("
			}
			if (RegExCount3){
				ScriptStringResult.= ToStringExpr(Var3)
			}
			else if (RegExCount4){
				ScriptStringResult.= ", "
			}
			if (RegExCount4){
				if (Var2="Add"){
					ScriptStringResult.= ", " Var4
				}
				else{
					ScriptStringResult.= ", " ToStringExpr(Var4)
				}
			}
			if (RegExCount5){
				ScriptStringResult.= ", " ToStringExpr(Var5)
			}
			if (RegExCount1){
				ScriptStringResult.= ")"
			}
			ScriptStringResult.= Comment!="" ? " `;" Comment : ""
			
		}
		else{
			ScriptStringResult.= A_LoopField
		}
		ScriptStringResult.= "`n"
	}
	return ScriptStringResult
}
;~ Gui, Add, Text,xm, X:
;~ MyGui.Add("Text",, "WinSearch:")


; =============================================================================
; Convert traditional statements to expressions
;    Don't pass whole commands, instead pass one parameter at a time
; =============================================================================
ToExp(Text)
{
	static qu := "`"" ; Constant for double quotes
	static bt := "``" ; Constant for backtick to escape
	Text := Trim(Text, " `t")
	DeRef := 0
	
	If (Text = "")       ; If text is empty
		return (qu . qu)  ; Two double quotes
	else if (SubStr(Text, 1, 2) = "`% ")    ; if this param was a forced expression
		return SubStr(Text, 3)               ; then just return it without the %
	
	Text := StrReplace(Text, qu, bt . qu)    ; first escape literal quotes
	Text := StrReplace(Text, bt . ",", ",")  ; then remove escape char for comma
	;msgbox text=%text%
	
	if InStr(Text, "`%")        ; deref   %var% -> var
	{
		;msgbox %text%
		TOut := ""
		;Loop % StrLen(Text)
		Loop Parse Text
		{
			;Symbol := Chr(NumGet(Text, (A_Index-1)*2, "UChar"))
			Symbol := A_LoopField
			If Symbol == "`%"
			{
				If (DeRef := !DeRef) && (A_Index != 1)
					TOut .= qu . " . "
				else If (!DeRef) && (A_Index != StrLen(Text))
					TOut .= " . " . qu
			}
			else
			{
				If A_Index = 1
					TOut .= qu
				TOut .= Symbol
			}
		}
		If Symbol != "`%"
			TOut .= (qu) ; One double quote
	}
	else if Text is "number"
	{
		;msgbox %text%
		TOut := Text+0
	}
	else      ; wrap anything else in quotes
	{
		;msgbox text=%text%`ntout=%tout%
		TOut := qu . Text . qu
	}
	return (TOut)
}

; same as above, except numbers are excluded. 
; that is, a number will be turned into a quoted number.  3 -> "3"
ToStringExpr(Text)
{
	static qu := "`"" ; Constant for double quotes
	static bt := "``" ; Constant for backtick to escape
	Text := Trim(Text, " `t")
	DeRef := 0
	If (Text = "")       ; If text is empty
		return (qu . qu)  ; Two double quotes
	else if (SubStr(Text, 1, 2) = "`% ")    ; if this param was a forced expression
		return SubStr(Text, 3)               ; then just return it without the %
	
	Text := StrReplace(Text, qu, bt . qu)    ; first escape literal quotes
	Text := StrReplace(Text, bt . ",", ",")  ; then remove escape char for comma
	;msgbox text=%text%
	
	if InStr(Text, "`%")        ; deref   %var% -> var
	{
		TOut := ""
		;Loop % StrLen(Text)
		Loop Parse Text
		{
			;Symbol := Chr(NumGet(Text, (A_Index-1)*2, "UChar"))
			Symbol := A_LoopField
			If Symbol == "`%"
			{
				If (DeRef := !DeRef) && (A_Index != 1)
					TOut .= qu . " . "
				else If (!DeRef) && (A_Index != StrLen(Text))
					TOut .= " . " . qu
			}
			else
			{
				If A_Index = 1
					TOut .= qu
				TOut .= Symbol
			}
		}
		
		If Symbol != "`%"
			TOut .= (qu) ; One double quote
	}
	;else if type(Text+0) != "String"
	;{
		;msgbox %text%
		;TOut := Text+0
	;}
	else      ; wrap anything else in quotes
	{
		;msgbox text=%text%`ntout=%tout%
		TOut := qu . Text . qu
	}
	return (TOut)
}

; change   "text" -> text
RemoveSurroundingQuotes(text)
{
   if (SubStr(text, 1, 1) = "`"") && (SubStr(text, -1) = "`"")
      return SubStr(text, 2, -1)
   return text
}

; change   %text% -> text
RemoveSurroundingPercents(text)
{
   if (SubStr(text, 1, 1) = "`%") && (SubStr(text, -1) = "`%")
      return SubStr(text, 2, -1)
   return text
}

; check if a param is empty
IsEmpty(param)
{
   if (param = '') || (param = '""')   ; if its an empty string, or a string containing two double quotes
      return true
   return false
}

; =============================================================================
; Command formatting functions
;    They all accept an array of parameters and return command(s) in text form
;    These are only called in one place in the script and are called dynamicly
; =============================================================================
_WinGetActiveStats(p) {
   Out := format_v("{1} := WinGetTitle(`"A`")", p) . "`r`n"
   Out .= format_v("WinGetPos {4}, {5}, {2}, {3}, `"A`"", p)
   return Out   
}

_EnvAdd(p) {
   if !IsEmpty(p[3])
      return format_v("{1} := DateAdd({1}, {2}, {3})", p)
   else
      return format_v("{1} += {2}", p)
}

_EnvSub(p) {
   if !IsEmpty(p[3])
      return format_v("{1} := DateDiff({1}, {2}, {3})", p)
   else
      return format_v("{1} -= {2}", p)
}

_StringGetPos(p)
{
   ;msgbox, % p.Length() "`n" p[1] "`n" p[2] "`n" p[3] "`n" p[4] "`n" p[5]
   if IsEmpty(p[4]) && IsEmpty(p[5])
      return format_v("{1} := InStr({2}, {3}) - 1", p)

   ; modelled off of:   https://github.com/Lexikos/AutoHotkey_L/blob/master/source/script.cpp#L14181
   else
   {
      p[5] := p[5] ? p[5] : 0   ; 5th param is 'Offset' aka starting position. set default value if none specified

      p4FirstChar := SubStr(p[4], 1, 1)
      p4LastChar := SubStr(p[4], -1)
      ;msgbox, % p[4] "`np4FirstChar=" p4FirstChar "`np4LastChar=" p4LastChar
      if (p4FirstChar = "`"") && (p4LastChar = "`"")   ; remove start/end quotes, would be nice if a non-expr was passed in
      {
         p4noquotes := SubStr(p[4], 2, -1)
         p4char1 := SubStr(p4noquotes, 1, 1)
         occurences := SubStr(p4noquotes, 2)
         ;msgbox, % p[4]
         p[4] := occurences ? occurences : 1
        
         if (StrUpper(p4char1) = "R") || (p4noquotes = "1")
            return format_v("{1} := InStr({2}, {3}, (A_StringCaseSense=`"On`") ? true : false, -1*(({5})+1), {4}) - 1", p)
         else
            return format_v("{1} := InStr({2}, {3}, (A_StringCaseSense=`"On`") ? true : false, ({5})+1, {4}) - 1", p)
      }
      else
      {
         ; else then a variable was passed (containing the "L#|R#" string),
         ;      or literal text converted to expr, something like:   "L" . A_Index
         ; output something anyway even though it won't work, so that they can see something to fix
         return format_v("{1} := InStr({2}, {3}, (A_StringCaseSense=`"On`") ? true : false, ({5})+1, {4}) - 1", p)
      }
   }
}


_StringMid(p)
{
   if IsEmpty(p[4]) && IsEmpty(p[5])
      return format_v("{1} := SubStr({2}, {3})", p)
   else if IsEmpty(p[5])
      return format_v("{1} := SubStr({2}, {3}, {4})", p)
   else
   {
      ;msgbox, % p[5] "`n" SubStr(p[5], 1, 2)
      ; any string that starts with 'L' is accepted
      if (StrUpper(SubStr(p[5], 2, 1) = "L"))
         return format_v("{1} := SubStr(SubStr({2}, 1, {3}), -{4})", p)
      else
      {
         out := format_v("if (SubStr({5}, 1, 1) = `"L`")", p) . "`r`n"
         out .= format_v("    {1} := SubStr(SubStr({2}, 1, {3}), -{4})", p) . "`r`n"
         out .= format_v("else", p) . "`r`n"
         out .= format_v("    {1} := SubStr({2}, {3}, {4})", p)
         return out
      }
   }
}


_StrReplace(p)
{
   ; v1
   ; StringReplace, OutputVar, InputVar, SearchText [, ReplaceText, ReplaceAll?]
   ; v2 obsolete
   ; StrReplace, OutputVar, Haystack, SearchText [, ReplaceText, OutputVarCount, Limit = -1]
   ; v2
   ; OutputVar := StrReplace(Haystack, SearchText , ReplaceText, OutputVarCount, Limit := -1)

   if IsEmpty(p[4]) && IsEmpty(p[5])
      return format_v("{1} := StrReplace({2}, {3},,, 1)", p)
   else if IsEmpty(p[5])
      return format_v("{1} := StrReplace({2}, {3}, {4},, 1)", p)
   else
   {
      p5char1 := SubStr(p[5], 1, 1)
      ; MsgBox(p[5] "`n" p5char1)

      if (p[5] = "UseErrorLevel")    ; UseErrorLevel also implies ReplaceAll
         return format_v("{1} := StrReplace({2}, {3}, {4}, ErrorLevel)", p)
      else if (p5char1 = "1") || (StrUpper(p5char1) = "A")
         ; if the first char of the ReplaceAll param starts with '1' or 'A'
         ; then all of those imply 'replace all'
         ; https://github.com/Lexikos/AutoHotkey_L/blob/master/source/script2.cpp#L7033
         return format_v("{1} := StrReplace({2}, {3}, {4})", p)
   }
}


; =============================================================================



format_v(f, v)
{
    local out, arg, i, j, s, m, key, buf, c, type, p, O_
    out := "" ; To make #Warn happy.
    VarSetStrCapacity(&arg, 8), j := 1, VarSetStrCapacity(&s, StrLen(f)*2.4)  ; Arbitrary estimate (120% * size of Unicode char).
    ;~ O_ := A_AhkVersion >= "2" ? "" : "O)"  ; Seems useful enough to support v1.
    O_ := "" ; Always run with V2 not compatible anymore with V1
	
    while i := RegExMatch(f, O_ "\{((\w+)(?::([^*`%{}]*([scCdiouxXeEfgGaAp])))?|[{}])\}", &m, j)  ; For each {placeholder}.
    {
        out .= SubStr(f, j, i-j)  ; Append the delimiting literal text.
        j := i + m.Len[0]  ; Calculate next search pos.
        if (m.1 = "{" || m.1 = "}") {  ; {{} or {}}.
            out .= m.2
            continue
        }
        key := (Type(m.2) = "String") ? m.2 : m.2+0  ; +0 to convert to pure number.
        if !v.HasKey(key) {
            out .= m.0  ; Append original {} string to show the error.
            continue
        }
        if m.3 = "" {
            out .= v[key]  ; No format specifier, so just output the value.
            ;if InStr(out, "var")
            ;   msgbox, %out%
            continue
        }
        if (type := m.4) = "s"
            NumPut("UPtr", (p := v.GetAddress(key)) ? p : &(s := v[key] ""), arg)
        else if InStr("cdioux", type)  ; Integer types.
            NumPut("UPtr", v[key], arg, "int64") ; 64-bit in case of something like {1:I64i}.
        else if InStr("efga", type)  ; Floating-point types.
            NumPut("UPtr", v[key], arg, "double")
        else if (type = "p")  ; Pointer type.
            NumPut("UPtr", v[key], arg)
        else {  ; Note that this doesn't catch errors like "{1:si}".
            out .= m.0  ; Output m unaltered to show the error.
            continue
        }
        ; MsgBox % "key=" key ",fmt=" m.3 ",typ=" m.4 . (m.4="s" ? ",str=" NumGet(arg) ";" (&s) : "")
        if (c := DllCall("msvcrt\_vscwprintf", "wstr", "`%" m.3, "ptr", &arg, "cdecl")) >= 0  ; Determine required buffer size.
          && DllCall("msvcrt\_vsnwprintf", "wstr", &buf, "ptr", VarSetStrCapacity(&buf, ++c*2)//2, "wstr", "`%" m.3, "ptr", &arg, "cdecl") >= 0 {  ; Format string into buf.
            out .= buf  ; Append formatted string.
            continue
        }
    }
    out .= SubStr(f, j)  ; Append remainder of format string.
    return out
}

IsFunc(FunctionName){
	Try{
		return %FunctionName%.MaxParams
	}
	Catch{
		return 0
	}
	return
}
Last edited by AHK_user on 02 Aug 2021, 05:10, edited 1 time in total.
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

01 Aug 2021, 23:47

AHK_user wrote:
01 Aug 2021, 23:15
I am a Github noob :lol: I tried to post them agian on Github.
are you the guy who submitted the pull request?

User avatar
JoeSchmoe
Posts: 129
Joined: 08 Dec 2014, 08:58

Re: v1 -> v2 Script Converter

02 Aug 2021, 01:12

What I would really love to see is a v1 -> v2 script converter that can convert itself from v1 to v2....
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

02 Aug 2021, 01:14

JoeSchmoe wrote:
02 Aug 2021, 01:12
What I would really love to see is a v1 -> v2 script converter that can convert itself from v1 to v2....
what does this mean

robodesign
Posts: 932
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: v1 -> v2 Script Converter

02 Aug 2021, 02:50

Is this project still in development? The github project page looks outdated.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: v1 -> v2 Script Converter

02 Aug 2021, 05:32

guest3456 wrote:
02 Aug 2021, 01:14
JoeSchmoe wrote:
02 Aug 2021, 01:12
What I would really love to see is a v1 -> v2 script converter that can convert itself from v1 to v2....
what does this mean
:lol:
He means that I would funny to convert the v1 to v2 convertor (Written in V1) to V2 with itself.
It would be indeed a great proof of concept.
robodesign wrote:
02 Aug 2021, 02:50
Is this project still in development? The github project page looks outdated.
I tried to update the function convert() to work in AHK V2 but did not got it to work properly :facepalm: .
I`ll post my version when I am at home, I think I got it almost working, but function format_v still has some errors.

The function that I created convert2() is maily for the menu and gui commands that are now converted to objects.
guest3456 wrote:
01 Aug 2021, 23:47
AHK_user wrote:
01 Aug 2021, 23:15
I am a Github noob :lol: I tried to post them agian on Github.
are you the guy who submitted the pull request?
Yes dmtr99 is my github account.
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

02 Aug 2021, 10:22

robodesign wrote:
02 Aug 2021, 02:50
Is this project still in development? The github project page looks outdated.
i'm starting to try to fix it for v2beta. why not contribute add make pull requests?
AHK_user wrote:
02 Aug 2021, 05:32
:lol:
He means that I would funny to convert the v1 to v2 convertor (Written in V1) to V2 with itself.
It would be indeed a great proof of concept.
the converter is already written in v2 and has been for years.
AHK_user wrote:
02 Aug 2021, 05:32
but function format_v still has some errors.
format_v() was used from way back when, i have no idea if it works the same as the built-in format(). can anyone confirm?
AHK_user wrote:
02 Aug 2021, 05:32
Yes dmtr99 is my github account.
ok i pulled in 2 of your commits into the main branch

User avatar
JoeSchmoe
Posts: 129
Joined: 08 Dec 2014, 08:58

Re: v1 -> v2 Script Converter

02 Aug 2021, 14:02

guest3456 wrote:
02 Aug 2021, 10:22
AHK_user wrote:
02 Aug 2021, 05:32
:lol:
He means that I would funny to convert the v1 to v2 convertor (Written in V1) to V2 with itself.
It would be indeed a great proof of concept.
the converter is already written in v2 and has been for years.
Yup, sorry that wasn't clear... I can't blame you for writing it in v2!
guest3456 wrote:
02 Aug 2021, 10:22
i'm starting to try to fix it for v2beta. why not contribute add make pull requests?
That's tremendous. I will happily test it on my main v1 script. I'm eager to finish the conversion to v2.

True confession - I've never done a pull request in my life or even made a private repository. However, if you get this up and running with v2beta, I will do my best. I took a look at the code and it was well enough organized and commented that it wasn't hard to figure out the broad strokes of how the script works. It does involve some complex regexes to identify what needs to be replaced. With that said, it doesn't look like it's something outside the scope of what even a casual coder like myself could work with. I'll say upfront that I'm completely overwhelmed with work, though. I just feel the community really needs a good conversion script.
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

02 Aug 2021, 14:22

JoeSchmoe wrote:
02 Aug 2021, 14:02
True confession - I've never done a pull request in my life or even made a private repository. However, if you get this up and running with v2beta, I will do my best. I took a look at the code and it was well enough organized and commented that it wasn't hard to figure out the broad strokes of how the script works. It does involve some complex regexes to identify what needs to be replaced. With that said, it doesn't look like it's something outside the scope of what even a casual coder like myself could work with. I'll say upfront that I'm completely overwhelmed with work, though. I just feel the community really needs a good conversion script.
first we need to get the converter script itself working again on v2beta

once the script is functional and executable again, then we can work on updating the actual conversion of the syntax from v1 -> v2, including the Test scripts. this process should be easier for the majority of contributors. we will never expect 100% conversion as thats impossible. but the idea is to remove a lot of the tedious changes and at least give users a head start

AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: v1 -> v2 Script Converter

03 Aug 2021, 05:34

guest3456 wrote:
02 Aug 2021, 14:22
JoeSchmoe wrote:
02 Aug 2021, 14:02
True confession - I've never done a pull request in my life or even made a private repository. However, if you get this up and running with v2beta, I will do my best. I took a look at the code and it was well enough organized and commented that it wasn't hard to figure out the broad strokes of how the script works. It does involve some complex regexes to identify what needs to be replaced. With that said, it doesn't look like it's something outside the scope of what even a casual coder like myself could work with. I'll say upfront that I'm completely overwhelmed with work, though. I just feel the community really needs a good conversion script.
first we need to get the converter script itself working again on v2beta

once the script is functional and executable again, then we can work on updating the actual conversion of the syntax from v1 -> v2, including the Test scripts. this process should be easier for the majority of contributors. we will never expect 100% conversion as thats impossible. but the idea is to remove a lot of the tedious changes and at least give users a head start
I agree.

At the moment I understand more of less most of the script working, except the function format_v that handles a very important part.

I think if somebody can help me to convert it, I can make it work again, I think I am almost there!!! :D

Do somebody knows the V2 alternative of .GetAddress? or is it still valid?

(I could not find in the documentation in what it changed.)

Changes:
; VarSetCapacity( => VarSetStrCapacity(&
; v.HasKey(key) => v.HasProp(key)

Code: Select all

format_v(f, v)
{
    local out, arg, i, j, s, m, key, buf, c, type, p, O_
    out := "" ; To make #Warn happy.
	
	; Changed: VarSetCapacity = VarSetStrCapacity
    VarSetStrCapacity(&arg, 8)
	j := 1
	VarSetStrCapacity(&s, StrLen(f)*2.4)  ; Arbitrary estimate (120% * size of Unicode char).
	
    O_ := A_AhkVersion >= "2" ? "" : "O)"  ; Seems useful enough to support v1.
    while i := RegExMatch(f, O_ "\{((\w+)(?::([^*`%{}]*([scCdiouxXeEfgGaAp])))?|[{}])\}", &m, j)  ; For each {placeholder}.
    {
        out .= SubStr(f, j, i-j)  ; Append the delimiting literal text.
        j := i + m.Len[0]  ; Calculate next search pos.
        if (m.1 = "{" || m.1 = "}") {  ; {{} or {}}.
            out .= m.2
            continue
        }
        key := (Type(m.2) = "String") ? m.2 : m.2+0  ; +0 to convert to pure number.
		
		; Changed: v.HasKey(key) => v.HasProp(key)
        if !v.HasProp(key) {
            out .= m.0  ; Append original {} string to show the error.
            continue
        }
        if m.3 = "" {
            out .= v[key]  ; No format specifier, so just output the value.
            ;if InStr(out, "var")
            ;   msgbox, %out%
            continue
        }
        if (type := m.4) = "s"
            NumPut((p := v.GetAddress(key)) ? p : &(s := v[key] ""), arg)
        else if InStr("cdioux", type)  ; Integer types.
            NumPut(v[key], arg, "int64") ; 64-bit in case of something like {1:I64i}.
        else if InStr("efga", type)  ; Floating-point types.
            NumPut(v[key], arg, "double")
        else if (type = "p")  ; Pointer type.
            NumPut(v[key], arg)
        else {  ; Note that this doesn't catch errors like "{1:si}".
            out .= m.0  ; Output m unaltered to show the error.
            continue
        }
        ; MsgBox % "key=" key ",fmt=" m.3 ",typ=" m.4 . (m.4="s" ? ",str=" NumGet(arg) ";" (&s) : "")
        if (c := DllCall("msvcrt\_vscwprintf", "wstr", "`%" m.3, "ptr", &arg, "cdecl")) >= 0  ; Determine required buffer size.
          && DllCall("msvcrt\_vsnwprintf", "wstr", buf, "ptr", VarSetStrCapacity(&buf, ++c*2)//2, "wstr", "`%" m.3, "ptr", &arg, "cdecl") >= 0 {  ; Format string into buf.
            out .= buf  ; Append formatted string.
            continue
        }
    }
    out .= SubStr(f, j)  ; Append remainder of format string.
    return out
}
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

03 Aug 2021, 06:23

AHK_user wrote:
03 Aug 2021, 05:34
except the function format_v that handles a very important part.
i'm in the process of trying to get the converter working on v2beta1 too... i'm curious to see how our changes line up. hate to have us both duplicating work though. maybe you're closer than me. i finally got the yunit testing stuff fixed

like i said, i'm not sure if format_v() is anything special or not, and maybe it was written before the built-in format() was added. does this work for you?

Code: Select all

format_v(p*)
{
   format(p*)
}

format_v(f, v)
{
   format(f, v*)
}
AHK_user wrote:
03 Aug 2021, 05:34
Do somebody knows the V2 alternative of .GetAddress? or is it still valid?
lexikos briefly mentions .GetAddress in this thread:
https://www.autohotkey.com/boards/viewtopic.php?f=37&t=51356
might need to use a Buffer object

guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

03 Aug 2021, 11:12

AHK_user wrote:
03 Aug 2021, 05:34
I agree.

At the moment I understand more of less most of the script working, except the function format_v that handles a very important part.

I think if somebody can help me to convert it, I can make it work again, I think I am almost there!!!
ok sir i've completed the upgrade to v2beta1

you can see the changes i made here:

https://github.com/mmikeww/AHK-v2-script-converter/commits/master

i've removed the format_v() function and instead now we use the built in format()

this means now that the converter script will execute successfully using the v2beta1 interpreter. however the actual v1->v2 conversion is still converting based on the old v2-a076 syntax. so now comes the process of upgrading the conversion parser to handle all of these commands/funcs/syntaxes, as well as including more Tests for each change. when you are ready to try to incorporate your gui conversion, you can submit pull request. i don't know how much of this i will undertake or not. hopefully the community can contribute

robodesign
Posts: 932
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: v1 -> v2 Script Converter

03 Aug 2021, 11:37

@AHK_user.. .please incorporate the GUI stuff.

I plan on trying to convert my ahk script to v2 and it has 61000 lines....much of it is GUI stuff.

@guest3456 .thank you for the work!

Best regards, Marius.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

03 Aug 2021, 11:46

robodesign wrote:
03 Aug 2021, 11:37
@AHK_user.. .please incorporate the GUI stuff.
incorporating the GUI stuff will likely be a big integration

in contrast to adding conversion for simple command, where all that is required is adding the definition for conversion, and writing some Tests. see this (outdated) example for SplitPath:

https://github.com/mmikeww/AHK-v2-script-converter/commit/060ae1de67cf19c5a0913c3c05d0340df23d5172

GUI will not be as easy


robodesign wrote:
03 Aug 2021, 11:37
@guest3456 .thank you for the work!
youre welcome

AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: v1 -> v2 Script Converter

04 Aug 2021, 05:33

guest3456 wrote:
03 Aug 2021, 11:12
AHK_user wrote:
03 Aug 2021, 05:34
I agree.

At the moment I understand more of less most of the script working, except the function format_v that handles a very important part.

I think if somebody can help me to convert it, I can make it work again, I think I am almost there!!!
ok sir i've completed the upgrade to v2beta1

you can see the changes i made here:

https://github.com/mmikeww/AHK-v2-script-converter/commits/master

i've removed the format_v() function and instead now we use the built in format()

this means now that the converter script will execute successfully using the v2beta1 interpreter. however the actual v1->v2 conversion is still converting based on the old v2-a076 syntax. so now comes the process of upgrading the conversion parser to handle all of these commands/funcs/syntaxes, as well as including more Tests for each change. when you are ready to try to incorporate your gui conversion, you can submit pull request. i don't know how much of this i will undertake or not. hopefully the community can contribute

Great work :D @guest3456
I guess that I also will rewrite the gui and menu functions, as they currently could not handle syntax, but if this script works again, we can modify it.

I`ll start rewriting my gui conversion as the first version only worked on code without expressions.

:think: I have also the idea to split some commands temporary that have different handling depending on the parameters:
MsgBox for example has a short version and a long, depending if the first variable starts with a number, and if the timeout function is present, the handing is also a little different if the Timeout function is present, as the last variable will be added to the options...
And we should also keep track of the last errorlevel function, so we can replace the errorlevel with the correct parameter.
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: v1 -> v2 Script Converter

04 Aug 2021, 10:26

AHK_user wrote:
04 Aug 2021, 05:33
:think: I have also the idea to split some commands temporary that have different handling depending on the parameters:
MsgBox for example has a short version and a long, depending if the first variable starts with a number, and if the timeout function is present, the handing is also a little different if the Timeout function is present, as the last variable will be added to the options...
if you prefix the replacement text with a * then you can callout to a func to check the params:
https://github.com/mmikeww/AHK-v2-script-converter/blob/b8f436420911a5093c22d7c4d1f4eff150cd14c0/ConvertFuncs.ahk#L62
which calls:
https://github.com/mmikeww/AHK-v2-script-converter/blob/b8f436420911a5093c22d7c4d1f4eff150cd14c0/ConvertFuncs.ahk#L814

so you could do that with MsgBox and then check if isInteger(param[1]) or something

as always, be sure to add a Test for each case that you try to convert. some up with a list of all cases you want to handle, and then write a Test for each of those cases
AHK_user wrote:
04 Aug 2021, 05:33
And we should also keep track of the last errorlevel function, so we can replace the errorlevel with the correct parameter.
the converter just goes one line at a time, so i don't believe it can track state throughout the script like that, but feel free to try

AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: v1 -> v2 Script Converter

04 Aug 2021, 23:41

guest3456 wrote:
04 Aug 2021, 10:26
AHK_user wrote:
04 Aug 2021, 05:33
:think: I have also the idea to split some commands temporary that have different handling depending on the parameters:
MsgBox for example has a short version and a long, depending if the first variable starts with a number, and if the timeout function is present, the handing is also a little different if the Timeout function is present, as the last variable will be added to the options...
if you prefix the replacement text with a * then you can callout to a func to check the params:
https://github.com/mmikeww/AHK-v2-script-converter/blob/b8f436420911a5093c22d7c4d1f4eff150cd14c0/ConvertFuncs.ahk#L62
which calls:
https://github.com/mmikeww/AHK-v2-script-converter/blob/b8f436420911a5093c22d7c4d1f4eff150cd14c0/ConvertFuncs.ahk#L814

so you could do that with MsgBox and then check if isInteger(param[1]) or something

as always, be sure to add a Test for each case that you try to convert. some up with a list of all cases you want to handle, and then write a Test for each of those cases
AHK_user wrote:
04 Aug 2021, 05:33
And we should also keep track of the last errorlevel function, so we can replace the errorlevel with the correct parameter.
the converter just goes one line at a time, so i don't believe it can track state throughout the script like that, but feel free to try
Thanks for the explanation, very easily written :bravo:.

I already updated the script to handle [msgbox] better and a start of [gui], but I encounterd some errors in the examples, so I will post the updates if I finished it.

My idea is not to parse the v1 script string, but to put it in an global object and a global index so we can easily check temporary the following lines or the previous lines. This way you could also handle continuation section better and probably also the errorlevel variable.

REQUEST:
I am currently looking for a way to split or parse a string with "," but I want to keep into account the ahk syntax. Does this already exists?

Example:
stringtosplit := "var1, `"va,r2`", function(jkllksd,"")"",`"((`"),'ssdfsdf'"
=>
array[1] := "var1"
array[2] := "`"va,r2`""
array[3] := "function(jkllksd,"")"",`"((`")"
array[4] := "'ssdfsdf'"

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: JoeWinograd and 78 guests