[Function] - O() - Simple Object Function!

Post your working scripts, libraries and tools for AHK v1.1 and older
User
Posts: 407
Joined: 26 Jun 2017, 08:12

[Function] - O() - Simple Object Function!

19 Sep 2018, 00:27

I'm writing the function below for something I need, then I noticed it is turning into something like a "simple object function"?

Haha, anyway, I'm just sharing it here:

Save "o()" function objects in ".ini" files! (Click here)

o(Funcion) _VS_ Built-in Object - Speed Test (Click here)

v1.4 (Click here)
v1.3 (Click here)
v1.2 (Click here)
v1.1 (Click here)

v1.0 (below):

simple examples, Defining, Get, InsertingAt, RemovingAt:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


O(Test, "x", , "=", "xxx")
O(Test, "y", , "=", "yyy")
O(Test, "z", , "=", "zzz")
O(Test, "xyz", , "=", "xxx`r`nyyy`r`nzzz")

O(Test, "#@#!", , "=", "#@#! _ #@#! _ #@#!")

O(Test, "Type", "House1", "=", "H T 111")
O(Test, "Size", "House1", "=", "H S 111")
O(Test,"Color", "House1", "=", "H C 111")

O(Test, "Type", "House2", "=", "H T 222")
O(Test, "Size", "House2", "=", "H S 222")
O(Test,"Color", "House2", "=", "H C 222")

O(Test, "Type", "House3", "=", "H T 333")
O(Test, "Size", "House3", "=", "H S 333")
O(Test,"Color", "House3", "=", "H C 333")

O(Test, "Type", "House4", "=", "H T 444")
O(Test, "Size", "House4", "=", "H S 444")
O(Test,"Color", "House4", "=", "H C 444")

O(Test, "Type", "House5", "=", "H T 555")
O(Test, "Size", "House5", "=", "H S 555")
O(Test,"Color", "House5", "=", "H C 555")

O(Test, "Type", "House6", "=", "H T 666")
O(Test, "Size", "House6", "=", "H S 666")
O(Test,"Color", "House6", "=", "H C 666")

O(Test, "Type", "House10", "=", "H T 101010")
O(Test, "Size", "House10", "=", "H S 101010")
O(Test,"Color", "House10", "=", "H C 101010")

O(Test, , "House5", "DelSection")		;Delete Section ("House6" section will be made "House5" section, and so on ...!)

O(Test, "Type", "House2", "<=", "H T 777")	;"<=" = "InsertAt" section (the previous "House2" section will be made "House3" section, and so on ...!)
O(Test, "Size", "House2", "=", "H S 777")
O(Test,"Color", "House2", "=", "H C 777")



;__

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % Test, % "ahk_id" EditControlId

gui, show

;__

msgbox, % ""
. O(Test, "x") " - " O(Test, "y") " - " O(Test, "z") "`n`n"
. O(Test, "xyz")   "`n"
. "`n"
. O(Test, "#@#!")  "`n"
. "`n"
. O(Test, "Type", "House1") " - " O(Test, "Size", "House1") " - " O(Test, "Color", "House1")  "`n"
. O(Test, "Type", "House2") " - " O(Test, "Size", "House2") " - " O(Test, "Color", "House2")  "`n"
. O(Test, "Type", "House3") " - " O(Test, "Size", "House3") " - " O(Test, "Color", "House3")  "`n"
. O(Test, "Type", "House4") " - " O(Test, "Size", "House4") " - " O(Test, "Color", "House4")  "`n"
. O(Test, "Type", "House5") " - " O(Test, "Size", "House5") " - " O(Test, "Color", "House5")  "`n"
. O(Test, "Type", "House6") " - " O(Test, "Size", "House6") " - " O(Test, "Color", "House6")  "`n"
. O(Test, "Type", "House7") " - " O(Test, "Size", "House7") " - " O(Test, "Color", "House7")  "`n"
. O(Test, "Type", "House8") " - " O(Test, "Size", "House8") " - " O(Test, "Color", "House8")  "`n"
. O(Test, "Type", "House9") " - " O(Test, "Size", "House9") " - " O(Test, "Color", "House9")  "`n"
. O(Test, "Type", "House10") " - " O(Test, "Size", "House10") " - " O(Test, "Color", "House10")  "`n"

return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


O(ByRef Var, Key := "", Section := "", Task := "", Value := "")	;__________________ SimpleObject(Function) - v1.0 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)

Key := RegExReplace(Key, "#", "#_")
Value := RegExReplace(Value, "#", "#_")
Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"=>" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if (IndexFound = 0)
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}
More Extensive Examples:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


	;"##@" is the blank section (Which is the main section)

LV = 
(join`r`n
##@
#Test#=#Type#
#Type#=#T #_#_ #_@ #_! MainSection#
#Options# = #O MainSection#
#Col1# = #Col1 MainSection#
#End#!

#Col1#@
#Test#=#Type#
#Type# = #T1#
#Options# = #O1#
#Col2# = #Col2 111#
#End#!

#Col2#@
#Test#=#Type#
#Type#  =  #T2#
#Options# = #O2#
#Col3# = #Col3 222#
#End#!

#Col3#@
#Test#=#Type#
#Type#    =    #T3#
#Options# = #O3#
#Col4# = #Col4 333#
#End#!

#End#@
#Test#=#Type#
#Type#		=		#T End#
#Options# = #O End#
#Col5# = #Col5 End#
#End#!


)	;Extra "`r`n`r`n" at the end just for better testing

SimpleObject(LV, "Test" , , "=", " Value #Col2#@ - #End#! Value ")
SimpleObject(LV, " Key #Col2#@ - #End#! Key ", , "=", "Test2")

SimpleObject(LV, "Test", "NewSection", "=", "Type")
SimpleObject(LV, "type", "NewSection", "=", "T NewSection")
SimpleObject(LV, "Option", "NewSection", "=", "O NewSection")
SimpleObject(LV, "type", "NewSection", "=", "T NewSection - EEEE")

SimpleObject(LV, "Test", "NewSection5", "=", "Type")
SimpleObject(LV, "type", "NewSection5", "=", "T NewSection5")
SimpleObject(LV, "Option", "NewSection5", "=", "O NewSection5")
SimpleObject(LV, "type", "NewSection5", "=", "T NewSection5 - EEEE")

SimpleObject(LV, "Test", "NewSection0", "=", "NewSection0")

SimpleObject(LV, "Test", "#Col7#@", "=", "Type #Col7#@")
SimpleObject(LV, "Test", "Col7", "=", "Type")
SimpleObject(LV, "Type", "Col7", "=", "T7")

SimpleObject(LV, "Test", "za1", "=", "Type")
SimpleObject(LV, "Test", "ta1", "=", "Type")
SimpleObject(LV, "Test", "yu0", "=", "Type")

SimpleObject(LV, "Test", "10", "=", "Index Only Test 10")

SimpleObject(LV, "Test", "House23Floor11", "=", "House Test 11")

SimpleObject(LV, "Test", "NewSection", "=>", "Insert Test NewSection")		;this will be ignored because there is no number in the end
SimpleObject(LV, "Test", "NewSection0", "=>", "Insert Test NewSection0")	;this will be ignored because number at the end is 0
SimpleObject(LV, "Test", "NewSection1", "=>", "Insert Test NewSection1")
SimpleObject(LV, "Test", "NewSection4", "=>", "Insert Test NewSection4")
SimpleObject(LV, "Test", "NewSection10", "=>", "Insert Test NewSection10")	;"NewSection10" section does not exist, but it will be created anyway

SimpleObject(LV, , "5", "DelSection")
SimpleObject(LV, , "House23Floor10", "DelSection")

;SimpleObject(LV, "Test", "Col467", "=", "Type")
;SimpleObject(LV, "Test", "94", "=", "Type")
;SimpleObject(LV, "Test", "8999", "=", "Type")

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % LV, % "ahk_id" EditControlId

gui, show

;msgbox, % SimpleObject(LV, "")            "`n`n"
;msgbox, % SimpleObject(LV, "", "Col1")    "`n`n"
;msgbox, % SimpleObject(LV, "", "Col2")    "`n`n"
;msgbox, % SimpleObject(LV, "", "Col3")    "`n`n"
;msgbox, % SimpleObject(LV, "", "Col4")    "`n`n"
;msgbox, % SimpleObject(LV, "", "End")     "`n`n"

msgbox, % SimpleObject(LV, "Type")            "`n`n"	;get "Type" value from blank section (Which is the main section)
msgbox, % SimpleObject(LV, "Type", "Col1")    "`n`n"	;get "Type" value from "Col1" section
msgbox, % SimpleObject(LV, "Type", "Col2")    "`n`n"	;get "Type" value from "Col2" section
msgbox, % SimpleObject(LV, "Type", "Col3")    "`n`n"	;and so on ...!
msgbox, % SimpleObject(LV, "Type", "Col4")    "`n`n"
msgbox, % SimpleObject(LV, "Type", "End")     "`n`n"
msgbox, % SimpleObject(LV, "Type", "Col7")     "`n`n"

return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


SimpleObject(ByRef Var, Key := "", Section := "", Task := "", Value := "")	;__________________ SimpleObject(Function) - v1.0 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)

Key := RegExReplace(Key, "#", "#_")
Value := RegExReplace(Value, "#", "#_")
Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (Task = "=>" and SectionIndex != "" and SectionIndex > 0)    ;"=>" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if (IndexFound = 0)
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}
Last edited by User on 29 Nov 2018, 13:49, edited 8 times in total.
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: [Function] - O() - Simple Object Function!

19 Sep 2018, 09:00

I'm confused as to why you'd ever need such a thing.
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] - O() - Simple Object Function!

19 Sep 2018, 10:05

