optimize code converted from v1.1 Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
marypoppins_1
Posts: 123
Joined: 28 Oct 2020, 02:58

optimize code converted from v1.1

05 May 2024, 01:55

hello. i had a working v1.1 code that capitalizes selected text (or all text if none is selected). i converted it to v2.0 using joe glines' converter and it works. i just want to ask if there is a way to optimize the current code or if it is fine? thanks in advance.

Code: Select all

^NumpadAdd:: { ; Hotkey to make selected text uppercase
    OldClipboardBackup := ClipboardAll() ; Save the entire clipboard to a variable (OldClipboardBackup).
    A_Clipboard := "" ; Empties the Clipboard.
    Send("^c") ; Sends Control + C (Copy) to copy text. (This is to check if text is currently selected)
    Errorlevel := !ClipWait(0.1) ; Waits 0.1 second and then checks the status of the clipboard
    If(A_Clipboard = ""){ ; If Clipboard is empty => no text was previously selected
        Send("^a") ; Will send control + a to select everything in the active window
        Sleep(10) ; Waits for 10ms to make sure text has been selected
        Send("^c") ; Copies selected text.
        Errorlevel := !ClipWait(0.1) ; Will wait 0.1 seconds and then check the status of the clipboard. It should now contain text since text was previously copied and will proceed to the next if statement.
    }
    If(A_Clipboard != ""){ ; If Clipboard is not empty, proceed
        A_Clipboard := StrUpper(A_Clipboard) ; Turns all letters into uppercase form in the clipboard
        Send("^v") ; Will send the text in clipboard with all uppercase (Replaces old case by uppercase)
        Sleep(1000) ; Added the sleep incase the processing would outrun the script without first sending the manipulated data string
    }
    A_Clipboard := OldClipboardBackup ; Restore the original clipboard. Note the use of Clipboard (not ClipboardAll).
    OldClipboardBackup := "" ; Free the memory in case the clipboard was very large. (Our variable "OldClipboardBackup" becomes empty)
}
User avatar
Noitalommi_2
Posts: 265
Joined: 16 Aug 2023, 10:58

Re: optimize code converted from v1.1

05 May 2024, 06:14

Hi.

I think your script is fine as it is, exept that the Errorlevel variable serves no purpose and the script could be shorten a little bit but that's just personal taste.

Code: Select all

^NumpadAdd:: {

	B := ClipboardAll(), A_Clipboard := ""
	if !(Send("^c"), ClipWait(0.1))
		Send("^a^c"), ClipWait()
	A_Clipboard := StrUpper(A_Clipboard)
	Send("^v"), KeyWait("Ctrl", "L")
	A_Clipboard := B, B := ""
}
marypoppins_1
Posts: 123
Joined: 28 Oct 2020, 02:58

Re: optimize code converted from v1.1

05 May 2024, 10:14

i never fully understood what errorlevel was in 1.1 but what do you mean its not needed in v2.0??
also can you please just explain to me these lines? i don't understand what they mean. is the comma considered "and" in this context??

Code: Select all

if !(Send("^c"), ClipWait(0.1))
		Send("^a^c"), ClipWait()
User avatar
Seven0528
Posts: 392
Joined: 23 Jan 2023, 04:52
Location: South Korea
Contact:

Re: optimize code converted from v1.1

05 May 2024, 11:24

 @marypoppins_1
When multiple expressions are enclosed in parentheses with commas, they are executed sequentially,
but only the result of the last expression is considered as the overall return value.
However, please note that there are slight differences in the comma syntax between v1.1 and v2.0.
In v1.1, the first result value was considered as the overall return value.

Code: Select all

a := send("^c")
b := clipWait(0.1)
if (!b)    {
    
}

Code: Select all

if (send("^c"), !clipWait(0.1))    {
    
}
 Comma
v2.0 wrote: For a multi-statement expression, the result of the last statement is returned. For example, (a := 1, b := 2, c := 3) returns 3.

