Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

String - Methods/Properties (AHK_L)


  • Please log in to reply
10 replies to this topic
jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
I wrote this script mainly to help myself learn AutoHotkey_L better, but I thought maybe some other people might find it helpful as well.
 
class StringLib {
    static init := ("".base.base := StringLib)
    static __Set := Func("StringLib_Set")
    Left(count=1) {
       return, SubStr(this, 1, count)
    }
    Right(count=1) {
       StringRight, out, this, count
       return, out
    }
    TrimL(count="") {
        if count.is_Str
            out := count? LTrim(this, count):LTrim(this)
        else
            StringTrimLeft, out, this, count
        return, out
    }
    TrimR(count="") {
        if count.is_Str
            return, count? RTrim(this, count):RTrim(this)
        else
            StringTrimRight, out, this, count
        return, out
    }
    Count(count) {
        StringReplace, this, this, %count%, , UseErrorLevel
        return, ErrorLevel
    }
    Replace(find, replace="") {
       StringReplace, out, this, %find%, %replace%, A
       return, out
    }
    GSub(needle, replace="") {
        return, RegExReplace(this, needle, replace)
    }
    Times(times) {
        VarSetCapacity(out, times)
        Loop, %times%
            out .= this
        return, out
    }
    Split(delim="", omit="") {
        out := object()
        if (SubStr(delim, 1, 2) = "R)") {
            this := this.Replace(omit), pos := 0, n:=start:=1
            if ((needle:=SubStr(delim, 3))="")
                return, this.Split(needle)
            while, pos := RegExMatch(this, needle, match, start)
                out[n++] := SubStr(this, start, pos-start), start := pos+StrLen(match)
            out[n] := SubStr(this, start)
        } else 
            Loop, Parse, this, %delim%, %omit%
                out[A_Index] := A_LoopField 
        return, out 
    } 
    RemoveLines(lines) {
        VarSetCapacity(out, n:=StrLen(this))
        Loop, Parse, this, `n, `r 
            if A_Index not in %lines%
                out .= A_LoopField "`n" 
        return, SubStr(out, 1, -1)
    }
    KeepLines(lines) {
        VarSetCapacity(out, n:=StrLen(this))
        Loop, Parse, this, `n, `r 
            if A_Index in %lines%
                out .= A_LoopField "`n" 
        return, SubStr(out, 1, -1)
    }
    __Get(key, key2="") {
        if (key = "is_int") {
            if this is integer
                out := true
            else, 
                out := false
        } else if (key = "upper")
            StringUpper, out, this
        else if (key = "lower")
            StringLower, out, this
        else if (key = "capitalize")
            out := SubStr(this, 1, 1).upper . SubStr(this, 2).lower
        else if (key = "reverse") or (key = "rev")
            DllCall("msvcrt\_" (A_IsUnicode? "wcs":"str") "rev", "UInt",&this, "CDecl"), out:=this
        else if (key = "length") or (key = "len")
            out := StrLen(this)
        else if (key = "isEmpty")
            out := StrLen(this)? False:True
        else if key.is_int and key2.is_int
            out := SubStr(this, key, key2)
        else if key.is_int and key2=""
            out := SubStr(this, key, 1)
        else if (key = "toHex") {
            format := A_FormatInteger
            SetFormat, IntegerFast, Hex
            out := "" this+0 ""
            SetFormat, IntegerFast, %format%
        } else if (key = "toDec") {
            format := A_FormatInteger
            SetFormat, IntegerFast, Dec
            out := "" this+0 ""
            SetFormat, IntegerFast, %format%
        } else if (key = "is_str") {
            Format := A_FormatInteger
            SetFormat, IntegerFast, Hex
            out := SubStr(this:=this, 1, 2)="0x"? False:True
            SetFormat, IntegerFast, %Format%
        }
        return, out
    }
}
StringLib_Set(byref this, key, value){
	StringReplace, this, this, %key%, %value%, all
}
To use this, save the above code as a file named StringLib.ahk in your user Lib folder. Then place #Include <StringLib> at the beginning of your script. (requires AHK_L)

Example Uses:
#Include <StringLib>

var := "AutoHotkey"
MsgBox % var.Length
MsgBox % var[5]
MsgBox % var.Upper
MsgBox % "AutoHotkey".Lower
MsgBox % var.Reverse
MsgBox % var.Left(4)
MsgBox % var.Right(6)
MsgBox % var.Replace("utoHotkey","HK")
MsgBox % var[5,3]
#Include <StringLib>