kczx3 wrote:I'm confused as to why you'd ever need such a thing.
For a lot of things, of course! (That's obvious!)

Anyway, I don't know if it is standard in the other languages, as it is in Autohotkey, to store objects references into variables instead the objects themselves, the thing is, I really don't like that! (Standard or not!)

The Object "Clone()" function that sometimes clones and sometimes doesn't! (Haha, with "O()" function Objects, I can clone just like this, "Object2 := Object1")

I can define sections, where for example, section "Col1" has its own set of Keys-Values (the same for section Col2, Col3, and so on ...!)
If, for example, I insert a new section "Col2" at section "Col2", the previous section "Col2" is made section "Col3", Section "Col3" is made section "Col4", and so on...!
If, for example, I delete section "Col2", section "Col3" is automatically made section "Col2", section "Col4" is automatically made section "Col3", and so on ...!

The "O()" function Objects can be write\read to\from ".ini" files on the go!
IniWrite, % Object1, ObjectWriteReadTest.ini, section, Object1
IniRead, Object1, ObjectWriteReadTest.ini, section, Object1

I'm not saying this is a real Object function in no way, I just noticed that the function behaves similarly!

Well, for what I need, "O()" function is a FANTASTIC alternative to AutoHotKey Built-in Object system!
User avatar
Frosti
Posts: 426
Joined: 27 Oct 2017, 14:30
Contact:

Re: [Function] - O() - Simple Object Function!

20 Sep 2018, 04:11

Hmm, I'm not familiar with objects. I use objects in a really basic way. I have the feeling I can understand what this is for. it comes very close to my way of understanding than many other things so far. This creates a tangible image in my head of a virtual process. This is a nice thing to study. Thx for open your mind.
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] - O() - Simple Object Function!

20 Sep 2018, 09:05

Frosti wrote:Hmm, I'm not familiar with objects. I use objects in a really basic way. I have the feeling I can understand what this is for. it comes very close to my way of understanding than many other things so far. This creates a tangible image in my head of a virtual process. This is a nice thing to study. Thx for open your mind.
You welcome!

But remember that, I really don't know if this function has anything to do with "Objects", "Simple Objects" or whatever!

The truth is that, I don't even know what "Objects" really means, I just notice that this function behaves similarly as an object, so, I decide to share it!
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] - O() - Simple Object Function!

27 Sep 2018, 00:35

(v1.1)

for "Key" parameter:

=> ;Add\Modify multiple keys (if section does not exist, it will be created)

+=> ;Create new section at specified index and Add multiple keys (the previous section index number will be increased, and so on)

-=> ;Delete content of the specified section and then add multiple keys!

Get=> ;get content of the specified section

for "Task" parameter:

GetSection ;get section content

DelSectionContent ;delete section content

Example:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


o(Test, "Type", "Col1", "=", "T 111")		;Adding 1 key-value

o(Test, "#Color# = #C 111#, #Options# = #O 111#, #Header# = #H 111# =>", "Col1")
;Adding multiple keys-values (must enclose keys and values between ##)
;the string must end with an "=>" in order to add multiple keys-values
;any "#" that belongs to keys or values must be pos-escaped with "_" (which means that any "#_" represents a literal "#")
;the "," separator is optional, any character can be used as separator, such as "space" character, /, \, etc, etc

o(Test, o("type") "=" o("T 222") . o("Color") "=" o("C 222") . o("Options") "=" o("O 222") "=>", "Col2")
;in case you don't want to worry about Enclosing\Pos-Escaping manually, you can tell the "o()" function to do it for you automatically!

;get content of "Col1" secction and paste it in "Col6, Col7, Col8" sections
o(Test, o(Test, "Get=>", "Col1") "=>", "Col6")
o(Test, o(Test, "Get=>", "Col1") "=>", "Col7")
o(Test, o(Test, "Get=>", "Col1") "=>", "Col8")

o(Test, "#x# = #xxx# / #y# = #yyy#  -=>", "Col7")	;"-=>" remove content from "Col7" section then add new keys-values

o(Test, "#z# = #zzz inserted at ''col index 8''#    #I# = #III#  +=>", "Col8")
;"+=>", Create new "col8" section, the previous "Col8" section will be made "Col9" section, and so on!


	;o(Test, , "Col7", "DelSectionContent")		;deletes content from "Col7" section 

;__

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % Test, % "ahk_id" EditControlId

gui, show

;__

msgbox, % ""
. o(Test, , "Col7", "GetSection")   "`n`n"	;get content of "Col7" section

return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.1 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if (IndexFound = 0)
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}
More extensive example:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


	;"##@" is the blank section (Which is the main section)

LV = 
(join`r`n
##@
#Test#=#Type#
#Type#=#T #_#_ #_@ #_! MainSection#
#Options# = #O MainSection#
#Col1# = #Col1 MainSection#
#End#!

#Col1#@
#Test#=#Type#
#Type# = #T1#
#Options# = #O1#
#Col2# = #Col2 111#
#End#!

#Col2#@
#Test#=#Type#
#Type#  =  #T2#
#Options# = #O2#
#Col3# = #Col3 222#
#End#!

#Col3#@
#Test#=#Type#
#Type#    =    #T3#
#Options# = #O3#
#Col4# = #Col4 333#
#End#!

#End#@
#Test#=#Type#
#Type#		=		#T End#
#Options# = #O End#
#Col5# = #Col5 End#
#End#!


)	;Extra "`r`n`r`n" at the end just for better testing

o(LV, "Test" , , "=", " Value #Col2#@ - #End#! Value ")
o(LV, " Key #Col2#@ - #End#! Key ", , "=", "Test2")

o(LV, "Test", "NewSection", "=", "Type")
o(LV, "type", "NewSection", "=", "T NewSection")
o(LV, "Option", "NewSection", "=", "O NewSection")
o(LV, "type", "NewSection", "=", "T NewSection - EEEE")

o(LV, "Test", "NewSection5", "=", "Type")
o(LV, "type", "NewSection5", "=", "T NewSection5")
o(LV, "Option", "NewSection5", "=", "O NewSection5")
o(LV, "type", "NewSection5", "=", "T NewSection5 - EEEE")

o(LV, "Test", "NewSection0", "=", "NewSection0")

o(LV, "Test", "#Col7#@", "=", "Type #Col7#@")
o(LV, "Test", "Col7", "=", "Type")
o(LV, "Type", "Col7", "=", "T7")

o(LV, "zazaza", "za1", "=", "zaaaaaaaaaaaa")
o(LV, "tatata", "ta1", "=", "taaaaaaaaaaaa")
o(LV, "Test", "yu0", "=", "Type")

o(LV, "Test", "10", "=", "Index Only Test 10")

o(LV, "Test", "House23Floor11", "=", "House Test 11")

o(LV, "Test", "NewSection", "<=", "Insert Test NewSection")		;this will be ignored because there is no number in the end
o(LV, "Test", "NewSection0", "<=", "Insert Test NewSection0")		;this will be ignored because number at the end is 0
o(LV, "Test", "NewSection1", "<=", "Insert Test NewSection1")
o(LV, "Test", "NewSection4", "<=", "Insert Test NewSection4")
o(LV, "Test", "NewSection10", "<=", "Insert Test NewSection10")		;"NewSection10" section does not exist, but it will be created anyway

o(LV, , "5", "DelSection")
o(LV, , "House23Floor10", "DelSection")

;_______________

	;"=>" Adds or Modifies existing "Keys" (Examples below:)
	;The "Keys" and "Values" must be enclosed by ##
	;any "#" that belongs to "key" or "value" must be pos-escaped with an "_"
	;which means that, any "#_" represents a literal "#" character

o(LV, "#Car# = #Toyota#, #Ass# = #Really Big#, #Status# = #Main# =>")	;Adding multiple keys-values in "blank\Main" section (Note that string must end with an "=>")

o(LV, "#Car# = #Toy2# / #Status# = #Main2# / #x# = #x2# =>", "Col2")	;Adding multiple keys-values in "col2" section (note that / is used instead , as separator)
o(LV, "#Car# = #Toy3#   #Type# = #Main3-3#   #x# = #x3# =>", "Col3")	;note that separator is optional

o(LV, "#Ca #_ = #_ r# = #Toy #_ Esc#   #Type# = #T #_ Esc#   #x# = #x #_ Esc# =>", "EscapeTest")

	;in case you don't want to worry about enclosing/Pos-Escaping manually, you can tell the o() function to do it for you automatically:

o(LV, o("Car") "=" o("Toy4") . o("Type") "=" o("T 4")  . o("x") "=" o("x4") "=>", "Col4")

o(LV, o("Car") "=" o("Toyz") . o("Type") "=" o("T z")  . o("x") "=" o("xz") "=>", "Colz")

