Clip() - Send and Retrieve Text using the Clipboard

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

Clip() - Send and Retrieve Text using the Clipboard

18 Feb 2019, 21:38

Clip() - Send and Retrieve Text using the Clipboard

V2 VERSION OF THIS FUNCTION HERE

This is an update to an old post in order to bring it to the new live version of the forums. The old post is here: https://autohotkey.com/board/topic/70404-clip-send-and-retrieve-text-using-the-clipboard/



Using the windows clipboard with AutoHotkey is useful, but it can be confusing and annoying. You'll probably want to backup and restore the contents so that the previous data isn't erased. Usually it also requires a few sleeps to work correctly. This script helps to standardize some of those uses in a small package.

This script includes two of the most common uses of the clipboard: finding out what text is currently being selected, and sending large amounts of text via control-v. It also standardizes some features often needed with these operations, and improves performance through consolidation.


Download code from Github: https://github.com/berban/Clip/blob/master/Clip.ahk



Clip(Text="", ReSelect=False)


Usage: Call it without any parameters to retrieve the text currently selected.

Code: Select all

Var := Clip() ; will store any selected text in %Var%
Or call it with some text in the first parameter to "send" that text via the clipboard and Control+V.

Code: Select all

; The two are analogous. Use of the clipboard is generally preferable for larger amounts of text
Clip("Some text")
SendInput {Raw}Some text ; {Raw} avoids sending keyboard combinations like ^v as ctrl+v
Parameters:
  • Text: If you put text in this parameter, the function will send the text via the clipboard. If you leave this parameter blank, the function will return the selected text instead.
  • ReSelect: (Optional parameter) Only use this parameter in send mode (i.e. if there is text in the first parameter.) If ReSelect is true (has a value of 1), the cursor will re-select the just-pasted text. This is convenient if you are going to make extra modifications to the text, for instance, if you want to bold it after you paste it. If ReSelect is empty or false (equal to 0), then it will not reselect the text. If ReSelect is any other value (such as 2 or a non-numeric string), it will only reselect the text if there are 3000 or fewer characters - more than this number may be lead to choppy re-selecting.
Why use Clip()?
  • Has the right amount of sleep based on many years of experience to work reliably. (Because of trickiness using the windows clipboard, it still might fail to copy or paste every once in a while.)
  • Can send and retrieve with one function
  • No delay while sending. Normally you have to wait 400ms or so after sending Control+V before restoring the clipboard's contents, or else sometimes it pastes the backup contents instead. Clip() tasks this to a timer so your script can continue executing.
  • Improves performance by only saving & restoring the clipboard's contents once in the case of rapid clipboard operations.
  • Can reselct pasted text.
Some working examples:

Simple examples:

Code: Select all

; Displays the selected text
MsgBox, % "The selected text is: " Clip()

; Sends "long text string" using ctrl-v
Clip("long text string")

; Sends "long text string" and then re-selects it
Clip("long text string", True)