var =
(
line1
line2
line3
line4
)
MsgBox, % var.RemoveLines("1,3")
MsgBox, % var.KeepLines("1,3")


fincs
  • Moderators
  • 1662 posts
  • Last active:
  • Joined: 05 May 2007
I had something similar:
; Initialize syntactic sugar
SynSugar()

s := String_new()
s.append("Hello World")
s.face := "die"
s.append("Appending content: " s.MyBoy)
msgbox % s.content

; Wipe the contents
s.wipe()

s.append("New stuff")
s.die := "face"
s.append("Appending content: " s.AllTrueWarriors)
msgbox % s.content

ObjDelete(s)

; Test ini
ini =
(
[Sec1]
val1 = Hello
val2 = World

[Sec2]
val1 = My
val2 = boy
)

ini := IniToObject(ini)
MsgBox % ini["Sec1", "val1"] " " ini["Sec1", "val2"]
MsgBox % ini["Sec2", "val1"] " " ini["Sec2", "val2"]

; Test syntactic sugar
msgbox % myvar.assign("die") myvar
msgbox % "4,1,3,2".sort("D,")
msgbox % "abc".is("integer") " " (45).is("integer") " " (45.14).is("float")
msgbox % "faceface".toupper() " FACEFACE".tolower()
msgbox % "|" "    `t`t`tText surrounded by stuff`t`t`t    ".trim() "|"
msgbox % "|" "    `t`t`tText surrounded by stuff`t`t`t    ".ltrim() "|"
msgbox % "|" "    `t`t`tText surrounded by stuff`t`t`t    ".rtrim() "|"
msgbox % "AAAfacefaceAAA".trim("A")
msgbox % "FaceFace".replace("Face", "Die")
msgbox % "Match: " "FaceFace".match("^\w+$")
msgbox % "fACefAce".rereplace("(\w)[aA][cC][eE]", "$U1aceDie")
msgbox % "intformat: " "255".intformat("h")
msgbox % "floatformat: " "3.141592".floatformat("0.4")

q := "this,is,a,test".split(",")
Loop, % q._MaxIndex()
	MsgBox % "q[" A_Index "] = " q[A_Index] "`nq[" A_Index "].len() = " q[A_Index].len()

; Test errors
Face.Yes := "face".No
"face".Invalid()

; User-defined properties test
SS_AddProp("content", "Content")
msgbox % "Content get: " "face".content
msgbox % "Content set: " (q.content := "Yes")

String_new(){
	Static String_base
	if(!IsObject(String_base))
		String_base := Object("append", "String_append", "wipe", "String_wipe", "__Set", "String__Set", "__Get", "String__Get", "__Delete", "String__Delete")
	rObj := Object("base", String_base)
	rObj._Insert("content", "") ; add the content variable
	return rObj
}

String__Set(obj, name, val){
	obj.append("**LOG** " name " was assigned the value '" val "'")
	return val
}

String__Get(obj, name){
	obj.append("**LOG** " name " was requested - returning 'dummy'")
	return "dummy"
}

String__Delete(obj){
	msgbox String object was deleted
	obj.wipe()
}

String_append(obj, val){
	obj.content := obj.content val "`r`n"
}

String_wipe(obj){
	obj._Remove("content")
	obj._Insert("content", "")
}

;----------------------------------------------------------

IniToObject(ini){
	oIni := Object()
	section := ""
	Loop, Parse, ini, `n, `r
	{
		line := A_LoopField.trim()
		if(line.match("^\[(.+)\]$", o))
			section := o1.trim()
		else if(section && line.match("^(.+?)=(.*?)$", o))
			oIni[section, o1.trim()] := o2.trim()
	}
	return oIni
}

Content_Get(var){
	return var
}

Content_Set(ByRef var, val){
	return var := val
}

;----------------------------------------------------------

SynSugar(){
	Global __SS_Props
	
	; Shorthands to built-in functions
	"".base.subs := "SubStr"
	"".base.len := "StrLen"
	"".base.Trim := "Trim"
	"".base.LTrim := "LTrim"
	"".base.RTrim := "RTrim"
	"".base.Match := "RegExMatch"
	"".base.REReplace := "RegExReplace"
	"".base.Find := "InStr"
	
	; Shorthands to special functions
	"".base.Replace := "__Base_Replace"
	"".base.ToUpper := "__Base_ToUpper"
	"".base.ToLower := "__Base_ToLower"
	"".base.Split := "__Base_Split"
	"".base.IntFormat := "__Base_IntFormat"
	"".base.FloatFormat := "__Base_FloatFormat"
	"".base.Is := "__Base_Is"
	"".base.Assign := "__Base_Assign"
	"".base.Sort := "__Base_Sort"

	; Meta-functions for debug & extensibility
	"".base.__Get := "__Base__Get"
	"".base.__Set := "__Base__Set"
	"".base.__Call := "__Base__Call"

	; Array to hold names of custom Set/Get functions for properties
	__SS_Props := Object()
}

