AHK - # (windows) hotkey stay in pressed state at first use - autohotkey

I wrote a simple script wich open the active joomla site administrator page in Firefox:
#a::
Send, !d
GetText(url)
StringGetPos, localHost, url, localhost
startPos := 7
if(localhost)
startPos := 17
StringGetPos, pos, url, /,,startPos
adminURL := SubStr(url,1,pos)
Send ^t%adminURL%/administrator{enter}
return
GetText(ByRef txt) ;copy the selected text to clipboard
{
BlockInput, on
prevClipboard = %clipboard%
clipboard =
Send, ^c
BlockInput, off
ClipWait, 2
txt = %clipboard%
txt:=RegExReplace(txt,"\x20{2,}"," ")
clipboard = %prevClipboard%
}
At first use (after reboot) the script do weird things:
logout
open command line
open Windows Explorer
It looks like the windows key is still in pressed state when I send the input.
After first use the script work properly.
I think something is wrong with the getText function.
I try a lot of modification, but doesn't work.
Can somebody help me?

Let the hotkey label wait until you have released each key:
#a::
KeyWait, LWin ; or RWin, as desired
KeyWait, a ; just to make sure nothing interferes
/*
do stuff!
*/
return
In contrast to #a UP::, this won't let a key press trickle through when releasing A first.

Related

Autohotkey with unicode and KeyWait / Long press

I'd like a hotkey that changes a s to a ลก if s is hold down for a time. The "s" key doesn't work anymore with my version. Any ideas how to fix this?
s::
If (KeyWait,s,T0.3){
If ErrorLevel
Send {U+0161}
}
return
return
I use AHK 1.1.33.10 on a Win10 machine. The script is saved with ANSI coding.
$s:: ; The $ prefix forces the keyboard hook to be used
KeyWait, s, T0.3
If ErrorLevel
{
KeyWait, s ; waits for s to be released
Send {U+0161}
}
else
Send s
return
https://www.autohotkey.com/docs/commands/KeyWait.htm

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

Content awareness of AutoHotKey script

Is there a content awareness feature of AutoHotKey? I need to replace some selected text in my application. Imagine the following CSHTML:
#
{
ViewBag.Title = "Welcome";
}
<p>Welcome to this page</p>
I have created a very simple script, that (once text has been selected):
Clears clipboard
Send CTRL+C
Send #normalize("
Send CTRL+V
Send ")
That means, that if I select Welcome to this page, it will be replaced with #normalize("Welcome to this page"). That part works perfectly fine.
However, if I want to replace "Welcome" with the same, I would have to select the quotation marks, which speeds down this automation script quite a lot, because I can't simply double click on the word and select it. Now I would have to press and hold, then drag the mouse across the screen until it reaches the last ending quotation mark.
Instead, I need my AutoHotKey script to do something like:
Send CTRL + C;
var caret = currentCaretTextPosition; //made up
IF caret+1 IS "
Send Delete
IF caret-1 IS "
Send Backspace
Send #normalize("
Send CTRL+V
Send ")
If that makes sense. Basically transforms "Welcome" into:
""
"
#normalize("
#normalize("Welcome
#normalize("Welcome")
This is very basic content awareness stuff, because it checks the surrounding characters of the caret, then acts upon that.
AutoHotKey script (triggered by CTRL+ALT+SHIFT+X):
^!+x::
clipboard:=""
While clipboard
Sleep 10
While !clipboard
{
Send ^c
Sleep 100
}
Sleep 20
Send #normalize("
Sleep 20
Send ^v
Sleep 20
Send ")
return
This solution will check if there are surrounding quotes and proceed accordingly. It may fail if there is nothing to the right (such as end of file). It does stop if nothing is selected initially. It does not check if what is selected already contains quotes.
^!+x::
clipboard := ""
Send , ^x
ClipWait , 1
If ErrorLevel
Return
sNormalize := clipboard
clipboard := ""
Send , {right}+{left 2}^c
ClipWait , 1
Send , % ( clipboard = """""" ? "{del}" : "{left}{right}" )
clipboard := "#normalize""" . sNormalize . """)"
Send , ^v
Return
I've made a not-so-bulletproof fix, but it unfortunately requires me to use another keybinding, which I'm not a fan of:
^!+z::
clipboard:=""
While clipboard
Sleep 10
While !clipboard
{
Send ^x
Sleep 100
}
Sleep 20
Send {Right}
Sleep 5
Send {BackSpace}
Sleep 5
Send {BackSpace}
Send #normalize("
Sleep 20
Send ^v
Sleep 20
Send ")
return
It does what I wanted above, but it's not very bulletproof.
Off topic but thought I'd mention it
If you have many of such snippets an alternative could be Lintalist, it is developed in AutoHotkey so you can extend it with your own scripts and plugins. The above script could be replaced with the following snippet - here it uses the selected text in your editor but you can use the clipboard as well:
#
{
ViewBag.Title = "[[selected]]";
}
<p>[[selected]]</p>
You can group snippets in Bundles per application and/or language, assign hotkeys and search for them.
You can learn more about Lintalist here https://lintalist.github.io/ - available plugins here https://lintalist.github.io/#InteractiveBundleText

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.

How to not send hotkey text to open editor

I use this hotkey to close the current Window :
:*:xx::
Send, {Alt Down}{Sleep 100}{f4 Down}{Alt Up}{f4 Up}
return ;
How can the script be amended so that the characters xx are not sent to display but are still registered by autohotkeys ? In other words if focus is within open editor do not display the xx characters but still fire the commands associated with the xx keys.
You can't do it with a Hotstring but you would have have to use a Hotkey and check for a double key press. A regular key like x might not be the most useful as it will most likely always get in the way of your regular typing as you want to block the x being sent. An example with Ctrl:
~Ctrl::
KeyWait, Ctrl ; wait for Ctrl to be released
KeyWait, Ctrl, D T0.2 ; and pressed again within 0.2 seconds
if ErrorLevel ; timed-out (only a single press)
MsgBox single
else
MsgBox double
return
The above code comes from here http://www.autohotkey.com/board/topic/23224-resolved-catch-a-double-press-click/#entry150299 and you will also find an example (no 4) on the KeyWait doc http://ahkscript.org/docs/commands/KeyWait.htm