o(LV, o("Ca # = # r") "=" o("Toy # Esc3") . o("Type") "=" o("T # Esc3")  . o("x") "=" o("x # Esc3") "=>", "EscapeTest3")

	;the o() function will automatically enclose "Keys" and "Values" between ##
	;the o() function will automatically replace any "#" that belongs to "Keys" or "Values" with "#_" (pos-escapes # with _)

	
	;"+=>", will create a new "NewSection5" section, the previous "NewSection5" section will be made "NewSection6" section, and so on ...!

o(LV, "#Car# = #Toy new 5#   #Type# = #T new 5#   #x# = #x new 5# +=>", "NewSection5")

o(LV, "#Car# = #Toy new y#   #Type# = #T new y#   #x# = #x new y# +=>", "yyy")		;will be ignored because, "yyy" should end with a number > 0
o(LV, "#Car# = #Toy new z#   #Type# = #T new z#   #x# = #x new z# +=>", "zzz0")		;will be ignored because, "zzz" should end with a number > 0

o(LV, "#Car# = #Toy new s#   #Type# = #T new s#   #x# = #x new s# +=>", "sss3")		;will not be ignored because, "sss" ends with a number > 0

o(LV, "#Car# = #Toy new t#   #Type# = #T new t#   #x# = #x new t# +=>", "ttt03")	;will be ignored because number contains leading zeros
o(LV, "#Car# = #Toy new r#   #Type# = #T new r#   #x# = #x new r# +=>", "rrr003")	;will be ignored because number contains leading zeros

o(Lv, "test","aaa004", "<=", "test a")	;will be ignored because number contains leading zeros

o(Lv, "test","ggg004", "=", "test g")	;creates only "ggg004" section, instead sections "ggg1" to "ggg4"

;_______________

o(Lv, , "Colz", "DelSectionContent")

o(Lv, o(Lv, "Get=>", "Col1") "=>", "za1")	;get keys-values from "Col1" section and paste them in "za1" section

o(Lv, o(Lv, "Get=>", "Col1") "-=>", "ta1")	;Delete content of "ta1" section, then get keys-values from "Col1" section and paste them in "ta1" section

o(Lv, o(Lv, "Get=>", "Col1") "+=>", "za1")	;create new "za1" section, get keys-values from "Col1" section and paste them in the new "za1" section (the previous "za1" is made "za2" section)

	;o(LV, "Test", "Col467", "=", "Type")
	;o(LV, "Test", "94", "=", "Type")
	;o(LV, "Test", "8999", "=", "Type")

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % LV, % "ahk_id" EditControlId

gui, show

;msgbox, % o(LV, "")            "`n`n"
;msgbox, % o(LV, "", "Col1")    "`n`n"
;msgbox, % o(LV, "", "Col2")    "`n`n"
;msgbox, % o(LV, "", "Col3")    "`n`n"
;msgbox, % o(LV, "", "Col4")    "`n`n"
;msgbox, % o(LV, "", "End")     "`n`n"

msgbox, % o(LV, "Type")            "`n`n"	;get "Type" value from blank section (Which is the main section)
msgbox, % o(LV, "Type", "Col1")    "`n`n"	;get "Type" value from "Col1" section
msgbox, % o(LV, "Type", "Col2")    "`n`n"	;get "Type" value from "Col2" section
msgbox, % o(LV, "Type", "Col3")    "`n`n"	;and so on ...!
msgbox, % o(LV, "Type", "Col4")    "`n`n"
msgbox, % o(LV, "Type", "End")     "`n`n"
msgbox, % o(LV, "Type", "Col7")     "`n`n"

msgbox, % o(LV, , , "GetSection")     "`n`n"		;Get content of "Blank\Main" section!

msgbox, % o(LV, , "Col2", "GetSection")     "`n`n"	;Get content of "Col2" section!

msgbox, % o(Lv, "Get=>", "Col3")	;Get content of "Col3" section!

return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.1 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if (IndexFound = 0)
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] - O() - Simple Object Function!

28 Sep 2018, 23:25

(v1.2)

AHK For-Loop equivalent implemented by using the new options below:

for "Key" parameter: ___

<=Get ;get values from "o()" function static vars (Mainly for "FindAnyKey" var)

Kx=> ;get the nth key of a section (K1=> First, K2=> second, and so on ...!)

Vx=> ;get the nth value of a section (v1=> First, v2=> second, and so on ...!)

GetIndex=> ;get index of a specified section

for "Task" parameter: ___

GetSectionIndex ;get index of a specified section

Example:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


o(Test, "Options", "Col1", "=", "O 111")
o(Test, "Color", "Col1", "=", "C 111")
o(Test, "Type", "Col1", "=", "T 111")

o(Test, "Color", "Col2", "=", "C 222")
o(Test, "Header", "Col2", "=", "H 222")
o(Test, "Options", "Col2", "=", "O 222")
o(Test, "Type", "Col2", "=", "T 222")
o(Test, "Size", "Col2", "=", "S 222")

o(Test, "Type", "Col3", "=", "T 333")
o(Test, "Options", "Col3", "=", "O 333")
o(Test, "Header", "Col3", "=", "H 333")
o(Test, "Color", "Col3", "=", "C 333")

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % Test, % "ahk_id" EditControlId

gui, show

;__

msgbox, % ""
. "'Col1' section index = " o(Test, "GetIndex=>", "Col1") " / k2v2 = " o(Test, "k2=>", "Col1") " : "  o(Test, "v2=>", "Col1")  "`n"
. "'Col2' section index = " o(Test, "GetIndex=>", "Col2") " / k3v3 = " o(Test, "k3=>", "Col2") " : "  o(Test, "v3=>", "Col2")  "`n"
. "'Col3' section index = " o(Test, "GetIndex=>", "Col3") " / k1v1 = " o(Test, "k1=>", "Col3") " : "  o(Test, "v1=>", "Col3")  "`n"
. "`n"
. "RegEx pattern to FindAnyKey from section content:    `n"
. o("FindAnyKey", "<=Get")   "`n`n"

;__

loop, % o(Test, "GetIndex=>", "Col2")	;AHK "For-loop" Equivalent (Easier way, but slower!)
msgbox, % ""				;Applying "For-loop" in "Col2" section 
. "K" a_index "V" a_index " of 'Col2' section:  `n`n"
. o(Test, "k" a_index "=>", "Col2") " : " o(Test, "v" a_index "=>", "Col2")

;__

FoundPos := 1				;AHK "For-loop" Equivalent (Less Easier way, but Faster!)
MatchLenght := 0
loop, % o(Test, "GetIndex=>", "Col3")	;get index of "Col3" section
{
FoundPos := RegExMatch(o(Test, "Get=>", "Col3"), o("FindAnyKey", "<=Get"), Match, FoundPos + MatchLenght)

MatchLenght := StrLen(Match)

key := RegExReplace(Match1, "#_", "#")

value := RegExReplace(Match4, "#_", "#")

msgbox, % ""
. "(For-Loop - Less Easier way, but faster!) `n`n"
. "k" a_index "v" a_index " of 'Col3' section:   `n`n"
. key " : " Value
}

;__


return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.2 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (key = "<=Get")
return, (%Var%)		;returns the values of static variables of this function! (Mainly for "FindAnyKey" var)

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

if (Key = "GetIndex=>")
key := "", Task := "GetSectionIndex"

if RegExMatch(Key, "i)^(k|v)(\d+)=>$", Found)
key := "", GetWhat := Found1, GetX := Found2

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (GetWhat != "")
	{
		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(SectionContent, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "k" ? RegExReplace(Match1, "#_", "#") : RegExReplace(Match4, "#_", "#")
			}
		}
	}

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (Task = "GetSectionIndex")
	{
	RegExReplace(SectionContent, FindAnyKey,, TotalReplace)
	return, TotalReplace
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if (IndexFound = 0)
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}
More extensive example:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


	;"##@" is the blank section (Which is the main section)

LV = 
(join`r`n
##@
#Test#=#Type#
#Type#=#T #_#_ #_@ #_! MainSection#
#Options# = #O MainSection#
#Col1# = #Col1 MainSection#
#End#!

#Col1#@
#Test#=#Type#
#Type# = #T1#
#Options# = #O1#
#Col2# = #Col2 111#
#End#!

#Col2#@
#Test#=#Type#
#Type#  =  #T2#
#Options# = #O2#
#Col3# = #Col3 222#
#End#!

#Col3#@
#Test#=#Type#
#Type#    =    #T3#
#Options# = #O3#
#Col4# = #Col4 333#
#End#!

#End#@
#Test#=#Type#
#Type#		=		#T End#
#Options# = #O End#
#Col5# = #Col5 End#
#End#!


)	;Extra "`r`n`r`n" at the end just for better testing

o(LV, "Test" , , "=", " Value #Col2#@ - #End#! Value ")
o(LV, " Key #Col2#@ - #End#! Key ", , "=", "Test2")

o(LV, "Test", "NewSection", "=", "Type")
o(LV, "type", "NewSection", "=", "T NewSection")
o(LV, "Option", "NewSection", "=", "O NewSection")
o(LV, "type", "NewSection", "=", "T NewSection - EEEE")

o(LV, "Test", "NewSection5", "=", "Type")
o(LV, "type", "NewSection5", "=", "T NewSection5")
o(LV, "Option", "NewSection5", "=", "O NewSection5")
o(LV, "type", "NewSection5", "=", "T NewSection5 - EEEE")

o(LV, "Test", "NewSection0", "=", "NewSection0")

o(LV, "Test", "#Col7#@", "=", "Type #Col7#@")
o(LV, "Test", "Col7", "=", "Type")
o(LV, "Type", "Col7", "=", "T7")

o(LV, "zazaza", "za1", "=", "zaaaaaaaaaaaa")
o(LV, "tatata", "ta1", "=", "taaaaaaaaaaaa")
o(LV, "Test", "yu0", "=", "Type")

o(LV, "Test", "10", "=", "Index Only Test 10")

o(LV, "Test", "House23Floor11", "=", "House Test 11")

o(LV, "Test", "NewSection", "<=", "Insert Test NewSection")		;this will be ignored because there is no number in the end
o(LV, "Test", "NewSection0", "<=", "Insert Test NewSection0")		;this will be ignored because number at the end is 0
o(LV, "Test", "NewSection1", "<=", "Insert Test NewSection1")
o(LV, "Test", "NewSection4", "<=", "Insert Test NewSection4")
o(LV, "Test", "NewSection10", "<=", "Insert Test NewSection10")		;"NewSection10" section does not exist, but it will be created anyway

o(LV, , "5", "DelSection")
o(LV, , "House23Floor10", "DelSection")

;_______________

	;"=>" Adds or Modifies existing "Keys" (Examples below:)
	;The "Keys" and "Values" must be enclosed by ##
	;any "#" that belongs to "key" or "value" must be pos-escaped with an "_"
	;which means that, any "#_" represents a literal "#" character

o(LV, "#Car# = #Toyota#, #Ass# = #Really Big#, #Status# = #Main# =>")	;Adding multiple keys-values in "blank\Main" section (Note that string must end with an "=>")

o(LV, "#Car# = #Toy2# / #Status# = #Main2# / #x# = #x2# =>", "Col2")	;Adding multiple keys-values in "col2" section (note that / is used instead , as separator)
o(LV, "#Car# = #Toy3#   #Type# = #Main3-3#   #x# = #x3# =>", "Col3")	;note that separator is optional