SS_AddProp(prop, handler){
	Global __SS_Props
	__SS_Props[prop] := handler
}

ObjDelete(ByRef obj){
	obj := ""
}

__Base__Get(var, key){
	Global __SS_Props

	key := key.trim()
	func := __SS_Props[key] "_Get"
	if(!IsFunc(func))
		goto __Base_Get_ErrHandler

	return %func%(var)

__Base_Get_ErrHandler:
	ListLines
	MsgBox Invalid GET operation: %key%
	return ""
}

__Base__Set(ByRef var, key, val){
	Global __SS_Props

	key := key.trim()
	func := __SS_Props[key] "_Set"
	if(!IsFunc(func))
		goto __Base_Set_ErrHandler

	return %func%(var, val)

__Base_Set_ErrHandler:
	ListLines
	MsgBox Invalid SET operation: %key%
	return ""
}

__Base__Call(var, func, p1="", p2="", p3="", p4="", p5="", p6="", p7="", p8=""){

__Base_Call_ErrHandler:
	ListLines
	MsgBox Invalid CALL operation: %func%
	return ""
}

__Base_Replace(txt, a, b){
	StringReplace, txt, txt, % a, % b, All
	return txt
}

__Base_ToUpper(txt){
	StringUpper, txt, txt
	return txt
}

__Base_ToLower(txt){
	StringLower, txt, txt
	return txt
}

__Base_Split(txt, delim, omit=""){
	obj := Object()
	Loop, Parse, txt, % delim, % omit
		obj[A_Index] := A_LoopField
	return obj
}

__Base_IntFormat(num, format=""){
	num := Floor(num) ; force integer
	oldfmt := A_FormatInteger
	SetFormat, IntegerFast, %format%
	num .= "" ; update internal string representation
	SetFormat, IntegerFast, %oldfmt%
	return num "" ; force string
}

__Base_FloatFormat(num, format=""){
	num += 0.0 ; force float
	oldfmt := A_FormatFloat
	SetFormat, FloatFast, %format%
	num .= "" ; update internal string representation
	SetFormat, FloatFast, %oldfmt%
	return num "" ; force string
}

__Base_Is(var, type){
	if var is %type%
		return true
	else
		return false
}

__Base_Assign(ByRef var, value=""){
	var := value
	return var
}

__Base_Sort(list, options=""){
	Sort, list, %options%
	return list
}


sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008
Wow, that explains some of the concepts that made me hesitate to use the object functions of AHK_L, thanks!

Obviously it's just a sample but you could shorten the String_Properties function down slightly, no?

String_Properties(string, key) { 
   If (key = "upper")
      StringUpper, string, string 
   If (key = "lower")
      StringLower, string, string 
   If (key = "reverse")
      DllCall("msvcrt\_strrev", "UInt",&string, "CDecl")
   If (key = "length") 
      string:=StrLen(string) 
   If key is integer 
      string:=SubStr(string, key, 1) 
   return, string
}

I also found that the String_Properties function limited some string extraction operations for my taste so I rewrote it in this fashion:

String_Properties(string, key,[color=red] len=""[/color]) { 
   If (key = "upper") 
      StringUpper, string, string 
   If (key = "lower") 
      StringLower, string, string 
   If (key = "reverse") 
      DllCall("msvcrt\_strrev", "UInt",&string, "CDecl") 
   If (key = "length") 
      string:=StrLen(string) 
[color=red]   If len
      string:=SubStr(string, key, len) 
   If !len
      string:=SubStr(string, key)[/color]
   return, string 
}

Thanks again for the code! Provided much needed illumination!

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

"".base.LTrim := "String_LTrim"
	"".base.RTrim := "String_RTrim"
	...
	"".base.SubStr := "String_SubStr"

