AHK: Loop through clipboard history? - autohotkey

Is there a way in AHK (preferrably v1) to loop through Window's clipboard history (the one that pops up upon pressing Windows key + v)? Something like...
Loop, parse, clipboard, `n, `r
{
MsgBox, 4, , File number %A_Index% is %A_LoopField%.`n`nContinue?
IfMsgBox, No, break
}
...but not line by line, but item by item?
Ultimately, I would like to use this to regularly and flexibly access the last couple of (text) clipboard items to fill in login forms, keyword lists etc.

Related

How to make script to paste something in with AutoHotKey

I'm trying to make a script in AutoHotkey where, when I press Numpad 1, it presses the slash button, then pastes in some text, let's say "hello world", and then presses enter, but I can't figure out how. Can someone help?
Welcome to Stack Overflow.
In the future, try to at least show what you tried. All of this should be accomplished pretty easily by e.g. looking at the beginner tutorial combined with a quick Google search.
But well, here it is:
Numpad1::
Clipboard := "/hello word"
SendInput, ^v{Enter}
return
Numpad1:: creates the hotkey label.
Clipboard:= ... puts something into the clipboard.
SendInput sends input.
^v means Ctrl+v.
{Enter} means the enter key (could've possibly appended `n (line feed) into the string as well).
Return stops the hotkey label's code execution (in other words, ends the hotkey's code).
Assuming that you already have some text copied inside your clipboard before pressing the numpad1, the following code will work.
Numpad1::
Send, /^v ; ^ means ctrl key,
Send, {Enter}
return

How do I delete the current line using AutoHotkey?

Using an AutoHotkey script I'd like to set the keyboard command Ctrl+D to delete the current line in any active Windows app.
How?
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del}
Might not work in all edge cases, but passes some very basic testing in Notepad. =~)
HaveSpacesuit's answer works but after using it for a while I realized it deletes the active line and sometimes re-positions the spacing of the line below.
This led me to rethink his solution. Instead of going from the front of the line to the back, I tried going from back to front. This solved the re-positioning issue.
SendInput {End}
SendInput +{Home}
SendInput ^+{Left}
SendInput {Delete}
There is still a small problem though. If the cursor is on an empty line, with more empty lines above, then all empty lines get deleted.
I don't know a key combo to replace ^+{Left} that doesn't have this behavior so I had to write a more comprehensive solution.
^d:: DeleteCurrentLine()
DeleteCurrentLine() {
SendInput {End}
SendInput +{Home}
If get_SelectedText() = "" {
; On an empty line.
SendInput {Delete}
} Else {
SendInput ^+{Left}
SendInput {Delete}
}
}
get_SelectedText() {
; See if selection can be captured without using the clipboard.
WinActive("A")
ControlGetFocus ctrl
ControlGet selectedText, Selected,, %ctrl%
;If not, use the clipboard as a fallback.
If (selectedText = "") {
originalClipboard := ClipboardAll ; Store current clipboard.
Clipboard := ""
SendInput ^c
ClipWait .2
selectedText := ClipBoard
ClipBoard := originalClipboard
}
Return selectedText
}
As far as I can tell this produces no unexpected behaviour.
However, be careful if you're using a clipboard manager as this script uses the clipboard, if necessary, as an intermediary to get the selected text. This will impact clipboard manager history.
In case you run into problems where you need different behaviours for different programs, you can "duplicate" your ^d command for specific programs like this:
SetTitleMatchMode, 2 ; Makes the #IfWinActive name searching flexible
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; Generic response to ^d.
#IfWinActive, Gmail ; Gmail specific response
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; adapt this line for gmail
#IfWinActive ; End of Gmail's specific response to ^d
#IfWinActive, Excel ; Excel specific response.
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; adapt this line for Excel
#IfWinActive ; End of Excel's specific response to ^d
This way your ^d command will work differently in Excel and Gmail.
I have a simple way to solve the repositioning issue. Without using the clipboard.
The repositioning issue is due to the need to handle 2 separate cases.
if there's existing text in a line,
we want to select them all, and delete the text (backspace 1)
and backspace one more time to delete the empty line (backspace 2)
if it's a blank line,
we want to delete the empty line (backspace 1)
To cater for both of above cases, I introduced a dummy character.
This will make sure BOTH cases will act the same way.
So doing backspace 2 times, will result in the same transformation each time.
Simply,
; enable delete line shortcut
^d::
Send {Home}
Send {Shift Down}{End}{Shift Up}
Send d
Send {Backspace 2}
Send {down}
return
Disadvantage with this approach,
the dummy character "d" will appear when you undo. Not a bad tradeoff since I don't undo delete lines very often.

Insert Tab character into Word

