Clip() - Send and Retrieve Text using the Clipboard

Post your working scripts, libraries and tools for AHK v1.1 and older
elbitjusticiero
Posts: 78
Joined: 06 May 2017, 11:07

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by elbitjusticiero » 16 Mar 2023, 14:37

Hi! Another grateful, longtime user of Clip() here.

I'm now trying to port it to AHK v2 so I can keep enjoying the goodness. But I'm stuck at the part where it uses a label and then retrieves the value of A_ThisLabel, which doesn't exist anymore in v2. SetTimer also requires functions and not labels now.

Do you know how I could adapt that part of the function so that I can make it work in v2?

elbitjusticiero
Posts: 78
Joined: 06 May 2017, 11:07

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by elbitjusticiero » 17 Mar 2023, 11:27

I ended up doing this, which "works", but I'm not sure I haven't introduced bugs:

Code: Select all

Clip(Text := "", Reselect := "", Restore := "") 
{
	Static BackUpClip := "", Stored := False, LastClip := "", Restored := ""
	
	If (Restore) {

		If (A_Clipboard == LastClip)
			A_Clipboard := BackUpClip
		
		BackUpClip := LastClip := Stored := ""
		
		return Clip()
	
	} Else {
		
		If !Stored {
			Stored := True
			BackUpClip := ClipboardAll() ; ClipboardAll must be on its own line
		
		} Else {
			SetTimer ClipRestore, 0
		}
		
		LongCopy := A_TickCount, A_Clipboard := "", LongCopy -= A_TickCount 
		; LongCopy gauges the amount of time it takes to empty the clipboard 
		; which can predict how long the subsequent clipwait will need
		
		If (Text = "") {
			SendInput("^c")
			ClipWait (LongCopy ? 0.6 : 0.2), True
		
		} Else {
			A_Clipboard := LastClip := Text
			ClipWait 10
			SendInput("^v")
		}
		
		SetTimer ClipRestore, -700
		Sleep 20 
		; Short sleep in case Clip() is followed by more keystrokes such as {Enter}
		
		If (Text = "")
			Return LastClip := StrReplace( A_Clipboard, "`r" )	

		Else If (ReSelect = True) or (Reselect and (StrLen(Text) < 3000)) {
			Text := StrReplace(Text, "`r")
			SendInput("{Shift Down}{Left " StrLen(Text) "}{Shift Up}")
		}
	}
	Return
	
	ClipRestore() {
		Clip( , , "RESTORE" )
	}

	Clip:
	Return Clip()
}



Jasonosaj
Posts: 56
Joined: 02 Feb 2022, 15:02
Location: California

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by Jasonosaj » 21 Mar 2023, 10:23

I recently found this and love the idea. In practice, I'm encountering an issue with the function restoring BackupClip after successfully copying the highlighted text. Absolutely nothing special about the use case and the issue will generally crop up after the script has been active for some time. Anyone else had issues with the function not working in v1?

MoltenKeyboards
Posts: 4
Joined: 05 Jun 2023, 10:58

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by MoltenKeyboards » 20 Jun 2023, 00:16

@elbitjusticiero I know you said you got it figured out but when I was trying your code out I ran into some issues with Clip() continuously recalling itself. I think this stems from the call to Clip() after the return in line 12.

I may be way off base, but after doing some msgbox debugging, I found that removing that mention of Clip() in line 12 (Since any output by that point was already returned anyway) and adding an additional (maybe unnecessary)

Code: Select all

SetTimer , 0
did the trick. The code below works for me. I hope others find it useful.

If you want, you could post it to the V2 forums and link here so others can see and contribute if interested.

Code: Select all

#Warn  ; Enable warnings to assist with detecting common errors.
SetWorkingDir(A_ScriptDir)  ; Ensures a consistent starting directory.

Clip(Text := "", Reselect := "", Restore := "") 
{
	Static BackUpClip := "", Stored := False, LastClip := "", Restored := ""
	If (Restore) {
		If (A_Clipboard == LastClip){
			A_Clipboard := BackUpClip
    }
    BackUpClip := LastClip := Stored := ""
		SetTimer , 0
		return
	
	} Else {
      If !Stored {
      Stored := True
      BackUpClip := ClipboardAll() ; ClipboardAll must be on its own line

      } Else {
      SetTimer ClipRestore, 0
      }

      LongCopy := A_TickCount, A_Clipboard := "", LongCopy -= A_TickCount 
      ; LongCopy gauges the amount of time it takes to empty the clipboard 
      ; which can predict how long the subsequent clipwait will need
		
      If (Text = "") {
        SendInput("^c")
        ClipWait (LongCopy ? 0.6 : 0.2), True
      
      } Else {
        A_Clipboard := LastClip := Text
        ClipWait 10
        SendInput("^v")
      }

      SetTimer ClipRestore, -700
      Sleep 20 
      ; Short sleep in case Clip() is followed by more keystrokes such as {Enter}
		
		If (Text = ""){
			Return LastClip := StrReplace( A_Clipboard, "`r" )	

    } Else If (ReSelect = True) or (Reselect and (StrLen(Text) < 3000)) {
      Text := StrReplace(Text, "`r")
			SendInput("{Shift Down}{Left " StrLen(Text) "}{Shift Up}")
		}
	}
	Return
	
	ClipRestore() {
		Clip( , , "RESTORE" )
	}
}