I can't confirm atm, but I suppose you can discard String_LTrim, '_RTrim and '_SubStr by replacing the above with the below:
"".base.LTrim := "LTrim"
"".base.RTrim := "RTrim"
"".base.SubStr := "SubStr"
Built-in functions can be used as "methods" in the same way as script functions, though it's probably only useful in cases like this. See Trim() for details about Trim, LTrim and RTrim.

<nitpicking>

If (key = "upper") 
      StringUpper, string, string 
   If (key = "lower") 
      StringLower, string, string 

Unlike jethrow's code (which returns as soon as it has found a match) this code performs every comparison every time. I'd simply add "else":
If key = upper
      StringUpper, string, string 
   Else If key = lower
      StringLower, string, string 
Also, traditional IF performs marginally better, but it's more a matter of personal preference. I'd use it because it looks a little "cleaner", but I suppose mixing traditional IF and expression IF can be confusing for some users...
</nitpicking>

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
@Lexikos

I'm continually impressed by your dedicated efforts to improve AHK & the AHK community :D. Thank you for the information.

Edit - Actually, I hesitated using LTrim/RTrim terminology because of your Trim function, but I didn't think it would matter since I wasn't planning on developing this script any more. The functionality of my LTrim/RTrim was to trim a number of characters, rather than specific characters. Is there a way to do this with you're Trim function?

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

The functionality of my LTrim/RTrim was to trim a number of characters, rather than specific characters.

Ah! I wasn't paying attention. :)

Is there a way to do this with you're Trim function?

No, I'd typically just use SubStr.

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
I did some more work on this library ( maybe someone will use it someday :p ). I have to give a special thanks to HotKeyIt for this post. Here is a script that shows most of the changes:
String_Lib()

var := "AutoHotkey"
MsgBox % "1) "	var.capitalize
	. "`n2) " .	var.reverse
	. "`n3) " .	var.isEmpty
	. "`n4) " .	"123".toHex
	. "`n5) " .	"0x7B".toDec
	. "`n6) " .	"123".isStr	; special thanks to HotKeyIt
	. "`n7) " .	(123).isStr
	. "`n8) " .	"123AutHotKey".LTrim( "12" )	; trim string
	. "`n9) " .	"123AutHotKey".LTrim( 4 )	; trim number of characters
	. "`n10 " .	"|" . "		123AutoHotKey".LTrim()	; regular LTrim() functionality
	. "`n11) " .	var.count( "t" )
	. "`n12) " .	"A".times( 5 )
	. "`n13) " .	var.gsub( "[A-Z]", "[$0]" )
	
array := "Testing[color=red],[/color]normal[color=red],[/color]split".split( "[color=red],[/color]" )
Loop, % array.count
	t1 .= A_Index " = " array[ A_Index ] "`n"
MsgBox, %t1%
	
array := "Testing[color=red]1[/color]RegEx[color=red]65[/color]split".split( "R)[color=red]\d+[/color]" ) ; use "R)" for RegEx Split
Loop, % array.count
	t2 .= A_Index " = " array[ A_Index ] "`n"