o(LV, "#Ca #_ = #_ r# = #Toy #_ Esc#   #Type# = #T #_ Esc#   #x# = #x #_ Esc# =>", "EscapeTest")

	;in case you don't want to worry about enclosing/Pos-Escaping manually, you can tell the o() function to do it for you automatically:

o(LV, o("Car") "=" o("Toy4") . o("Type") "=" o("T 4")  . o("x") "=" o("x4") "=>", "Col4")

o(LV, o("Car") "=" o("Toyz") . o("Type") "=" o("T z")  . o("x") "=" o("xz") "=>", "Colz")

o(LV, o("Ca # = # r") "=" o("Toy # Esc3") . o("Type") "=" o("T # Esc3")  . o("x") "=" o("x # Esc3") "=>", "EscapeTest3")

	;the o() function will automatically enclose "Keys" and "Values" between ##
	;the o() function will automatically replace any "#" that belongs to "Keys" or "Values" with "#_" (pos-escapes # with _)

	
	;"+=>", will create a new "NewSection5" section, the previous "NewSection5" section will be made "NewSection6" section, and so on ...!

o(LV, "#Car# = #Toy new 5#   #Type# = #T new 5#   #x# = #x new 5# +=>", "NewSection5")

o(LV, "#Car# = #Toy new y#   #Type# = #T new y#   #x# = #x new y# +=>", "yyy")		;will be ignored because, "yyy" should end with a number > 0
o(LV, "#Car# = #Toy new z#   #Type# = #T new z#   #x# = #x new z# +=>", "zzz0")		;will be ignored because, "zzz" should end with a number > 0

o(LV, "#Car# = #Toy new s#   #Type# = #T new s#   #x# = #x new s# +=>", "sss3")		;will not be ignored because, "sss" ends with a number > 0

o(LV, "#Car# = #Toy new t#   #Type# = #T new t#   #x# = #x new t# +=>", "ttt03")	;will be ignored because number contains leading zeros
o(LV, "#Car# = #Toy new r#   #Type# = #T new r#   #x# = #x new r# +=>", "rrr003")	;will be ignored because number contains leading zeros

o(Lv, "test","aaa004", "<=", "test a")	;will be ignored because number contains leading zeros

o(Lv, "test","ggg004", "=", "test g")	;creates only "ggg004" section, instead sections "ggg1" to "ggg4"

;_______________

o(Lv, , "Colz", "DelSectionContent")

o(Lv, o(Lv, "Get=>", "Col1") "=>", "za1")	;get keys-values from "Col1" section and paste them in "za1" section

o(Lv, o(Lv, "Get=>", "Col1") "-=>", "ta1")	;Delete content of "ta1" section, then get keys-values from "Col1" section and paste them in "ta1" section

o(Lv, o(Lv, "Get=>", "Col1") "+=>", "za1")	;create new "za1" section, get keys-values from "Col1" section and paste them in the new "za1" section (the previous "za1" is made "za2" section)

	;o(LV, "Test", "Col467", "=", "Type")
	;o(LV, "Test", "94", "=", "Type")
	;o(LV, "Test", "8999", "=", "Type")

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % LV, % "ahk_id" EditControlId

gui, show

;msgbox, % o(LV, "")            "`n`n"
;msgbox, % o(LV, "", "Col1")    "`n`n"
;msgbox, % o(LV, "", "Col2")    "`n`n"
;msgbox, % o(LV, "", "Col3")    "`n`n"
;msgbox, % o(LV, "", "Col4")    "`n`n"
;msgbox, % o(LV, "", "End")     "`n`n"

msgbox, % o(LV, "Type")            "`n`n"	;get "Type" value from blank section (Which is the main section)
msgbox, % o(LV, "Type", "Col1")    "`n`n"	;get "Type" value from "Col1" section
msgbox, % o(LV, "Type", "Col2")    "`n`n"	;get "Type" value from "Col2" section
msgbox, % o(LV, "Type", "Col3")    "`n`n"	;and so on ...!
msgbox, % o(LV, "Type", "Col4")    "`n`n"
msgbox, % o(LV, "Type", "End")     "`n`n"
msgbox, % o(LV, "Type", "Col7")     "`n`n"

msgbox, % ""
. "Index = " o(LV, "GetIndex=>") " = Total Keys-Values"            "`n"		;Get Index of "Blank\Main" section!
. "Index = " o(LV, , , "GetSectionIndex") " = Total Keys-Values"   "`n"		;Get Index of "Blank\Main" section!
. o(LV, , , "GetSection")                                          "`n`n"	;Get content of "Blank\Main" section!

msgbox, % ""
. "Index = " o(LV, "GetIndex=>", "Col2") " = Total Keys-Values"         "`n"	;Get Index of "Col2" section!
. "Index = " o(LV, , "Col2", "GetSectionIndex") " = Total Keys-Values"  "`n"	;Get Index of "Col2" section!
. o(LV, , "Col2", "GetSection")                                         "`n`n"	;Get content of "Col2" section!

msgbox, % ""
. "Index = " o(LV, "GetIndex=>", "Col3") " = Total Keys-Values"         "`n"	;Get Index of "Col3" section!
. "Index = " o(LV, , "Col3", "GetSectionIndex") " = Total Keys-Values"  "`n"	;Get Index of "Col3" section!
.  o(Lv, "Get=>", "Col3")	                                                ;Get content of "Col3" section!

msgbox, % ""
. "k1v1 of 'Blank\Main' section: `n" 
. o(Lv, "k1=>") " : " o(Lv, "v1=>")   "`n`n"	;Get the 1st(first) Key-Value of "Blank\Main" section
. "k5v5 of 'Blank\Main' section: `n"
. o(Lv, "K5=>") " : " o(Lv, "V5=>")   "`n"	;Get the 5th(fifth) Key-Value of "Blank\Main" section
. "__`n`n"
. "k2v2 of 'Col3' section: `n"
. o(Lv, "k2=>", "Col3") " : " o(Lv, "v2=>", "Col3")   "`n`n"	;Get the 2nd(second) Key-Value of "Col3" section
. "k6v6 of 'Col3' section: `n"
. o(Lv, "k6=>", "Col3") " : " o(Lv, "v6=>", "Col3")   "`n"	;Get the 6th(sixth) Key-Value of "Col3" section

;__

loop, % o(Lv, "GetIndex=>")		;AHK "For-loop" Equivalent (Easier way, but slower!)
msgbox, % ""				;Applying "For-loop" in "Blank\Main" section 
. "K" a_index "V" a_index " of 'Blank\Main' section:  `n`n"
. o(Lv, "k" a_index "=>") " : " o(Lv, "v" a_index "=>")

loop, % o(Lv, "GetIndex=>", "Col3")	;AHK "For-loop" Equivalent (Easier way, but slower!)
msgbox, % ""				;Applying "For-loop" in "Col3" section 
. "K" a_index "V" a_index " of 'Col3' section:  `n`n"
. o(Lv, "k" a_index "=>", "Col3") " : " o(Lv, "v" a_index "=>", "Col3")

;__

msgbox, % ""
. "RegEx pattern that FindAnyKey from a Section content:   `n`n"
. o("FindAnyKey", "<=Get") 

;__

FoundPos := 1			;AHK "For-loop" Equivalent (Less Easier way, but Faster!)
MatchLenght := 0
loop, % o(Lv, "GetIndex=>")	;get index of "Blank\Main" section
{
FoundPos := RegExMatch(o(Lv, "Get=>"), o("FindAnyKey", "<=Get"), Match, FoundPos + MatchLenght)

MatchLenght := StrLen(Match)

key := RegExReplace(Match1, "#_", "#")

value := RegExReplace(Match4, "#_", "#")

msgbox, % ""
. "(For-Loop - Less Easier way, but faster!) `n`n"
. "k" a_index "v" a_index " of 'Blank\Main' section:   `n`n"
. key " : " Value
}

FoundPos := 1				;AHK "For-loop" Equivalent (Less Easier way, but Faster!)
MatchLenght := 0
loop, % o(Lv, "GetIndex=>", "Col3")	;get index of "Col3" section
{
FoundPos := RegExMatch(o(Lv, "Get=>", "Col3"), o("FindAnyKey", "<=Get"), Match, FoundPos + MatchLenght)

MatchLenght := StrLen(Match)

key := RegExReplace(Match1, "#_", "#")

value := RegExReplace(Match4, "#_", "#")

msgbox, % ""
. "(For-Loop - Less Easier way, but faster!) `n`n"
. "k" a_index "v" a_index " of 'Col3' section:   `n`n"
. key " : " Value
}

;__


return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.2 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (key = "<=Get")
return, (%Var%)		;returns the values of static variables of this function! (Mainly for "FindAnyKey" var)

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

if (Key = "GetIndex=>")
key := "", Task := "GetSectionIndex"

if RegExMatch(Key, "i)^(k|v)(\d+)=>$", Found)
key := "", GetWhat := Found1, GetX := Found2

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (GetWhat != "")
	{
		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(SectionContent, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "k" ? RegExReplace(Match1, "#_", "#") : RegExReplace(Match4, "#_", "#")
			}
		}
	}

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (Task = "GetSectionIndex")
	{
	RegExReplace(SectionContent, FindAnyKey,, TotalReplace)
	return, TotalReplace
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if (IndexFound = 0)
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] - O() - Simple Object Function!

01 Oct 2018, 13:09

To save "o()" function objects in ".ini" files, use the "IniValue()" function!

It is really easy to be used, example:

Lest say "Test" variable contains an "o()" function object, the line below saves it to an ".ini" file,

IniWrite, % IniValue(Test), Test.ini, section, TestObject

To read it back, "R" option from "IniValue()" function must be used,

IniRead, Test, Test.ini, section, TestObject
IniValue(Test, "R")