; Puts quotes around the selected text.
; Despite calling Clip() twice, the clipboard is only backed up & restored once
Clip("""" Clip() """")
More involved examples: (from 2011, use at your own risk!)

Code: Select all

; The below hotkeys add some of the features of SciTE to notepad.

#IfWinActive ahk_class Notepad ; makes the hotkeys context-sensitive

; Duplicate the above line
^d::
	SendInput {End}+{Home}
	@ := Clip()
	SendInput {End}{Enter}
	Clip(@)
	Return

; Swap with the above line
^t::
	SendInput {End}+{Home}
	@ := Clip()
	SendInput {Del 2}{Up}{Enter}{Up}
	Clip(@)
	Return

; Indent a block of text. (This introduces a small delay for typing a normal tab; to avoid this you can use ^Tab / ^+Tab as a hotkey instead.)
$Tab::
$+Tab::
	TabChar := A_Tab ; this could be something else, say, 4 spaces
	NewLine := "`r`n"
	If ("" <> Text := Clip()) {
		@ := ""
		Loop, Parse, Text, `n, `r
			@ .= NewLine (InStr(A_ThisHotkey, "+") ? SubStr(A_LoopField, (InStr(A_LoopField, TabChar) = 1) * StrLen(TabChar) + 1) : TabChar A_LoopField)
		Clip(SubStr(@, StrLen(NewLine) + 1), 2)
	} Else
		Send % (InStr(A_ThisHotkey, "+") ? "+" : "") "{Tab}"
	Return

#IfWinActive
Notes:
  • With any large amount of text (more than 20 or so characters), it is usually much faster to send it via the clipboard, as opposed to with Send or SendInput.
  • Clip() waits only .15 seconds before its ClipWait times out and reports that no text is selected. I have done some testing and decided that this is an ample amount. However, on a slow machine it is possible you might have to increase this timeout.
  • The delayed restoration of the clipboard that occurs with Clip() can have unintended consequences. For instance, if you send some text with Clip() and then immediately exit the script, the clipboard will never be restored to its original state because the timer to restore it did not expire.
  • You cannot have another "Clip" label in your script. If this is problematic, you can easily enough change the name of the label.
Last edited by berban on 30 Jun 2023, 18:41, edited 3 times in total.
TAC109
Posts: 1098
Joined: 02 Oct 2013, 19:41
Location: New Zealand

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

18 Feb 2019, 22:13

Interesting..
BTW, the link to the old post at the beginning doesn’t seem to work.
My scripts:-
XRef - Produces Cross Reference lists for scripts
ReClip - A Text Reformatting and Clip Management utility
ScriptGuard - Protects Compiled Scripts from Decompilation
I also maintain Ahk2Exe
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

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

18 Feb 2019, 23:31

TAC109 wrote:
18 Feb 2019, 22:13
BTW, the link to the old post at the beginning doesn’t seem to work.
Thanks for catching that! Updated.
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

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

19 Feb 2019, 12:16

@berban, thanks very much. All examples are working fine on Win7 64-bit, AHK_L 1.1.30.01 64-bit.
Regards,
burque505
0x00
Posts: 89
Joined: 22 Jan 2019, 13:12

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

23 Feb 2019, 00:36

Neat, i personally use these though, a bit more intuitive dare i say... Get(), Put(), to take care of most use cases & to get Selected or All Text Left/Right of caret...

Code: Select all

MsgBox % Get()
MsgBox % Get("L")
MsgBox % Get("R")
MsgBox % Get("L") "`n`n" Get("R",false)
Put("Hello World")


Put(string){		;as an alternative to send,to instantly place a string
	ClipSaved := ClipboardAll, clipboard := "", clipboard := string
	clipwait
	BlockInput, on
	Send ^v
	BlockInput, off
	Clipboard := ClipSaved
}


Get(whichSideOfCaret:="",deselect:=true){		;gets everything to left or right of cursor	---> set param to 'L' or 'R', blank param gets selection...
	ClipSaved := ClipboardAll, clipboard := ""
	BlockInput, on
	( whichSideOfCaret = "R" ? Send("{Shift down}{end}{Shift up}{Ctrl down}{c}{Ctrl up}") & (deselect?Send("{Left}")) : (whichSideOfCaret = "L" ? Send("{Shift down}{home}{Shift up}{Ctrl down}{c}{Ctrl up}") & (deselect?Send("{Right}"):"") : (!whichSideOfCaret ? Send("{Ctrl down}{c}{Ctrl up}") : "")) )
	BlockInput, off
	clipwait, 1
	string := clipboard, Clipboard := ClipSaved
	Return string
}


Send(keys){
	Send % keys
}

User avatar
GollyJer
Posts: 61
Joined: 19 Sep 2015, 19:33
Contact:

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

26 Aug 2019, 18:14

Hi. I just wanted to say thank you! 🎉
I've been using Clip for 10 years and it's always been reliable. Love it! 😍
someguyinKC
Posts: 48
Joined: 25 Oct 2018, 11:33

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

01 Oct 2019, 08:36

how can I use this method of scripting but also get the ending character to come through. by ending character, I'm referring to the character that triggers the script, often it is a space, but sometimes it is a period or a quote or a dash, etc.
thank you,

Someguy
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

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

01 Oct 2019, 13:53

someguyinKC wrote:
01 Oct 2019, 08:36
how can I use this method of scripting but also get the ending character to come through. by ending character, I'm referring to the character that triggers the script, often it is a space, but sometimes it is a period or a quote or a dash, etc.
I just noticed that you also asked this question in the other thread where you were asking about your larger issue. It's difficult for people to answer here because your question doesn't mean anything in the context of this thread. They would need to know that what you are calling a script is really a hotstring definition within a script. And they would need to know how you're using this function in conjunction with your hotstrings.

To answer your question, you would accomplish that like this:

Code: Select all

:X:a::Clip("aaaaaaaaaaaaaaaaaaaaa" . A_EndChar)
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

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

01 Oct 2019, 14:04

Thanks, boiler, that's a good tip.
Regards,
burque505
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

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

02 Oct 2019, 09:55

Hey someguyinKC,

Sorry I didn't get a notification for some reason. But boiler is correct, that is how you would do it. (In fact I didn't know about the "X" option for hotstrings so I am glad they posted!)

Let me know if you have any further questions.
someguyinKC
Posts: 48
Joined: 25 Oct 2018, 11:33

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

03 Oct 2019, 11:38

boiler:

in your example:

Code: Select all

:X:a::Clip("aaaaaaaaaaaaaaaaaaaaa" . A_EndChar)
what is that X for?

thanks,

someguy
thank you,

Someguy
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

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

03 Oct 2019, 12:07