MsgBox, %t2%
If anyone has any suggestions/criticisms/questions, I'm open to comments.
[color=darkred]String_Lib()[/color] {
"".base.[color=olive]Left[/color] := "String_Left"
"".base.[color=olive]Right[/color] := "String_Right"
"".base.[color=olive]Replace[/color] := "String_Replace"
"".base.[color=olive]LTrim[/color] := "String_LTrim"
"".base.[color=olive]RTrim[/color] := "String_RTrim"
"".base.[color=olive]Count[/color] := "String_Count"
"".base.[color=olive]Times[/color] := "String_Times"
"".base.[color=olive]Split[/color] := "String_Split"

"".base.[color=olive]RemoveLines[/color] := "String_RemoveLines"
"".base.[color=olive]KeepLines[/color] := "String_KeepLines"

"".base.[color=olive]SubStr[/color] := "SubStr"
"".base.[color=olive]InStr[/color] := "InStr"
"".base.[color=olive]Trim[/color] := "Trim"
"".base.[color=olive]gsub[/color] := "RegExReplace"
"".base.__Get  := "String_Properties"
Return, True
}
[color=darkred]String_Properties( in, key )[/color] {
	If ( key = "[color=olive]upper[/color]" )
		StringUpper, out, in
	Else If ( key = "[color=olive]lower[/color]" )
		StringLower, out, in
	Else If ( key = "[color=olive]capitalize[/color]" )
		out := SubStr( in, 1, 1 ).upper . SubStr( in, 2 ).lower
	Else If ( key = "[color=olive]reverse[/color]" ) || ( key = "[color=olive]rev[/color]" ) ; http://www.autohotkey.com/forum/topic46040.html&start=5
		DllCall("msvcrt\_" ( A_IsUnicode ? "wcs" : "str" ) "rev", "UInt",&in, "CDecl"), out:=in
	Else If ( key = "[color=olive]length[/color]" ) || ( key = "[color=olive]len[/color]" )
		out := StrLen( in )
	Else If ( key = "[color=olive]isEmpty[/color]" )
		out := StrLen( in ) ? False : True
	Else If key is integer
		out := SubStr( in, key, 1 )
	Else If ( key = "[color=olive]toHex[/color]" ) {
		format := A_FormatInteger
		SetFormat, IntegerFast, Hex
		out := "" in+0 ""
		SetFormat, IntegerFast, %format%
	} Else If ( key = "[color=olive]toDec[/color]" ) {
		format := A_FormatInteger
		SetFormat, Integerfast, Dec
		out := "" in+0 ""
		SetFormat, IntegerFast, %format%
	} Else If ( key = "[color=olive]isStr[/color]" ) {
		Format := A_FormatInteger
		SetFormat, IntegerFast, Hex
		out := SubStr( in:=in, 1, 2 )="0x" ? False : True
		SetFormat, IntegerFast, %Format%
	}
	Return, out
}
[color=darkred]String_Left( in, count=1 )[/color] {
   Return, SubStr( in, 1, count )
}
[color=darkred]String_Right( in, count=1 )[/color] {
   StringRight, out, in, count
   Return, out
}
[color=darkred]String_LTrim( in, count="" )[/color] {
	If count.isStr
		out := count ? LTrim( in, count ) : LTrim( in )
	Else
		StringTrimLeft, out, in, count
	Return, out
}
[color=darkred]String_RTrim( in, count="" )[/color] {
	If count.isStr
		Return, count ? RTrim( in, count ) : RTrim( in )
	Else
		StringTrimRight, out, in, count
	Return, out
}
[color=darkred]String_Count( in, count )[/color] {
	StringReplace, in, in, %count%, , UseErrorLevel
	Return, ErrorLevel
}
[color=darkred]String_Replace( in, find, replace="" )[/color] {
   StringReplace, out, in, %find%, %replace%, A
   Return, out
}
[color=darkred]String_Times( in, times )[/color] {
	VarSetCapacity( out, times )
	Loop, %times%
		out .= in
	Return, out
}
[color=darkred]String_Split( in, delim="", omit="" )[/color] {
	out := object()
	If ( SubStr( delim, 1, 2 ) = "R)" ) {
		in := in.Replace( omit ), pos := 0, n:=start:=1
		If ( (needle:=SubStr( delim, 3 ))="" )
			Return, in.Split( needle )
		While, pos := RegExMatch( in, needle, match, start )
			out[n++] := SubStr( in, start, pos-start ), start := pos+StrLen( match )
		out[n] := SubStr( in, start )
	} Else 
		Loop, Parse, in, %delim%, %omit%
			out[ A_Index ] := A_LoopField
	out.base := object( "__Get", "Split_Count" )
	Return, out
}
[color=darkred]Split_Count( obj, key )[/color] {
	Return, key="count" ? obj._MaxIndex() : ""
}
[color=darkred]String_RemoveLines( in, lines )[/color] {
	VarSetCapacity( out, n:=StrLen( in ) )
	Loop, Parse, in, `n, `r 
		If A_Index not in %lines%
			out .= A_LoopField "`n" 
	Return, SubStr( out, 1, -1 )
}
[color=darkred]String_KeepLines( in, lines )[/color] {
	VarSetCapacity( out, n:=StrLen( in ) )
	Loop, Parse, in, `n, `r 
		If A_Index in %lines%
			out .= A_LoopField "`n" 
	Return, SubStr( out, 1, -1 )
}


Frankie
  • Members
  • 2930 posts
  • Last active: Feb 05 2015 02:49 PM
  • Joined: 02 Nov 2008
Would it be possible to do this with 1.1.0.0 class syntax?

I've tried reassigning the base to my class, extending "", extending "".base, and none of it works. The last two give errors.

Any ideas?
aboutscriptappsscripts
Request Video Tutorials Here or View Current Tutorials on YouTube
Any code ⇈ above ⇈ requires AutoHotkey_L to run

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
You should be able to just call this StringLib.ahk, put it in your Lib filder, then put #Include <StringLib> at the top of your script. If there's not errors, I'll replace the original post:
class StringLib {

