3
votes

I have the below simple code, which sends keystrokes for text in the clipboard with a 15ms delay in between characters (I use this to traverse huge lists of treeview elements).

Issue: If I have copied 'text1' to clipboard, followed by 'text2', this script outputs 'text1text2' instead of 'text2' alone.

If I reload the script, then it prints 'text2'.

Is there a mistake in the below code, or is it a bug in implementing %clipboard% in Autohotkey 1.1.14.03 ?

#v::
textToType=" "
textToType=%clipboard%
LoopCount:=StrLen(textToType)
;StringLen, LoopCount, textToType
Array%LoopCount%:=textToType
loop %LoopCount%
{
theChar:=Array%A_Index%
Send %theChar%
sleep 15
}
return

Update: Thanks for pointing out smarter ways of doing this, but I would still like to figure out what is wrong in the above piece of code.

Update 2: The mistake was in my understanding of the AHK syntax. Array%LoopCount%:=textToType assigns the whole string value in textToType to the (LoopCount)th STRING element of the STRING array named 'Array'.

Update 3: (Thanks @John Y for clarifying)

Actually, there's no "declared" array at all, in a traditional sense. You just have a bunch of individual variables, dynamically created as needed, that happen to have names with numbers at the end. Array1 and Array2 are not elements in some Array object. They are just two completely independent variables. AutoHotkey provides a way to glue numbers onto the ends of names, so you can use them like an array.

3

3 Answers

3
votes

The reason your script doesn't work properly is because you're using a pseudo-array to store different words from your clipboard.

I've commented up your code to explain what it does:

#v::
    textToType  := "" ; Empty variable
    textToType  := Clipboard ; Move clipboard into variable

    ; Get lenght of the word
    ; Used as array index / loop count
    LoopCount := StrLen(textToType)

    ; Put the clipboard in an array at index 'LoopCount'
    Array%LoopCount% := textToType

    ; Loop through the array as many times
    ; as the string is long
    Loop % LoopCount
    {
        ; Retrieve the word at this index in the array
        theChar := Array%A_Index%
        ; Send the whole word
        Send, % theChar
        sleep 15
    }
return

Instead of sending each character at a time, you're sending whole words from specific indexes in your Array array.

Say you copy the word Dragon, that word is 6 letters long. So you'd put that in Array6, then you'd loop through your array 6 times using the same variable. At which point the loop would take each index at a time and move it into theChar. On your 6th lap in the loop you'd put Array6 into theChar and print the whole word at once.

Then you copy the word Stackoverflow. That's going to go into Array13, and we're going to loop 13 times. On the 6th lap we're going to print out Dragon which is in Array6, and then keep going until we reach 13 where we'll print Stackoverflow since that is in Array13.

So that's why your script isn't doing what you want it to. Hopefully this helps a little.

See the code sample alpha bravo posted, that's the correct way of achieving what you want to do.

3
votes

keep it simple

#v::
loop Parse, Clipboard
{
    Send %A_LoopField%
    sleep 15
}
return
0
votes

There must be a bug in implementation of clipboard assignment in AHK. With the below code, the behaviour of AHK is that everytime the value of dir is accessed, AHK fetches the latest value from clipboard, instead of fetching the value of dir at the time the script was activated.

; Remove all CR+LF's from the clipboard contents:
dir = %clipboard%
sleep 100
dir := StrReplace(dir, "`r`n")

EDIT: To fix this, I added 1 second sleep before clipboard assignment code:

sleep 1000
; Remove all CR+LF's from the clipboard contents:
dir = %clipboard%
dir := StrReplace(dir, "`r`n")

100 millisecond sleep didn't seem to work.

Accessing value of dir now only gives value of last clipboard assignment at activation.