That's it!
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] - O() - Simple Object Function!

01 Oct 2018, 22:42

(v1.3)

Inside "UpdateSectionIndex", the line, if (IndexFound = 0), was replaced with, if RegExMatch(IndexFound, "^0")

Any section that ends by 0 or by an integer number that contains leading zero\s will be ignored while Updating section index!

Example at line 127:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


	;"##@" is the blank section (Which is the main section)

LV = 
(join`r`n
##@
#Test#=#Type#
#Type#=#T #_#_ #_@ #_! MainSection#
#Options# = #O MainSection#
#Col1# = #Col1 MainSection#
#End#!

#Col1#@
#Test#=#Type#
#Type# = #T1#
#Options# = #O1#
#Col2# = #Col2 111#
#End#!

#Col2#@
#Test#=#Type#
#Type#  =  #T2#
#Options# = #O2#
#Col3# = #Col3 222#
#End#!

#Col3#@
#Test#=#Type#
#Type#    =    #T3#
#Options# = #O3#
#Col4# = #Col4 333#
#End#!

#End#@
#Test#=#Type#
#Type#		=		#T End#
#Options# = #O End#
#Col5# = #Col5 End#
#End#!


)	;Extra "`r`n`r`n" at the end just for better testing

o(LV, "Test" , , "=", " Value #Col2#@ - #End#! Value ")
o(LV, " Key #Col2#@ - #End#! Key ", , "=", "Test2")

o(LV, "Test", "NewSection", "=", "Type")
o(LV, "type", "NewSection", "=", "T NewSection")
o(LV, "Option", "NewSection", "=", "O NewSection")
o(LV, "type", "NewSection", "=", "T NewSection - EEEE")

o(LV, "Test", "NewSection5", "=", "Type")
o(LV, "type", "NewSection5", "=", "T NewSection5")
o(LV, "Option", "NewSection5", "=", "O NewSection5")
o(LV, "type", "NewSection5", "=", "T NewSection5 - EEEE")

o(LV, "Test", "NewSection0", "=", "NewSection0")

o(LV, "Test", "#Col7#@", "=", "Type #Col7#@")
o(LV, "Test", "Col7", "=", "Type")
o(LV, "Type", "Col7", "=", "T7")

o(LV, "zazaza", "za1", "=", "zaaaaaaaaaaaa")
o(LV, "tatata", "ta1", "=", "taaaaaaaaaaaa")
o(LV, "Test", "yu0", "=", "Type")

o(LV, "Test", "10", "=", "Index Only Test 10")

o(LV, "Test", "House23Floor11", "=", "House Test 11")

o(LV, "Test", "NewSection", "<=", "Insert Test NewSection")		;this will be ignored because there is no number in the end
o(LV, "Test", "NewSection0", "<=", "Insert Test NewSection0")		;this will be ignored because number at the end is 0
o(LV, "Test", "NewSection1", "<=", "Insert Test NewSection1")
o(LV, "Test", "NewSection4", "<=", "Insert Test NewSection4")
o(LV, "Test", "NewSection10", "<=", "Insert Test NewSection10")		;"NewSection10" section does not exist, but it will be created anyway

o(LV, , "5", "DelSection")
o(LV, , "House23Floor10", "DelSection")

;_______________

	;"=>" Adds or Modifies existing "Keys" (Examples below:)
	;The "Keys" and "Values" must be enclosed by ##
	;any "#" that belongs to "key" or "value" must be pos-escaped with an "_"
	;which means that, any "#_" represents a literal "#" character

o(LV, "#Car# = #Toyota#, #Ass# = #Really Big#, #Status# = #Main# =>")	;Adding multiple keys-values in "blank\Main" section (Note that string must end with an "=>")

o(LV, "#Car# = #Toy2# / #Status# = #Main2# / #x# = #x2# =>", "Col2")	;Adding multiple keys-values in "col2" section (note that / is used instead , as separator)
o(LV, "#Car# = #Toy3#   #Type# = #Main3-3#   #x# = #x3# =>", "Col3")	;note that separator is optional

o(LV, "#Ca #_ = #_ r# = #Toy #_ Esc#   #Type# = #T #_ Esc#   #x# = #x #_ Esc# =>", "EscapeTest")

	;in case you don't want to worry about enclosing/Pos-Escaping manually, you can tell the o() function to do it for you automatically:

o(LV, o("Car") "=" o("Toy4") . o("Type") "=" o("T 4")  . o("x") "=" o("x4") "=>", "Col4")

o(LV, o("Car") "=" o("Toyz") . o("Type") "=" o("T z")  . o("x") "=" o("xz") "=>", "Colz")

o(LV, o("Ca # = # r") "=" o("Toy # Esc3") . o("Type") "=" o("T # Esc3")  . o("x") "=" o("x # Esc3") "=>", "EscapeTest3")

	;the o() function will automatically enclose "Keys" and "Values" between ##
	;the o() function will automatically replace any "#" that belongs to "Keys" or "Values" with "#_" (pos-escapes # with _)

	
	;"+=>", will create a new "NewSection5" section, the previous "NewSection5" section will be made "NewSection6" section, and so on ...!

o(LV, "#Car# = #Toy new 5#   #Type# = #T new 5#   #x# = #x new 5# +=>", "NewSection5")

o(LV, "#Car# = #Toy new y#   #Type# = #T new y#   #x# = #x new y# +=>", "yyy")		;will be ignored because, "yyy" should end with a number > 0
o(LV, "#Car# = #Toy new z#   #Type# = #T new z#   #x# = #x new z# +=>", "zzz0")		;will be ignored because, "zzz" should end with a number > 0

o(LV, "#Car# = #Toy new s#   #Type# = #T new s#   #x# = #x new s# +=>", "sss3")		;will not be ignored because, "sss" ends with a number > 0

o(LV, "#Car# = #Toy new t#   #Type# = #T new t#   #x# = #x new t# +=>", "ttt03")	;will be ignored because number contains leading zeros
o(LV, "#Car# = #Toy new r#   #Type# = #T new r#   #x# = #x new r# +=>", "rrr003")	;will be ignored because number contains leading zeros

o(Lv, "test","aaa004", "<=", "test a")	;will be ignored because number contains leading zeros

o(Lv, "test","ggg004", "=", "test g004")	;creates only "ggg004" section, instead sections "ggg1" to "ggg4"
o(Lv, "test","ggg3", "<=", "test g3")
o(Lv, "test","ggg2", "<=", "test g inserted at ggg2")
;(v1.3 fixed), any section that ends by 0 or by an interger number that contains leading zero\s will be ignored while Updating section index! 
;Inside "UpdateSectionIndex", the line, if (IndexFound = 0), was replaced with, if RegExMatch(IndexFound, "^0")
;so, in this case, after inserting the new "ggg2" section, "ggg004" section will not be replaced with "ggg1", because it ends by "004" that contains 2 leading zeros!

;_______________

o(Lv, , "Colz", "DelSectionContent")

o(Lv, o(Lv, "Get=>", "Col1") "=>", "za1")	;get keys-values from "Col1" section and paste them in "za1" section

o(Lv, o(Lv, "Get=>", "Col1") "-=>", "ta1")	;Delete content of "ta1" section, then get keys-values from "Col1" section and paste them in "ta1" section

o(Lv, o(Lv, "Get=>", "Col1") "+=>", "za1")	;create new "za1" section, get keys-values from "Col1" section and paste them in the new "za1" section (the previous "za1" is made "za2" section)

	;o(LV, "Test", "Col467", "=", "Type")
	;o(LV, "Test", "94", "=", "Type")
	;o(LV, "Test", "8999", "=", "Type")

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % LV, % "ahk_id" EditControlId

gui, show

;msgbox, % o(LV, "")            "`n`n"
;msgbox, % o(LV, "", "Col1")    "`n`n"
;msgbox, % o(LV, "", "Col2")    "`n`n"
;msgbox, % o(LV, "", "Col3")    "`n`n"
;msgbox, % o(LV, "", "Col4")    "`n`n"
;msgbox, % o(LV, "", "End")     "`n`n"

msgbox, % o(LV, "Type")            "`n`n"	;get "Type" value from blank section (Which is the main section)
msgbox, % o(LV, "Type", "Col1")    "`n`n"	;get "Type" value from "Col1" section
msgbox, % o(LV, "Type", "Col2")    "`n`n"	;get "Type" value from "Col2" section
msgbox, % o(LV, "Type", "Col3")    "`n`n"	;and so on ...!
msgbox, % o(LV, "Type", "Col4")    "`n`n"
msgbox, % o(LV, "Type", "End")     "`n`n"
msgbox, % o(LV, "Type", "Col7")     "`n`n"

msgbox, % ""
. "Index = " o(LV, "GetIndex=>") " = Total Keys-Values"            "`n"		;Get Index of "Blank\Main" section!
. "Index = " o(LV, , , "GetSectionIndex") " = Total Keys-Values"   "`n"		;Get Index of "Blank\Main" section!
. o(LV, , , "GetSection")                                          "`n`n"	;Get content of "Blank\Main" section!

msgbox, % ""
. "Index = " o(LV, "GetIndex=>", "Col2") " = Total Keys-Values"         "`n"	;Get Index of "Col2" section!
. "Index = " o(LV, , "Col2", "GetSectionIndex") " = Total Keys-Values"  "`n"	;Get Index of "Col2" section!
. o(LV, , "Col2", "GetSection")                                         "`n`n"	;Get content of "Col2" section!

msgbox, % ""
. "Index = " o(LV, "GetIndex=>", "Col3") " = Total Keys-Values"         "`n"	;Get Index of "Col3" section!
. "Index = " o(LV, , "Col3", "GetSectionIndex") " = Total Keys-Values"  "`n"	;Get Index of "Col3" section!
.  o(Lv, "Get=>", "Col3")	                                                ;Get content of "Col3" section!

msgbox, % ""
. "k1v1 of 'Blank\Main' section: `n" 
. o(Lv, "k1=>") " : " o(Lv, "v1=>")   "`n`n"	;Get the 1st(first) Key-Value of "Blank\Main" section
. "k5v5 of 'Blank\Main' section: `n"
. o(Lv, "K5=>") " : " o(Lv, "V5=>")   "`n"	;Get the 5th(fifth) Key-Value of "Blank\Main" section
. "__`n`n"
. "k2v2 of 'Col3' section: `n"
. o(Lv, "k2=>", "Col3") " : " o(Lv, "v2=>", "Col3")   "`n`n"	;Get the 2nd(second) Key-Value of "Col3" section
. "k6v6 of 'Col3' section: `n"
. o(Lv, "k6=>", "Col3") " : " o(Lv, "v6=>", "Col3")   "`n"	;Get the 6th(sixth) Key-Value of "Col3" section

;__

loop, % o(Lv, "GetIndex=>")		;AHK "For-loop" Equivalent (Easier way, but slower!)
msgbox, % ""				;Applying "For-loop" in "Blank\Main" section 
. "K" a_index "V" a_index " of 'Blank\Main' section:  `n`n"
. o(Lv, "k" a_index "=>") " : " o(Lv, "v" a_index "=>")

loop, % o(Lv, "GetIndex=>", "Col3")	;AHK "For-loop" Equivalent (Easier way, but slower!)
msgbox, % ""				;Applying "For-loop" in "Col3" section 
. "K" a_index "V" a_index " of 'Col3' section:  `n`n"
. o(Lv, "k" a_index "=>", "Col3") " : " o(Lv, "v" a_index "=>", "Col3")

;__

msgbox, % ""
. "RegEx pattern that FindAnyKey from a Section content:   `n`n"
. o("FindAnyKey", "<=Get") 

;__

FoundPos := 1			;AHK "For-loop" Equivalent (Less Easier way, but Faster!)
MatchLenght := 0
loop, % o(Lv, "GetIndex=>")	;get index of "Blank\Main" section
{
FoundPos := RegExMatch(o(Lv, "Get=>"), o("FindAnyKey", "<=Get"), Match, FoundPos + MatchLenght)

MatchLenght := StrLen(Match)

key := RegExReplace(Match1, "#_", "#")

value := RegExReplace(Match4, "#_", "#")

msgbox, % ""
. "(For-Loop - Less Easier way, but faster!) `n`n"
. "k" a_index "v" a_index " of 'Blank\Main' section:   `n`n"
. key " : " Value
}

FoundPos := 1				;AHK "For-loop" Equivalent (Less Easier way, but Faster!)
MatchLenght := 0
loop, % o(Lv, "GetIndex=>", "Col3")	;get index of "Col3" section
{
FoundPos := RegExMatch(o(Lv, "Get=>", "Col3"), o("FindAnyKey", "<=Get"), Match, FoundPos + MatchLenght)

MatchLenght := StrLen(Match)

key := RegExReplace(Match1, "#_", "#")

value := RegExReplace(Match4, "#_", "#")

msgbox, % ""
. "(For-Loop - Less Easier way, but faster!) `n`n"
. "k" a_index "v" a_index " of 'Col3' section:   `n`n"
. key " : " Value
}

;__


return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.3 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (key = "<=Get")
return, (%Var%)		;returns the values of static variables of this function! (Mainly for "FindAnyKey" var)

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

if (Key = "GetIndex=>")
key := "", Task := "GetSectionIndex"

if RegExMatch(Key, "i)^(k|v)(\d+)=>$", Found)
key := "", GetWhat := Found1, GetX := Found2

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (GetWhat != "")
	{
		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(SectionContent, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "k" ? RegExReplace(Match1, "#_", "#") : RegExReplace(Match4, "#_", "#")
			}
		}
	}

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (Task = "GetSectionIndex")
	{
	RegExReplace(SectionContent, FindAnyKey,, TotalReplace)
	return, TotalReplace
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if RegExMatch(IndexFound, "^0")
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] - O() - Simple Object Function!