    static init := ("".base.base := StringLib)

    static __Set := Func("StringLib_Set")

    Left(count=1) {

       return, SubStr(this, 1, count)

    }

    Right(count=1) {

       StringRight, out, this, count

       return, out

    }

    TrimL(count="") {

        if count.is_Str

            out := count? LTrim(this, count):LTrim(this)

        Else

            StringTrimLeft, out, this, count

        return, out

    }

    TrimR(count="") {

        if count.is_Str

            return, count? RTrim(this, count):RTrim(this)

        Else

            StringTrimRight, out, this, count

        return, out

    }

    Count(count) {

        StringReplace, this, this, %count%, , UseErrorLevel

        return, ErrorLevel

    }

    Replace(find, replace="") {

       StringReplace, out, this, %find%, %replace%, A

       return, out

    }

    Times(times) {

        VarSetCapacity(out, times)

        Loop, %times%

            out .= this

        return, out

    }

    Split(delim="", omit="") {

        out := object()

        if (SubStr(delim, 1, 2) = "R)") {

            this := this.Replace(omit), pos := 0, n:=start:=1

            if ((needle:=SubStr(delim, 3))="")

                return, this.Split(needle)

            while, pos := RegExMatch(this, needle, match, start)

                out[n++] := SubStr(this, start, pos-start), start := pos+StrLen(match)

            out[n] := SubStr(this, start)

        } else 

            Loop, Parse, this, %delim%, %omit%

                out[A_Index] := A_LoopField 

        return, out 

    } 

    RemoveLines(lines) {

        VarSetCapacity(out, n:=StrLen(this))

        Loop, Parse, this, `n, `r 

            if A_Index not in %lines%

                out .= A_LoopField "`n" 

        return, SubStr(out, 1, -1)

    }

    KeepLines(lines) {

        VarSetCapacity(out, n:=StrLen(this))

        Loop, Parse, this, `n, `r 

            if A_Index in %lines%

                out .= A_LoopField "`n" 

        return, SubStr(out, 1, -1)

    }

    __Get(key, key2="") {

        if (key = "is_int") {

            if this is integer

                out := true

            else, 

                out := false

        } else if (key = "upper")

            StringUpper, out, this

        else if (key = "lower")

            StringLower, out, this

        else if (key = "capitalize")

            out := SubStr(this, 1, 1).upper . SubStr(this, 2).lower

        else if (key = "reverse") or (key = "rev")

            DllCall("msvcrt\_" (A_IsUnicode? "wcs":"str") "rev", "UInt",&this, "CDecl"), out:=this

        else if (key = "length") or (key = "len")

            out := StrLen(this)

        else if (key = "isEmpty")

            out := StrLen(this)? False:True

        else if key.is_int and key2.is_int

            out := SubStr(this, key, key2)

        else if key.is_int and key2=""

            out := SubStr(this, key, 1)

        else if (key = "toHex") {

            format := A_FormatInteger

            SetFormat, IntegerFast, Hex

            out := "" this+0 ""

            SetFormat, IntegerFast, %format%

        } else if (key = "toDec") {

            format := A_FormatInteger

            SetFormat, IntegerFast, Dec

            out := "" this+0 ""

            SetFormat, IntegerFast, %format%

        } else if (key = "is_str") {

            Format := A_FormatInteger

            SetFormat, IntegerFast, Hex

            out := SubStr(this:=this, 1, 2)="0x"? False:True

            SetFormat, IntegerFast, %Format%

        }

        return, out

    }

}

StringLib_Set(byref this, key, value){

	StringReplace, this, this, %key%, %value%, all

}


Frankie
  • Members
  • 2930 posts
  • Last active: Feb 05 2015 02:49 PM
  • Joined: 02 Nov 2008
Thanks, I'll try it out next time I'm on windows (maybe in a few hours).
aboutscriptappsscripts
Request Video Tutorials Here or View Current Tutorials on YouTube
Any code ⇈ above ⇈ requires AutoHotkey_L to run

Frankie
  • Members
  • 2930 posts
  • Last active: Feb 05 2015 02:49 PM
  • Joined: 02 Nov 2008
Sorry for the very, very late reply. It works great!

#Include <StrLib>
text := "That links it nicely"
Msgbox % text[1,3] . text[8,3]

aboutscriptappsscripts
Request Video Tutorials Here or View Current Tutorials on YouTube
Any code ⇈ above ⇈ requires AutoHotkey_L to run