I'm trying to create a script, which will insert Tab character into Word.
Quick note: I've also tested it in OpenOffice. So if you haven't Word, you may test it in OpenOffice or, probably, LibreOffice Writer.
If you are familiar with Word, you know that if you press Tab key on a blank line, you get the Word-like indentation, instead of inserting real Tab char.
Here is attempt to fix it:
$Tab::
old := ClipboardAll
Sleep, 1000 ; Just for testing. If I remove this line, the error still
; occurs, but much more randomly.
Clipboard := " " ; Tab character
ClipWait
SendInput, ^v
KeyWait, Tab
Clipboard := old
return
The problem is, that sometimes (when I press Tab quickly), it is inserted an old content of the clipboard, instead of Tab.
I've tried to use ClipWait, KeyWait, Sleep, InstallKeybdHook in different combinations.
Maybe someone knows what's the problem here and how it can be solved?
Sends tab without triggering indent in word
SetTitleMatchMode 2
#IfWinActive Microsoft Word
$tab:: sendinput .{tab}{left}{backspace}{right}
If I'm understanding you correctly, a better solution might be to turn off this feature with Options > Proofing > Autoformat as you type > Set left and first indent with tabs and backspaces (see here)

How to wrap currently selected text in ``

How can write a hotkey (which works in any editor) to wrap currently selected text in ``
e.g double click "text", it becomes selected, then by pressing key for single `` it
is converted to text
Here is mix of pseudo code and actual code. Text within <> is what I'm not sure of
^<COMMAND FOR PRESSING ` KEY>::
KeyWait Control
<STORE CURRENTLY SELECTED TEXT IN MEMORY>
SendInput `<STORED SELECTED TEXT>'
return
Your approach is pretty good already. Try this:
$`::
clp_tmp := ClipboardAll
send ^c
currently_selected := Clipboard
stringReplace, currently_selected, currently_selected, `r,, All
Clipboard := clp_tmp
sendraw ``%A_Space%
sendraw %currently_selected%
sendraw ``%A_Space%
return
$ is needed because otherwise, sendraw `` would re-trigger this hotkey. The built-in variable clipboard / clipboardAll contains windows' clipboard. Also, you don't need any keywaits. ahk manages concurring modifiers from hotkey triggers by itself. I also suggest using sendraw which will not treat # as the win-button, + as Shift and so on.
script inserts new lines between each line if multiple lines are selected
Weird. When using msgBox, %currently_selected% instead of any send command, the line breaks are displayed correctly... there is obviously some strange formatting going on, I fixed it by simply removing all Carriage Returns (CR) (`r) from the string which does not change the selected text at all.
The given solution works for my keyboard which is German. This might be different for other keyboard layouts. For me, the %A_Space% in sendraw ``%A_Space% (at least in the second one) is needed, because if you state sendraw `` (a literal space character in the end), AHK will ignore it. You could also put all three sends in one line like
sendraw `` %currently_selected%``%A_Space%
Another solution might be
sendInput ````{BS}%currently_selected%````{BS}
or just simply
sendRaw `%currently_selected%`
Finally: If you wanted to make everything easier, make use of the #EscapeChar command and change the delimiter from ` to \ or sth. similar.

Selecting the last N characters before caret with AutoHotkey

Is there a way to select last N symbols with autohotkey?
I'm making a function which replicates Sublime Text's duplicate function (Ctrl+Shift+D). I want text to be selected before it is duplicated via SendInput ^C{right}^V
Technically, I could make something like:
selectBefore(n){
Loop, %n% {
SendInput +{Left}
}
}
But that has shown poor performance.
Another method would be to play with Shift+Home. For example, Send +{Home}, then count the number of symbols selected, then Send {Left} and Send +{Home} again, and so on until reaching the length of the duplicated string.
I don't see any better alternatives.
Is there a good, basic way to select N symbols before caret?
From what I read about ST2 (thank you for making me aware) is that ^+d either copies the selected text or if nothing is selected, copies the whole line.
Would this work?
TempCB = %ClipBoard% ; Park clipboard (text) content, Other content (format, images, etc.) will be lost.
ClipBoard = ; Clear clipboard
Send, ^c ; Grab selected text
Sleep, 100 ; Wait 0.1 seconds for clipboard (clipboard will not get filled if nothing is selected)
if (Clipboard = "") ; Nothing selected, thus copy whole line
{
Send, {Home}+{End}^c ; Select line and copy to clipbard
}
MoveBack := StrLen(ClipBoard)
MoveFwd := MoveBack
MoveBack++ ; Move one step back further back due to earlier step {right}
Send, {Right}{Left}^v{Right}{left %Moveback%}+{Right %MoveFwd%} ; Go to end of selected text (in MS notepad this is will jump over the first next char., thus a jump back as well), add a space and paste.
ClipBoard = %TempCB% ; Restore (text part) of previous clipboard content.
Return
I tested this in MS Notepad, other editors might behave differently (especially around jumping towards the end of the selected text).
The script now copies and pastes the selected text and highlights the newly pasted text.