29 Nov 2018, 00:36

(v1.4)

for "Key" parameter: ___

<=Sx ;get the nth Section name from an "o()" function object (<=S1 First, <=S2 second, and so on ...!)

<=Cx ;get the nth Section Content from an "o()" function object (<=C1 First, <=C2 second, and so on ...!)

<=CountSections ;count sections that an "o()" function object contains


for "Task" parameter: ___

CheckKey ;check if key exist

CheckSection ;check if section exist

DelKey ;delete keys from sections

Example:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


o(Test, "Options", "Col1", "=", "O 111")
o(Test, "Color", "Col1", "=", "C 111")
o(Test, "Type", "Col1", "=", "T 111")

o(Test, "Color", "Col2", "=", "C 222")
o(Test, "Header", "Col2", "=", "H 222")
o(Test, "Options", "Col2", "=", "O 222")
o(Test, "Type", "Col2", "=", "T 222")
o(Test, "Size", "Col2", "=", "S 222")

o(Test, "Type", "Col3", "=", "T 333")
o(Test, "Options", "Col3", "=", "O 333")
o(Test, "Header", "Col3", "=", "H 333")
o(Test, "Color", "Col3", "=", "C 333")

;__ DelKey __
o(Test, "Options", "Col1", "DelKey")
o(Test, "Options", "Col2", "DelKey")
o(Test, "Options", "Col3", "DelKey")

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % Test, % "ahk_id" EditControlId

gui, show

;__

msgbox, % ""
. "'Test' var contains " . o(Test, "<=CountSections") . " sections!"        "`r`n"
. "`r`n"
. "'1' means section exist, 'blank/empty' means section does not exist:"    "`r`n"
. "`r`n"
. "'Col1' section in 'Test' var = " o(Test, , "Col1", "CheckSection")       "`r`n"
. "'Col2' section in 'Test' var = " o(Test, , "Col2", "CheckSection")       "`r`n"
. "'Col3' section in 'Test' var = " o(Test, , "Col3", "CheckSection")       "`r`n"
. "'Col4' section in 'Test' var = " o(Test, , "Col4", "CheckSection")       "`r`n"
. "'Col5' section in 'Test' var = " o(Test, , "Col5", "CheckSection")       "`r`n"
. "'Col'  section in 'Test' var = " o(Test, , "Col",  "CheckSection")       "`r`n"
. "'ttt'  section in 'Test' var = " o(Test, , "ttt",  "CheckSection")       "`r`n"

;__

msgbox, % ""
. "'1' means key exist, 'blank/empty' means key does not exist:"                "`r`n"
. "`r`n"
. "'Color'   key in 'Col1' section = " o(Test, "Color",   "Col1", "CheckKey")   "`r`n"
. "'Type'    key in 'Col1' section = " o(Test, "Type",    "Col1", "CheckKey")   "`r`n"
. "'Options' key in 'Col1' section = " o(Test, "Options", "Col1", "CheckKey")   "`r`n"
. "'xxxxxxx' key in 'Col1' section = " o(Test, "xxxxxxx", "Col1", "CheckKey")   "`r`n"

;__

msgbox, % ""
. "First Section is '"  o(Test, "<=S1")  "'"         "`r`n"
. "`r`n"
. "Content of first section: `r`n" o(Test, "<=C1")   "`r`n"

msgbox, % ""
. "second Section is '"  o(Test, "<=S2")  "'"         "`r`n"
. "`r`n"
. "Content of second section: `r`n" o(Test, "<=C2")   "`r`n"

msgbox, % ""
. "third Section is '"  o(Test, "<=S3")  "'"         "`r`n"
. "`r`n"
. "Content of third section: `r`n" o(Test, "<=C3")   "`r`n"

;__

msgbox, % ""
. "RegEx pattern that FindAnySection from 'o()' function objects:   `n`n"
. o("FindAnySection", "<=Get") 


return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.4 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnySection := "s)#(.*?)#@(.*?)#End#!"

Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (key = "<=Get")
return, (%Var%)		;returns the values of static variables of this function! (Mainly for "FindAnyKey" var)

	if (Key = "<=CountSections")
	{
	RegExReplace(Var, "#End#!", , TotalReplace)
	return, TotalReplace
	}

	if RegExMatch(Key, "i)^<=(S|C)(\d+)$", Found)
	{
	GetWhat := Found1, GetX := Found2

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(Var, FindAnySection, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "S" ? RegExReplace(Match1, "#_", "#") : Match2
			}
		}
	}

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

if (Key = "GetIndex=>")
key := "", Task := "GetSectionIndex"

if RegExMatch(Key, "i)^(k|v)(\d+)=>$", Found)
key := "", GetWhat := Found1, GetX := Found2

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

if (Task = "CheckSection")
return, SectionExist

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

if (Task = "CheckKey")
return, KeyExist

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (GetWhat != "")
	{
		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(SectionContent, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "k" ? RegExReplace(Match1, "#_", "#") : RegExReplace(Match4, "#_", "#")
			}
		}
	}

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (Task = "DelKey")
	{
	SectionContent := RegExReplace(SectionContent, FindKey "`r`n")		;Delete "Key" from "section"

	EditedSection := "#" Section "#@" SectionContent "#End#!"

	EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	Var := RegExReplace(Var, FindSection, EditedSection)
	}

	if (Task = "GetSectionIndex")
	{
	RegExReplace(SectionContent, FindAnyKey,, TotalReplace)
	return, TotalReplace
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if RegExMatch(IndexFound, "^0")
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}

More extensive example:

Code: Select all

	;uncomment the "Local" line inside the function if you use AutoHotKey v1.1.27+
	;Force all variables in the function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;the function was tested in AutoHotKey 1.1.23.05


	;"##@" is the blank section (Which is the main section)