Comma is also used to delimit the parameters of a function call or control flow statement. To include a multi-statement expression in a parameter list, enclose it in an extra set of parentheses. For example, MyFn((x, y)) evaluates both x and y but passes y as the first and only parameter of MyFn.
v1.1 wrote: For a multi-statement expression, the result of the first statement is returned. For example, (a := 1, b := 2, c := 3) returns 1.
  • English is not my native language. Please forgive any awkward expressions.
  • 영어는 제 모국어가 아닙니다. 어색한 표현이 있어도 양해해 주세요.
marypoppins_1
Posts: 123
Joined: 28 Oct 2020, 02:58

Re: optimize code converted from v1.1

05 May 2024, 11:44

okay thank you, can i bother you with checking out my other hotkey that switches the cases of letters (using regex) if it can be optimized?
thanks in advance

Code: Select all

^NumpadMult:: { ; Hotkey to make selected text have alternated cases
    AlternatingCaseStartingNumber := "0"
    OldClipboardBackup := ClipboardAll() 
    A_Clipboard := "" ; Empties the Clipboard.
    Send("^c") ; Sends Control + C (Copy) to copy text. (This is to check if text is currently selected)
    Errorlevel := !ClipWait(0.1) ; Waits 0.1 second and then checks the status of the clipboard
    If (A_Clipboard = ""){ ; If Clipboard is empty => no text was previously selected
        Send("^a") ; Will send control + a to select everything in the active window
        Sleep(10) ; Waits for 10ms to make sure it's selected
        Send("^c") ; Copies selected text.
        Errorlevel := !ClipWait(0.1) ; Will wait until the text is copied to the clipboard.
    }
    If (A_Clipboard != "") { ; If Clipboard is not empty, proceed
        NewAlteredCaseData := ""
        Loop Parse, A_Clipboard
        {
            LetterCaseVar := A_LoopField
            if RegExMatch(LetterCaseVar, "[a-zA-Z]") { ; only match letters a-z
                AlternatingCaseStartingNumber++
                If Mod(AlternatingCaseStartingNumber,2)
                    LetterCaseVar := StrUpper(LetterCaseVar)
                else
                    LetterCaseVar := StrLower(LetterCaseVar)
            }
            NewAlteredCaseData .= LetterCaseVar ;append the new character to the NewAlteredCaseData string
        }
        A_Clipboard := NewAlteredCaseData ;set the clipboard to be the new data
        Send("^v") ;paste the contents of clipboard
        Sleep(1000)
    }
    A_Clipboard := OldClipboardBackup ; Restore the original clipboard.
    OldClipboardBackup := NewAlteredCaseData := "" ; Free the memory 
}
User avatar
kunkel321
Posts: 1123
Joined: 30 Nov 2015, 21:19

Re: optimize code converted from v1.1

05 May 2024, 11:45

Seven0528 wrote:
05 May 2024, 11:24
...When multiple expressions are enclosed in parentheses with commas, they are executed sequentially, ...
Thank you for the explanation. It's too bad we can't "upvote" or "like" individual replies...
ste(phen|ve) kunkel
User avatar
Noitalommi_2
Posts: 265
Joined: 16 Aug 2023, 10:58

Re: optimize code converted from v1.1

05 May 2024, 11:46

I just wanted to add that ClipWait has a return value (See here), which is either true or false (1 or 0), in which case the exclamation mark indicates that the return value must be false so that the line below is executed. You could also write it like this:

Code: Select all

Send "^c"
ReturnValue := ClipWait(0.1)

if !ReturnValue ; if not ReturnValue (equivivalent to: if ReturnValue = 0)
	Send("^a^c"), ClipWait()

marypoppins_1 wrote:
05 May 2024, 10:14
i never fully understood what errorlevel was in 1.1 but what do you mean its not needed in v2.0??
Errorlevel is an internal variable used in V1 that receives the return value ​​of some commands or is set when an error occurs. In V2 Errorlevel was removed as an internal variable, in your script ErrorLevel is a variable like any other.
See here
You store the return value of ClipWait in it, but otherwise do not use this variable in your script.
marypoppins_1
Posts: 123
Joined: 28 Oct 2020, 02:58

Re: optimize code converted from v1.1

05 May 2024, 11:53

okay thank you noitalommi. with regards to my post about alternating cases, is there something i can do besides fixing the first few lines that contain the errorlevel??