It specifies the Hotstring option to execute the text that follows as a command rather than send it as literal text.
aellie
Posts: 1
Joined: 02 Mar 2020, 04:27

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

02 Mar 2020, 04:33

This script cured my acne.

In all seriousness—and for future Googlers, if any—I've been using hotstrings to send emoji, and it works in almost every program, but not in Scrivener for some reason. Honestly at this point I barely care why. The important thing is, using this script to send them fixed the problem, and I'm happy about it.

Thank you so much.
iPhilip
Posts: 801
Joined: 02 Oct 2013, 12:21

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

12 Mar 2021, 23:33

Hi @berban,

Thank you for your Clip() function. I wanted to share a hotkey/function combination that makes it easy for me to switch between Upper, Lower or Title formats for a selected string. It uses your ReSelect parameter. :)

Code: Select all

F3::Clip(Format("{:" GetNextCaseFormat() "}", Clip()), true)

GetNextCaseFormat() {
   static i := 0, Formats := ["U", "L", "T"]
   return Formats[++i > 3 ? i := 1 : i]
}
Cheers!
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

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

13 Mar 2021, 04:26

@iPhilip
I can't make it work.
Can you give me a more detailed example please?
iPhilip
Posts: 801
Joined: 02 Oct 2013, 12:21

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

13 Mar 2021, 11:53

ozzii wrote:
13 Mar 2021, 04:26
@iPhilip
I can't make it work.
Can you give me a more detailed example please?
@ozzii,
Thank you for reaching out for help. The first thing I want to make sure that you did was to include the Clip() function. If you have it saved in a file named Clip.ahk in the same folder as the example code I posted you can simply use the #Include directive as follows:

Code: Select all

#Include Clip.ahk

F3::Clip(Format("{:" GetNextCaseFormat() "}", Clip()), true)

GetNextCaseFormat() {
   static i := 0, Formats := ["U", "L", "T"]
   return Formats[++i > 3 ? i := 1 : i]
}
Otherwise, below is a fully-self contained version that you can download and run:

Code: Select all

F3::Clip(Format("{:" GetNextCaseFormat() "}", Clip()), true)

GetNextCaseFormat() {
   static i := 0, Formats := ["U", "L", "T"]
   return Formats[++i > 3 ? i := 1 : i]
}

; Clip() - Send and Retrieve Text Using the Clipboard
; by berban - updated February 18, 2019
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=62156
Clip(Text="", Reselect="")
{
	Static BackUpClip, Stored, LastClip
	If (A_ThisLabel = A_ThisFunc) {
		If (Clipboard == LastClip)
			Clipboard := BackUpClip
		BackUpClip := LastClip := Stored := ""
	} Else {
		If !Stored {
			Stored := True
			BackUpClip := ClipboardAll ; ClipboardAll must be on its own line
		} Else
			SetTimer, %A_ThisFunc%, Off
		LongCopy := A_TickCount, 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 {
			Clipboard := LastClip := Text
			ClipWait, 10
			SendInput, ^v
		}
		SetTimer, %A_ThisFunc%, -700
		Sleep 20 ; Short sleep in case Clip() is followed by more keystrokes such as {Enter}
		If (Text = "")
			Return LastClip := Clipboard
		Else If ReSelect and ((ReSelect = True) or (StrLen(Text) < 3000))
			SendInput, % "{Shift Down}{Left " StrLen(StrReplace(Text, "`r")) "}{Shift Up}"
	}
	Return
	Clip:
	Return Clip()
}
After you run the script, you should be able to select one or more words, press the F3 key repeatedly, and see the word change from Upper to Lower to Title formats. For example, if you selected the word AutoHotkey, it would sequentially change to AUTOHOTKEY, autohotkey, Autohotkey, AUTOHOTKEY, etc.

Please let me know how this works out for you.

- iPhilip
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

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

14 Mar 2021, 10:48

Thank you @iPhilip
I don't know why the first time it didn't work.
Thank you again, this can be useful.
chaoscreater
Posts: 59
Joined: 12 Sep 2019, 21:15

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

31 Aug 2021, 19:30

How can I get rid of the copied text in the clipboard history? I just want to use this to paste the text into the field, but not actually retain any text in the clip history.
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

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

09 Sep 2021, 20:30

I’m not aware of any way to easily do that with autohotkey, not with the default commands at least. You might have to dive into dllcalls to either use an alternate copy/paste or to change the clipboard history. Sorry about that!
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

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

08 Nov 2021, 01:28

berban wrote:
18 Feb 2019, 21:38
Download code from Github: https://github.com/berban/Clip/blob/master/Clip.ahk
how does this ternary work?

ClipWait, LongCopy ? 0.6 : 0.2, True

isnt LongCopy always going to be non-zero and therefore the timeout will always be 0.6 ?


another question:

why do you set a timer to re-call the func in order to restore the old clipboard, instead of just restoring it yourself in the same func call?


Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: gwarble and 115 guests