elbitjusticiero
Posts: 78
Joined: 06 May 2017, 11:07

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by elbitjusticiero » 20 Jun 2023, 17:22

Thank you, @MoltenKeyboards! It looks like I had introduced a bug after all. ;-)

elbitjusticiero
Posts: 78
Joined: 06 May 2017, 11:07

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by elbitjusticiero » 20 Jun 2023, 17:23

BTW @berban, if you could look at it and ensure it's all correct, it would be helpful for those who made the jump to v2!

User avatar
berban
Posts: 99
Joined: 14 Apr 2014, 03:20

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by berban » 23 Jun 2023, 17:43

Hi @elbitjusticiero,

Thanks for bringing this to my attention! I put it on the V2 forums here: viewtopic.php?f=83&t=118764

Let me know if you see any issues with it. I altered what you had slightly according to my understanding of the differences with V2!

Berban

User avatar
Chrysalis
Posts: 13
Joined: 09 Feb 2021, 19:04

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by Chrysalis » 25 May 2024, 20:01

@berban
Nice function! Thanks for that.

But why do you wait 700 ms to call the function again to restore clipboard? In my test 10 ms was sufficient but, knowing AHK, I left it on 50 ms. But why 700? On what machine, under what load and with how large pasted text would it be required to wait this much to restore clipboard?

User avatar
berban
Posts: 99
Joined: 14 Apr 2014, 03:20

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by berban » 31 May 2024, 21:17

Chrysalis wrote:
25 May 2024, 20:01
But why do you wait 700 ms to call the function again to restore clipboard? In my test 10 ms was sufficient but, knowing AHK, I left it on 50 ms. But why 700? On what machine, under what load and with how large pasted text would it be required to wait this much to restore clipboard?
I think it was not the absolute required time to ensure the operation worked correctly; rather it was an extra amount of time to give the user time to perform any other work with the clipboard before restoring it. For instance, a common usage (in some of my scripts at least) is to copy selected text, transform the copied text somehow, and then paste it back. Ideally in this situation you’d do backup > copy > paste > restore, not backup > copy > restore > backup > paste > restore. So in principle the extra lag there gives you time to finish working with the clipboard, before restoring it. Another situation this might apply to is if you wanted to spam a bunch of text using ctrl+v, if you did it with under 700ms between pastes it would reduce the number of backups and restores here too.

Because it’s a timer, it doesn’t interrupt future code at all so I figured the delay doesn’t matter. The only issue is if your script ends after the paste, which can be a problem.

Still, in my experience windows does require a decent amount of time to finish a clipboard action before you can safely restore the value. Otherwise sometimes the original value gets pasted instead of the new value. From testing I recall this being in the neighborhood of 50-100ms but that was some years ago and I wouldn’t be surprised if performance has improved a lot since then.

User avatar
Chrysalis
Posts: 13
Joined: 09 Feb 2021, 19:04

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by Chrysalis » 02 Jun 2024, 11:34

OK, I understand now.

So in the process of backup > copy > transform > paste > restore, if paste occurs less than 700 ms away from copy, does the second call to SetTimer reset the previously running one?

User avatar
berban
Posts: 99
Joined: 14 Apr 2014, 03:20

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by berban » 09 Jun 2024, 15:33

Chrysalis wrote:
02 Jun 2024, 11:34
So in the process of backup > copy > transform > paste > restore, if paste occurs less than 700 ms away from copy, does the second call to SetTimer reset the previously running one?
That's correct. It would cancel the restore and set a new timer for 700ms in the future.

User avatar
Chrysalis
Posts: 13
Joined: 09 Feb 2021, 19:04

Re: Clip() - Send and Retrieve Text using the Clipboard

Post by Chrysalis » 09 Jun 2024, 16:23

OK, thanks for clarifying.

Post Reply

Return to “Scripts and Functions (v1)”