Selecting the last N characters before caret with AutoHotkey - 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.

Related

AutoHotKey String substitution

I am writing a small AHK script that defines a few simple HotStrings.
The concept is that when I type "Build QA1", the appropriate text associated with that HotString appears.
No problem there ...quite simple ...the issue is that I wish to have the string associated with the HotString appear as part of the substitute text ...in the example below, the results should be
Build QA1
Now is the time for all good men
The script below accomplishes this and works fine ...it does exactly what I ask, HOWEVER, when I enter the HotString text and hit Enter or Tab or whatever initiates the HotString, that first line of text ( Build QA1 ) will "flash" on the screen as it is being substituted ...it makes it obvious that a HotString substitution is in operation ...
I would ideally like the HotString ( Build QA1 ) to remain as a part of the
substitute text without being replaced ...is this possible or is there a way to avoid the "flash" as that string is substituted ?
::Build QA1::
send, Build QA1
send, {enter}
send, Now is the time for all good men
return
Try it this way:
::b0::Build QA1:: ; automatic backspacing is not done to erase the abbreviation you type.
ClipSaved := ClipboardAll ; save the entire clipboard to the variable ClipSaved
clipboard := "" ; empty the clipboard (start off empty to allow ClipWait to detect when the new text has arrived
clipboard = ; copy this text:
(
Now is the time for all good men
)
ClipWait, 1 ; wait for the clipboard to contain data.
if (!ErrorLevel) ; if NOT ErrorLevel ClipWait found data on the clipboard
Send ^v ; paste the text
Sleep, 300 ; don't change clipboard while pasting! (Sleep > 0)
clipboard := ClipSaved ; restore original clipboard
VarSetCapacity(ClipSaved, 0) ; free the memory of the variable ClipSaved
return
See Hotstrings Options, Clipboard and ClipboardAll in the documentation.

Automatic translation

im really new to all this and i was trying to make an Autohotkey for translation. i was digging for some time looking for examples that only confused me more, even if the code looked simple, i didn't understand half of it.
So, what I'm trying to do is: select a paragraph and replace it automatically with its translation.
i was hooping it to be somenthing as simple as CTRJ + C, Translate, CTRL + V, but i can't find the command to go to google translate or somenthing similar, it's not on the autohotkey help file so i'm guessing i don't have libraries?
I'm at my wits end, please help.
You came to the right place. Check out AutoHotKey for sure.
First, how to do it by hand? Those are the steps for ahk. So, lets say you have a paragraph of text selected. You will hit the ahk shortcut and that shortcut will:
first ahk figures out what window its in (using WinGetActiveTitle) and then sends the keystrokes Ctrl+c to copy the selection ("send, ^c" and "Clipwait"), then
ahk can access the clipboard containing the text, do a string manipulation or regex to replace all spaces with the html escape sequence %20 (eg, transtext := StrReplace(Clipboard, " ", "%20")) and
construct a URL to do the Google Translate, something like (where sl is source language and tl is translation language, and text is what you want translated): transurl := "https://translate.google.com/#view=home&op=translate&sl=en&tl=es&text=" . transtext
AHK runs that url and opens a browser window showing result (run % transurl).
This part sucks. Now, you need to use a mouse click at a location (or maybe you can find a controlsend or a combination of keystrokes moving the cursor with tabs and such) to land on the "Copy translation" button. Or how bout you do it manually (try sleep, 8000 to wait while you hit the button)
then have ahk close the window (optionally, or you just do it by hand during the sleep time) and
ahk switches back to the application with the original selected paragraph (WinActivate or do it yourself) and
send ctrl+v to paste the translated text over the original (send ^v).
A starter pack of AHK code (edited per user comments):
WinGetActiveTitle, activewin
Clipboard =
SendInput, ^c
ClipWait
transtext := StrReplace(Clipboard, " ", "%20")
transurl := "https://translate.google.com/#view=home&op=translate&sl=en&tl=es&text=" . transtext
Run, % transurl
Sleep, 6000 ; adjust to taste.
SendEvent, {tab 10} ; adjust to taste.
Sleep 1000
SendInput, {enter}
Sleep, 1000
SendInput, ^{F4}
WinActivate, activewin
sleep, 1000
SendInput, ^v
Try it and let us know how else to help.
OKOK, first of all, thank you all, the script works just fine now. I'm able to copy, translate and paste any text now. Only a few questions lingering.
1) i'm not sure i get what the step number 5 is suppose to do. whatever it is, it works so i don't touch it.
2) is there a way to reset google.translate so it dosent open a new window every time? that could save a lot of time.
3) this one doesn't have a chance, but i ask anyway. Is there a way to not open google chrome at all? because i know that u can translate from excel automatically. (i know that if it is possible will be super hard)
This is the code i ended with:
^a::
clipboard := ""
sendinput, ^c
ClipWait [,,Waitforanydata]
transtext := StrReplace(Clipboard, " ", "%20")
transurl := "https://translate.google.com/#view=home&op=translate&sl=en&tl=es&text=" .
transtext
run % transurl
Sleep, 4000
SendEvent, {tab 9}
SendEvent, {enter}
Winactivate, NAME.pdf - PROGRAM
sendinput, ^v

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)

can somebody help to write a autohotkey script for select all the pasted content after paste?

the autohotkey script should do follows:
after I tap the hotkey,
it will paste the content from the clipboard, then immediately select all the pasted content?
I write a script as follows:
^+p::
clipvar:=Clipboard
num:=strlen(clipvar)
send ^v
send +{left %num%}
return
This script works.
But the selecting process is too slow!!!
Can somebody write a better script?
SendMode, Input optionally combined with SetBatchLines, -1 and variations of SetKeyDelay can accelerate key sequences.
However, the selection of large texts will still take some time, and slow machines may slow it down even further.
Here's another approach which - in terms of sending keystrokes - is more efficient:
^+p::
oldCaretX := A_CaretX
oldCaretY := A_CaretY
Send, ^v
WaitForCaretChange()
MouseGetPos, mX, mY
MouseClickDrag, Left, %A_CaretX%, %A_CaretY%, %oldCaretX%, %oldCaretY%
MouseMove, %mX%, %mY%
return
WaitForCaretChange() {
oldCaretX := A_CaretX
oldCaretY := A_CaretY
while(A_CaretX = oldCaretX && A_CaretY = oldCaretY) {
Sleep, 15
}
}
This code relies on the window to expose the caret position, which unfortunately, not every window does. It remembers the caret position before the paste and selects text up to the old position after pasting new text; this should be equal to selecting all the newly inserted text. If you're only working with editors that expose their caret position, I recommend you go with this one since it's faster. Otherwise, you can still think about using both your method and this one, depending on the window and/or the text length.