Code: Select all

    OldClipboardBackup := ClipboardAll() 
    A_Clipboard := "" ; Empties the Clipboard.
    Send("^c") ; Sends Control + C (Copy) to copy text. (This is to check if text is currently selected)
    Errorlevel := !ClipWait(0.1) ; Waits 0.1 second and then checks the status of the clipboard
    If (A_Clipboard = ""){ ; If Clipboard is empty => no text was previously selected
        Send("^a") ; Will send control + a to select everything in the active window
        Sleep(10) ; Waits for 10ms to make sure it's selected
        Send("^c") ; Copies selected text.
        Errorlevel := !ClipWait(0.1) ; Will wait until the text is copied to the clipboard.
    }
User avatar
Seven0528
Posts: 392
Joined: 23 Jan 2023, 04:52
Location: South Korea
Contact:

Re: optimize code converted from v1.1

05 May 2024, 12:44

 @kunkel321
Whenever I'm feeling exhausted, small gestures of gratitude like this often become a source of strength for me.
Thank you for expressing your gratitude for my simple response.

 @marypoppins_1
Your code still has room for optimization.
But before optimizing, I'm not quite clear on what exactly you want.
Are you simply looking to invert the case of letters?
  • English is not my native language. Please forgive any awkward expressions.
  • 영어는 제 모국어가 아닙니다. 어색한 표현이 있어도 양해해 주세요.
User avatar
Noitalommi_2
Posts: 265
Joined: 16 Aug 2023, 10:58

Re: optimize code converted from v1.1

05 May 2024, 13:15

Seven0528 wrote:
05 May 2024, 12:44
But before optimizing, I'm not quite clear on what exactly you want.
Alternating between upper and lower case letters. I think so. ^^
marypoppins_1 wrote:
05 May 2024, 11:53
okay thank you noitalommi. with regards to my post about alternating cases, is there something i can do besides fixing the first few lines that contain the errorlevel??
Again, i think your script is fine as it is but could be shorten a little bit.

Code: Select all

^NumpadMult:: {

    B := ClipboardAll(), A_Clipboard := ""
	if !(Send("^c"), ClipWait(0.1))
		Send("^a^c"), ClipWait()
	Loop Parse, A_Clipboard
		(L := A_LoopField) ~= "\pL" ? (Mod(A_Index,2) ? L := StrUpper(L) : L := StrLower(L)) : 0, N .= L
	A_Clipboard := N
	Send("^v"), KeyWait("Ctrl", "L")
    A_Clipboard := B, N := B := ""
}
marypoppins_1
Posts: 123
Joined: 28 Oct 2020, 02:58

Re: optimize code converted from v1.1

05 May 2024, 22:31

thank you it works but i have something @Noitalommi_2 . i don't want to be picky but how it worked before in regex it only detected a-z characters which makes "Hi HeLlO" my output. with your code it capitalizes the space (no effect) so i kind of get "Hi hElLo" if you get what i mean. can this be fixed ??
User avatar
Noitalommi_2
Posts: 265
Joined: 16 Aug 2023, 10:58

Re: optimize code converted from v1.1

06 May 2024, 00:04

@marypoppins_1
I changed it.
The regex needle is also different, "\pL" means any letter. If it bothers you, you could also use the previous needle "[a-zA-Z]".

Code: Select all

^NumpadMult:: {

    B := ClipboardAll(), A_Clipboard := ""
	if !(Send("^c"), ClipWait(0.1))
		Send("^a^c"), ClipWait()
	Count := 0
	Loop Parse, A_Clipboard
		(L := A_LoopField) ~= "\pL" ? (Mod(++Count,2) ? L := StrUpper(L) : L := StrLower(L)) : 0, N .= L
	A_Clipboard := N
	Send("^v"), KeyWait("Ctrl", "L")
    A_Clipboard := B, N := B := ""
}
User avatar
Seven0528
Posts: 392
Joined: 23 Jan 2023, 04:52
Location: South Korea
Contact:

Re: optimize code converted from v1.1

06 May 2024, 02:07

 I've attempted to write it in a different way.

Code: Select all