LV = 
(join`r`n
##@
#Test#=#Type#
#Type#=#T #_#_ #_@ #_! MainSection#
#Options# = #O MainSection#
#Col1# = #Col1 MainSection#
#End#!

#Col1#@
#Test#=#Type#
#Type# = #T1#
#Options# = #O1#
#Col2# = #Col2 111#
#End#!

#Col2#@
#Test#=#Type#
#Type#  =  #T2#
#Options# = #O2#
#Col3# = #Col3 222#
#End#!

#Col3#@
#Test#=#Type#
#Type#    =    #T3#
#Options# = #O3#
#Col4# = #Col4 333#
#End#!

#End#@
#Test#=#Type#
#Type#		=		#T End#
#Options# = #O End#
#Col5# = #Col5 End#
#End#!


)	;Extra "`r`n`r`n" at the end just for better testing

o(LV, "Test" , , "=", " Value #Col2#@ - #End#! Value ")
o(LV, " Key #Col2#@ - #End#! Key ", , "=", "Test2")

o(LV, "Test", "NewSection", "=", "Type")
o(LV, "type", "NewSection", "=", "T NewSection")
o(LV, "Option", "NewSection", "=", "O NewSection")
o(LV, "type", "NewSection", "=", "T NewSection - EEEE")

o(LV, "Test", "NewSection5", "=", "Type")
o(LV, "type", "NewSection5", "=", "T NewSection5")
o(LV, "Option", "NewSection5", "=", "O NewSection5")
o(LV, "type", "NewSection5", "=", "T NewSection5 - EEEE")

o(LV, "Test", "NewSection0", "=", "NewSection0")

o(LV, "Test", "#Col7#@", "=", "Type #Col7#@")
o(LV, "Test", "Col7", "=", "Type")
o(LV, "Type", "Col7", "=", "T7")

o(LV, "zazaza", "za1", "=", "zaaaaaaaaaaaa")
o(LV, "tatata", "ta1", "=", "taaaaaaaaaaaa")
o(LV, "Test", "yu0", "=", "Type")

o(LV, "Test", "10", "=", "Index Only Test 10")

o(LV, "Test", "House23Floor11", "=", "House Test 11")

o(LV, "Test", "NewSection", "<=", "Insert Test NewSection")		;this will be ignored because there is no number in the end
o(LV, "Test", "NewSection0", "<=", "Insert Test NewSection0")		;this will be ignored because number at the end is 0
o(LV, "Test", "NewSection1", "<=", "Insert Test NewSection1")
o(LV, "Test", "NewSection4", "<=", "Insert Test NewSection4")
o(LV, "Test", "NewSection10", "<=", "Insert Test NewSection10")		;"NewSection10" section does not exist, but it will be created anyway

o(LV, , "5", "DelSection")
o(LV, , "House23Floor10", "DelSection")

;_______________

	;"=>" Adds or Modifies existing "Keys" (Examples below:)
	;The "Keys" and "Values" must be enclosed by ##
	;any "#" that belongs to "key" or "value" must be pos-escaped with an "_"
	;which means that, any "#_" represents a literal "#" character

o(LV, "#Car# = #Toyota#, #Ass# = #Really Big#, #Status# = #Main# =>")	;Adding multiple keys-values in "blank\Main" section (Note that string must end with an "=>")

o(LV, "#Car# = #Toy2# / #Status# = #Main2# / #x# = #x2# =>", "Col2")	;Adding multiple keys-values in "col2" section (note that / is used instead , as separator)
o(LV, "#Car# = #Toy3#   #Type# = #Main3-3#   #x# = #x3# =>", "Col3")	;note that separator is optional

o(LV, "#Ca #_ = #_ r# = #Toy #_ Esc#   #Type# = #T #_ Esc#   #x# = #x #_ Esc# =>", "EscapeTest")

	;in case you don't want to worry about enclosing/Pos-Escaping manually, you can tell the o() function to do it for you automatically:

o(LV, o("Car") "=" o("Toy4") . o("Type") "=" o("T 4")  . o("x") "=" o("x4") "=>", "Col4")

o(LV, o("Car") "=" o("Toyz") . o("Type") "=" o("T z")  . o("x") "=" o("xz") "=>", "Colz")

o(LV, o("Ca # = # r") "=" o("Toy # Esc3") . o("Type") "=" o("T # Esc3")  . o("x") "=" o("x # Esc3") "=>", "EscapeTest3")

	;the o() function will automatically enclose "Keys" and "Values" between ##
	;the o() function will automatically replace any "#" that belongs to "Keys" or "Values" with "#_" (pos-escapes # with _)

	
	;"+=>", will create a new "NewSection5" section, the previous "NewSection5" section will be made "NewSection6" section, and so on ...!

o(LV, "#Car# = #Toy new 5#   #Type# = #T new 5#   #x# = #x new 5# +=>", "NewSection5")

o(LV, "#Car# = #Toy new y#   #Type# = #T new y#   #x# = #x new y# +=>", "yyy")		;will be ignored because, "yyy" should end with a number > 0
o(LV, "#Car# = #Toy new z#   #Type# = #T new z#   #x# = #x new z# +=>", "zzz0")		;will be ignored because, "zzz" should end with a number > 0

o(LV, "#Car# = #Toy new s#   #Type# = #T new s#   #x# = #x new s# +=>", "sss3")		;will not be ignored because, "sss" ends with a number > 0

o(LV, "#Car# = #Toy new t#   #Type# = #T new t#   #x# = #x new t# +=>", "ttt03")	;will be ignored because number contains leading zeros
o(LV, "#Car# = #Toy new r#   #Type# = #T new r#   #x# = #x new r# +=>", "rrr003")	;will be ignored because number contains leading zeros

o(Lv, "test","aaa004", "<=", "test a")	;will be ignored because number contains leading zeros

o(Lv, "test","ggg004", "=", "test g004")	;creates only "ggg004" section, instead sections "ggg1" to "ggg4"
o(Lv, "test","ggg3", "<=", "test g3")
o(Lv, "test","ggg2", "<=", "test g inserted at ggg2")
;(v1.3 fixed), any section that ends by 0 or by an interger number that contains leading zero\s will be ignored while Updating section index! 
;Inside "UpdateSectionIndex", the line, if (IndexFound = 0), was replaced with, if RegExMatch(IndexFound, "^0")
;so, in this case, after inserting the new "ggg2" section, "ggg004" section will not be replaced with "ggg1", because it ends by "004" that contains 2 leading zeros!

;_______________

o(Lv, , "Colz", "DelSectionContent")

o(Lv, o(Lv, "Get=>", "Col1") "=>", "za1")	;get keys-values from "Col1" section and paste them in "za1" section

o(Lv, o(Lv, "Get=>", "Col1") "-=>", "ta1")	;Delete content of "ta1" section, then get keys-values from "Col1" section and paste them in "ta1" section

o(Lv, o(Lv, "Get=>", "Col1") "+=>", "za1")	;create new "za1" section, get keys-values from "Col1" section and paste them in the new "za1" section (the previous "za1" is made "za2" section)

o(Lv, "Options", "Col1", "DelKey")

	;o(LV, "Test", "Col467", "=", "Type")
	;o(LV, "Test", "94", "=", "Type")
	;o(LV, "Test", "8999", "=", "Type")

gui, add, edit, w600 h400 +HwndEditControlId,

ControlSetText , , % LV, % "ahk_id" EditControlId

gui, show

;msgbox, % o(LV, "")            "`n`n"
;msgbox, % o(LV, "", "Col1")    "`n`n"
;msgbox, % o(LV, "", "Col2")    "`n`n"
;msgbox, % o(LV, "", "Col3")    "`n`n"
;msgbox, % o(LV, "", "Col4")    "`n`n"
;msgbox, % o(LV, "", "End")     "`n`n"

msgbox, % o(LV, "Type")            "`n`n"	;get "Type" value from blank section (Which is the main section)
msgbox, % o(LV, "Type", "Col1")    "`n`n"	;get "Type" value from "Col1" section
msgbox, % o(LV, "Type", "Col2")    "`n`n"	;get "Type" value from "Col2" section
msgbox, % o(LV, "Type", "Col3")    "`n`n"	;and so on ...!
msgbox, % o(LV, "Type", "Col4")    "`n`n"
msgbox, % o(LV, "Type", "End")     "`n`n"
msgbox, % o(LV, "Type", "Col7")     "`n`n"

msgbox, % ""
. "Index = " o(LV, "GetIndex=>") " = Total Keys-Values"            "`n"		;Get Index of "Blank\Main" section!
. "Index = " o(LV, , , "GetSectionIndex") " = Total Keys-Values"   "`n"		;Get Index of "Blank\Main" section!
. o(LV, , , "GetSection")                                          "`n`n"	;Get content of "Blank\Main" section!

msgbox, % ""
. "Index = " o(LV, "GetIndex=>", "Col2") " = Total Keys-Values"         "`n"	;Get Index of "Col2" section!
. "Index = " o(LV, , "Col2", "GetSectionIndex") " = Total Keys-Values"  "`n"	;Get Index of "Col2" section!
. o(LV, , "Col2", "GetSection")                                         "`n`n"	;Get content of "Col2" section!

msgbox, % ""
. "Index = " o(LV, "GetIndex=>", "Col3") " = Total Keys-Values"         "`n"	;Get Index of "Col3" section!
. "Index = " o(LV, , "Col3", "GetSectionIndex") " = Total Keys-Values"  "`n"	;Get Index of "Col3" section!
.  o(Lv, "Get=>", "Col3")	                                                ;Get content of "Col3" section!

msgbox, % ""
. "k1v1 of 'Blank\Main' section: `n" 
. o(Lv, "k1=>") " : " o(Lv, "v1=>")   "`n`n"	;Get the 1st(first) Key-Value of "Blank\Main" section
. "k5v5 of 'Blank\Main' section: `n"
. o(Lv, "K5=>") " : " o(Lv, "V5=>")   "`n"	;Get the 5th(fifth) Key-Value of "Blank\Main" section
. "__`n`n"
. "k2v2 of 'Col3' section: `n"
. o(Lv, "k2=>", "Col3") " : " o(Lv, "v2=>", "Col3")   "`n`n"	;Get the 2nd(second) Key-Value of "Col3" section
. "k6v6 of 'Col3' section: `n"
. o(Lv, "k6=>", "Col3") " : " o(Lv, "v6=>", "Col3")   "`n"	;Get the 6th(sixth) Key-Value of "Col3" section

;__

loop, % o(Lv, "GetIndex=>")		;AHK "For-loop" Equivalent (Easier way, but slower!)
msgbox, % ""				;Applying "For-loop" in "Blank\Main" section 
. "K" a_index "V" a_index " of 'Blank\Main' section:  `n`n"
. o(Lv, "k" a_index "=>") " : " o(Lv, "v" a_index "=>")

loop, % o(Lv, "GetIndex=>", "Col3")	;AHK "For-loop" Equivalent (Easier way, but slower!)
msgbox, % ""				;Applying "For-loop" in "Col3" section 
. "K" a_index "V" a_index " of 'Col3' section:  `n`n"
. o(Lv, "k" a_index "=>", "Col3") " : " o(Lv, "v" a_index "=>", "Col3")

;__

msgbox, % ""
. "RegEx pattern that FindAnyKey from a Section content:   `n`n"
. o("FindAnyKey", "<=Get") 

;__

FoundPos := 1			;AHK "For-loop" Equivalent (Less Easier way, but Faster!)
MatchLenght := 0
loop, % o(Lv, "GetIndex=>")	;get index of "Blank\Main" section
{
FoundPos := RegExMatch(o(Lv, "Get=>"), o("FindAnyKey", "<=Get"), Match, FoundPos + MatchLenght)

MatchLenght := StrLen(Match)

key := RegExReplace(Match1, "#_", "#")

value := RegExReplace(Match4, "#_", "#")

msgbox, % ""
. "(For-Loop - Less Easier way, but faster!) `n`n"
. "k" a_index "v" a_index " of 'Blank\Main' section:   `n`n"
. key " : " Value
}

FoundPos := 1				;AHK "For-loop" Equivalent (Less Easier way, but Faster!)
MatchLenght := 0
loop, % o(Lv, "GetIndex=>", "Col3")	;get index of "Col3" section
{
FoundPos := RegExMatch(o(Lv, "Get=>", "Col3"), o("FindAnyKey", "<=Get"), Match, FoundPos + MatchLenght)

MatchLenght := StrLen(Match)

key := RegExReplace(Match1, "#_", "#")

value := RegExReplace(Match4, "#_", "#")

msgbox, % ""
. "(For-Loop - Less Easier way, but faster!) `n`n"
. "k" a_index "v" a_index " of 'Col3' section:   `n`n"
. key " : " Value
}

;__

msgbox, % ""
. "Sections in ''Lv'' var = " o(Lv, "<=CountSections")    "`n"
. "`n"
. "1 = Section Exist / Blank\Empty = section does not exist"    "`n"
. "''Col1'' section = " o(Lv, , "Col1", "CheckSection")         "`n"
. "''Col2'' section = " o(Lv, , "Col2", "CheckSection")         "`n"
. "''Main\Blank'' section = " o(Lv, , , "CheckSection")         "`n"
. "''Col59'' section = " o(Lv, , "Col59", "CheckSection")       "`n"
. "''xxxxx'' section = " o(Lv, , "xxxxx", "CheckSection")       "`n"
. "''zzzzz'' section = " o(Lv, , "zzzzz", "CheckSection")       "`n"
. "`n"
. "1 = Key Exist / Blank\Empty = Key does not exist!    `n"
. "''Options'' key in ''Main\Blank'' Section = " o(Lv, "Options", , "CheckKey")   "`n"
. "''xxxxxxx'' key in ''Main\Blank'' Section = " o(Lv, "xxxxxxx", , "CheckKey")   "`n"
. ""
. "''Type'' key in ''Col1'' Section = " o(Lv, "Type", "Col1", "CheckKey")         "`n"
. "''Options'' key in ''Col1'' Section = " o(Lv, "Options", "Col1", "CheckKey")   "`n"
. ""
. "''Status'' key in ''Col2'' Section = " o(Lv, "Status", "Col2", "CheckKey")    "`n"
. "''zzzzzz'' key in ''Col2'' Section = " o(Lv, "zzzzzz", "Col2", "CheckKey")    "`n"


msgbox, % ""
. "Section 1 = '" o(LV, "<=S1") "' / Section 2 = '" o(LV, "<=s2") "' / Section 3 = '" o(LV, "<=s3") "'"   "`r`n"
. "`r`n"
. "Content of Section 1 (below): `r`n" o(LV, "<=C1")


msgbox, % ""
. "Last Section = '" o(LV, "<=s" o(LV, "<=CountSections")) "'"   "`r`n"
. "`r`n"
. "Content of Last Section (below): `r`n" o(LV, "<=C" o(LV, "<=CountSections"))


msgbox, % ""
. "RegEx pattern that FindAnySection from 'o()' function objects:   `n`n"
. o("FindAnySection", "<=Get") 


return

guiclose:	;__________________________ Gui Close ___________________________
exitapp


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.4 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnySection := "s)#(.*?)#@(.*?)#End#!"

Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (key = "<=Get")
return, (%Var%)		;returns the values of static variables of this function! (Mainly for "FindAnyKey" var)

	if (Key = "<=CountSections")
	{
	RegExReplace(Var, "#End#!", , TotalReplace)
	return, TotalReplace
	}

	if RegExMatch(Key, "i)^<=(S|C)(\d+)$", Found)
	{
	GetWhat := Found1, GetX := Found2

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(Var, FindAnySection, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "S" ? RegExReplace(Match1, "#_", "#") : Match2
			}
		}
	}

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

if (Key = "GetIndex=>")
key := "", Task := "GetSectionIndex"

if RegExMatch(Key, "i)^(k|v)(\d+)=>$", Found)
key := "", GetWhat := Found1, GetX := Found2

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

if (Task = "CheckSection")
return, SectionExist

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

if (Task = "CheckKey")
return, KeyExist

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (GetWhat != "")
	{
		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(SectionContent, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "k" ? RegExReplace(Match1, "#_", "#") : RegExReplace(Match4, "#_", "#")
			}
		}
	}

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (Task = "DelKey")
	{
	SectionContent := RegExReplace(SectionContent, FindKey "`r`n")		;Delete "Key" from "section"

	EditedSection := "#" Section "#@" SectionContent "#End#!"

	EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	Var := RegExReplace(Var, FindSection, EditedSection)
	}

	if (Task = "GetSectionIndex")
	{
	RegExReplace(SectionContent, FindAnyKey,, TotalReplace)
	return, TotalReplace
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if RegExMatch(IndexFound, "^0")
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] - O() - Simple Object Function!

29 Nov 2018, 13:18

Hehe, Built-in object is really faster than "o()" function object!

o(Funcion) _VS_ Built-in Object (Speed Test).png
o(Funcion) _VS_ Built-in Object (Speed Test).png (12.48 KiB) Viewed 2764 times

Code: Select all

gui, wait: add, text, w200 h100, please wait
gui, wait: show 

LoopTime := 5000

gui, add, text, , % "For LoopTime = " LoopTime ":"

;___

Test := []

Temp_Start := A_TickCount
loop, % LoopTime
Test.x .= "x"

gui, add, text, Section, % "Built-in Object took " . A_TickCount - Temp_Start . " milliseconds!"
gui, add, edit, w250 h200 +HScroll, % Test.x

;___

Test := ""

Temp_Start := A_TickCount
loop, % LoopTime
o(Test, "y", , "=", o(Test, "y") "y")

gui, add, text, ys, % "o(Function) Object took " . A_TickCount - Temp_Start . " milliseconds!"
gui, add, edit, w250 h200 +HScroll, % o(Test, "y")
gui, add, edit, x+5 w250 h200 +HScroll, % Test

;___

gui, wait: destroy

gui, show

return

guiclose:	;_________ gui close ________
waitguiclose:
exitapp


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.4 _________________________ 
{

;Local	;uncomment this line if you use AutoHotKey v1.1.27+
	;Force all variables in this function to be "Local" vars (with no exceptions)
	;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
	;this function was tested in AutoHotKey 1.1.23.05

	;Local AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnySection := "s)#(.*?)#@(.*?)#End#!"

Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (key = "<=Get")
return, (%Var%)		;returns the values of static variables of this function! (Mainly for "FindAnyKey" var)

	if (Key = "<=CountSections")
	{
	RegExReplace(Var, "#End#!", , TotalReplace)
	return, TotalReplace
	}

	if RegExMatch(Key, "i)^<=(S|C)(\d+)$", Found)
	{
	GetWhat := Found1, GetX := Found2

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(Var, FindAnySection, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "S" ? RegExReplace(Match1, "#_", "#") : Match2
			}
		}
	}

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

if (Key = "GetIndex=>")
key := "", Task := "GetSectionIndex"

if RegExMatch(Key, "i)^(k|v)(\d+)=>$", Found)
key := "", GetWhat := Found1, GetX := Found2

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

if (Task = "CheckSection")
return, SectionExist

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

if (Task = "CheckKey")
return, KeyExist

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (GetWhat != "")
	{
		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(SectionContent, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "k" ? RegExReplace(Match1, "#_", "#") : RegExReplace(Match4, "#_", "#")
			}
		}
	}

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (Task = "DelKey")
	{
	SectionContent := RegExReplace(SectionContent, FindKey "`r`n")		;Delete "Key" from "section"

	EditedSection := "#" Section "#@" SectionContent "#End#!"

	EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	Var := RegExReplace(Var, FindSection, EditedSection)
	}

	if (Task = "GetSectionIndex")
	{
	RegExReplace(SectionContent, FindAnyKey,, TotalReplace)
	return, TotalReplace
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if RegExMatch(IndexFound, "^0")
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: gwarble and 121 guests