^NumpadMult::  {
    prevIC := critical("On")
    clipSaved := clipboardAll()
    if (!clipSaved.Size)
        clipSaved := ""
    A_Clipboard := ""
    if (!result := (send("^c"), clipWait(0.1)))
        result := (send("^a"), sleep(10), send("^c"), clipWait(0.1))
    if (result)    {
        /*
        Calling A_Clipboard incurs a cost.
        It is advantageous to minimize its usage.
        Remember that the clipboard is a shared resource accessible by all processes, not just in AHK.
        */
        newString := ""
        currString := A_Clipboard

        /*
        i := 0
        loop Parse, currString    {
            if (A_LoopField ~= "[\p{Ll}\p{Lu}]")    {
                switch (mod(++i,2))
                {
                    case true:      newString .= strUpper(A_LoopField)
                    default:        newString .= strLower(A_LoopField)
                }
                continue
            }
            newString .= A_LoopField
        }
        */
        charList := [], spo := 1
        while (regExMatch(currString,"s).",&m,spo))
            charList.push(m[0]), spo := m.Pos[0]+(m.Len[0]||1)
        i := 0
        for char in charList    {
            newChar := ""
            if (regExMatch(char, "(?:(*MARK:L)\p{Ll}|(*MARK:U)\p{Lu})", &m))    {
                switch (mod(++i,2))
                {
                    case true:
                        if (m.Mark == "L")
                            newChar := regExReplace(char,"\Q" char "\E","$U{0}")
                    default:
                        if (m.Mark == "U")
                            newChar := regExReplace(char,"\Q" char "\E","$L{0}")
                }
            }
            newString .= (newChar!==""?newChar:char)
        }
        A_Clipboard := ""
        A_Clipboard := newString
        if (clipWait(0.1))
            send("^v"), sleep(1000)
    }
    if (clipSaved)    {
        A_Clipboard := clipSaved
        ;  clipSaved := ""
        /*
        clipSaved is an internal variable created within the function.
        Memory is automatically deallocated when the function exits.
        */
    }
    ;  critical(prevIC)
    /*
    In this case, the end of the function signifies the termination of the thread, 
    so there is no need to recover the critical.
    */
}
  • English is not my native language. Please forgive any awkward expressions.
  • 영어는 제 모국어가 아닙니다. 어색한 표현이 있어도 양해해 주세요.
marypoppins_1
Posts: 123
Joined: 28 Oct 2020, 02:58

Re: optimize code converted from v1.1

06 May 2024, 04:55

okay, thank you both. both codes work. one last question. if i want to remove the comma and use two lines, do i also have to add brackets for the if ??
before:

Code: Select all

if !(Send("^c"), ClipWait(0.1))
	Send("^a^c"), ClipWait() 
after: ??

Code: Select all

if !(Send("^c"), ClipWait(0.1)){
	Send("^a^c")
    ClipWait()
}
User avatar
Seven0528
Posts: 392
Joined: 23 Jan 2023, 04:52
Location: South Korea
Contact:

Re: optimize code converted from v1.1  Topic is solved

06 May 2024, 05:54

 Yes!
{...} (block)
Splitting a Long Line into a Series of Shorter Ones
If any of the control flow statements mentioned above has only a single statement, that statement need not be enclosed in a block (this does not work for function definitions). However, there may be cases where doing so enhances the readability or maintainability of the script.
Continuation operator: A line that starts with a comma or any other expression operator (except ++ and --) is automatically merged with the line directly above it. Similarly, a line that ends with an expression operator is automatically merged with the line below it. In the following example, the second line is appended to the first because it begins with a comma:

Code: Select all

if !(Send("^c"), ClipWait(0.1))
	Send("^a^c"), ClipWait()

Code: Select all

if !(Send("^c"), ClipWait(0.1))
	Send("^a^c")
	,ClipWait()

Code: Select all

if !(Send("^c"), ClipWait(0.1))    {
	Send("^a^c")
	ClipWait()
}
  • English is not my native language. Please forgive any awkward expressions.
  • 영어는 제 모국어가 아닙니다. 어색한 표현이 있어도 양해해 주세요.
marypoppins_1
Posts: 123
Joined: 28 Oct 2020, 02:58

Re: optimize code converted from v1.1

06 May 2024, 06:21

thank you and thank you for referencing the documentation it helps a lot!

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: emp00, Felix Siano and 35 guests