How to implement something like a select-case-esac structure in AutoHotKey - autohotkey

I am not sure how to start this one. I went through the help files of AHK with no result.
I need to establish a construct like this (this is not in either UNIX shell or in AHK scripting language. Just shows the idea I am after)
while true
do
gosub screenscrape
; here, all text on page is on clipboard
; variable "input" is a predefined portion of the clipboard
case $input in
string-1)
gosub subroutione1;;
string-2)
gosub subroutine2;;
...
*)
echo "not found"
sleep 1minute
done
to make the things more complex, the parts noted as string-1, through string-n are also variables, read in from few different files, depending on time of the day or by trigger from an event.
can someone point me to the right direction for this ?

Autohotkey does not have any case statements. What everyone does is to use if and else statements. (I know how it feels. I like case, too)
A few tips for you:
You can't have that $ or a - in your variable name in autohotkey
...but you CAN have an underscore.
You don't need to terminate your lines with a ;.
Here is a translation into autohotkey for you.
gosub screenscrape
; here, all text on page is on clipboard
; variable "input" is a predefined portion of the clipboard
if(string1){ ;if the variable is not blank it will evaluate to `true`
gosub subroutine1
}else if(string2){
gosub subroutine2
}else{
msgbox not found
sleep 60000 ;milliseconds
}
Also, you can use real functions in autohotkey - you don't have to rely on gosubs. If you use gosubs, make sure you place a return at the end of them. You should also read the autohotkey docs concerning the "auto execute" section.

Related

How to manually trigger Autohotkey hotstrings?

In my main Autohotkey script I have several hundred hotstrings like these:
::fe::for example
::f::and
::fi::for instance
::fo::fortunate
::foy::fortunately
::glo::global
::gloy::globally
::ha::have
::hv::however
Fairly often it would be convenient to trigger a hotstring manually (e.g. by pressing ALT-9) rather than pressing and end character. Is there a way to do this? I haven't found anything in my Googling, so maybe there isn't. But it would be useful.
I've read the hotstrings options e.g. :*: but this isn't the same - I want normal hotstring operation, but also the option to manually force them to trigger as needed.
Updated:
So what you are in fact looking for is using ALT+9 as an end character. I'm not sure but you can probably not use key-combinations for that (see hotstring doc). I cannot think of a really clever way of doing that right now. You might try something like
::fe::
Transform, CtrlC, Chr, 3 ; comes from ahk input documentation, I never really understood how this is supposed to work but I guess there is a code for alt 9 as well somehow
input, key, L1 I M ; wait for the next 1 key
if(key==CtrlC)
sendraw forExample
return
Old answer:
You have to outsource the hotstring body:
::fe::gosub forExample
forExample:
send for example
return
, then you can define a hotkey somewhere:
!9::gosub forExample
If you want to be cool, use functions instead of subroutines.
Note:
::fe::something
is just a short form for
::fe::
send something
return
::fe::for example
::f::and
::fi::for instance
::fo::fortunate
::foy::fortunately
::glo::global
::gloy::globally
::ha::have
::hv::however
!8:: trigger_hotstring("fi")
!9:: trigger_hotstring("ha")
trigger_hotstring(hotstring){
Loop, Read, %A_ScriptFullPath%
{
If InStr(A_LoopReadLine, "::"hotstring "::")
{
SendInput, % StrSplit(A_LoopReadLine,"::"hotstring "::").2
break
}
}
}
If you use AutoHotkey v1.1.06+ you can use #InputLevel
::fe::for example
::f::and
; and so on
#InputLevel, 1 ; sending space will trigger hotstrings above this line
!F9::Send {space}
Edit:
I now see you want to omit the end char which needs a bit of extra work
One way would be to duplicate the hotstrings with additional options:
::fe::for example
:*O:fe_::for example ; duplicate the hotstrings like so
::f::and
::fi::for instance
::fo::fortunate
; and so on
#InputLevel, 1
!9::Send _
Another way would be to remove the endchar
::fe::for example
::f::and
::fi::for instance
::fo::fortunate
; and so on
#InputLevel, 1
!9::
Send {space}
Sleep 100 ; give it time to expand the hotstring, experiment with timing
Send {bs} ; now remove trailing space
Return
I generally use TAB as a trigger for all my hotstrings. like
:*:#pm ::mail1#protonmail.com
:*:#G ::mail2#gmail.com
:*:Btw ::By the way,{Left}
Note that the space that you see here is a tab and not a space. you can do this instead of doing Alt+9 to trigger your macro hotstring.
you can even use more than one Tab so you can be sure that you only trigger it when you really intend to.

Autohotkey, putting "D89dl" at the end of a sentence doesn't work as intended

I have a Autohotkey script that puts "D89dl" at the end of a sentence everytime I press Enter, but using it with a AutoCorrect script it doesn't work as it should. Let's say you type "dont", it then would look like this "don't" instead of "don't.". Something is blocking it but I'm not sure what it is, I've been trying for months now.
Here are the scripts:
enter::
send,D89dl{Enter}
Return
#Hotstring EndChars -()[]{}:;'"/\,.?!`n `t
::dont::don't
I would be VERY thankful if anyone of you helps me with this.
Overall, do you know any other way instead of Autohotkey that puts "D89dl" at the end of a sentence?
The easiest solution seems to be to use the :*: mode, which will trigger everytime the misspelled word is typed, without the need for Hotstring EndChars:
:*:dont::don't
Instead of using Enter, I suggest you use a special combination of keys that enter the string D89dl and then press Enter. Use a modifier like ctrl or alt and another key. The reasoning is that the key Enter has very important functionality and should not be changed. Pressing that special combination is appropriate, given the very special function it does.
It's a bit hacky, but it should do the job (given that by "end of sentence" you actually meant pressing "Enter"):
~enter::
Sleep, 100
SendInput, {BS}D89dl{Enter}
Return
#Hotstring EndChars -()[]{}:;'"/\,.?!`n `t
::dont::don't

advance hotstrings in autohotkey

I found this working autohotkey (ahk) code from the website https://jacksautohotkeyblog.wordpress.com/2015/10/22/how-to-turn-autohotkey-hotstring-autocorrect-pop-up-menus-into-a-function-part-5-beginning-hotstrings/ .
::agin::
TextMenu("again,a gin,aging")
Return
::duh::
TextMenu("what,huh,you're joking")
Return
TextMenu(TextOptions)
{
StringSplit, MenuItems, TextOptions , `,
Loop %MenuItems0%
{
Item := MenuItems%A_Index%
Menu, MyMenu, add, %Item%, MenuAction
}
Menu, MyMenu, Show
Menu, MyMenu, DeleteAll ;Moved from MenuAction:
}
MenuAction:
SendInput %A_ThisMenuItem%{Raw}%A_EndChar%
Return
This is a hotstring script with menu. For example when I type agin I get a many with three options (again,a gin,aging) to choose. Now I want to write it something like this:
agin=again,a gin,aging
duh=what,huh,you're joking
qwe=qwe,qww,ere
Because I have a lot of hotstrings.
As time has passed, in the most recent version of AHK it became possible to do!
Use option x to allow expressions in the oneliner.
Either as :x:...:: OR as a group option above all lines: #Hotstring x
:x:agin::TextMenu("again,a gin,aging")
As nice as it would be, unlike AutoHotkey Hotkeys, I don't believe you can put anything other than replacement text on the same line of an AutoHotkey Hotstring. In other words,
::agin::TextMenu("again,a gin,aging")
would not work while,
::agin::
TextMenu("again,a gin,aging")
Return
does. It is a few more characters long, but not overwhelming.

(AHK) Creating variable hotkeys that gets the key names from a 2 char file name of a script

I'm trying to make something for our employees to use so that they dont have to alter the script itself to define hotkeys. This may only work for hotkeys which can be defined by a single character, but that's fine, as there are so many combinations that can be made with them, and they can be very easy to remember. The script would look only at 2 character AHK files (or 6 if you must include the extension) in the working directory. And the variables it would search for could be defined with RegEx so for the first hotkey, it would look like ^. and then second would look like .(?=.) Once a match is found, it would simply launch that matched file. Has something like this been done before? It seems so simple but I can't seem to find anything on it.
Edit: Elliot brought this to my attention: http://autohotkey.com/board/topic/60630-easy-editmanage-hotkeyshotstrings-plugin-ahk-l/
It's a neat script manager, and very useful, but it's not what I'm looking for.
I dont not want an additional interface. I want to be able to change the hotkeys by using the filename.
Based on the answer of Forvin. Added the execution of the corresponding ahk script.
#Persistent
SetTimer, FindNewHotkeys, 2000
FindNewHotkeys:
Loop, %A_ScriptDir%\*
{
RegExMatch(A_LoopFileName, "^(.)(.).ahk$", hk)
If (hk)
{
Hotkey, ~%hk1% & ~%hk2%, HotkeyLabel
}
}
Return
HotkeyLabel:
RegExMatch(A_ThisHotkey, "~(.) & ~(.)", hk)
run, %hk1%%hk2%.ahk
Return
#Persistent
SetTimer, FindNewHotkeys, 2000
FindNewHotkeys:
Loop, %A_ScriptDir%\*
{
RegExMatch(A_LoopFileName, "^(.)(.).ahk$", hk)
If (hk)
Hotkey, ~%hk1% & ~%hk2%, HotkeyLabel
}
Return
HotkeyLabel:
MsgBox, A hotkey has been pressed!
Return

Autohotkey Input Times Out Because MatchList Isn't Matched

Here's my AHK script
:*:if ::
SendInput IF{Space}
Input cond, I V T5,, then
msgbox %ErrorLevel%
msgbox %cond%
if (ErrorLevel = "Match")
{
SendInput {Enter}End If{Space}'%cond%
}
Return
When I type If x = 1 then I get an ErrorLevel of 'Timeout' and a cond of 'x = 1 then'
My understanding is that when I type then it's supposed to stop the Input and set the ErrorLevel to Match.
I've tried putting it in quotes, using single letters in the MatchList, and including and end key, but none of works. The few examples I could find of using MathList look just like mine.
Input cond, I V T5 *,,% " then"
Without the asterisk option, an item in MatchList needs to be the next thing typed. So If Then would match then in the MatchList. But If anything then doesn't match then in the MatchList because it's trying to match anything then, not just then.
With the asterisk option, if anything then is matched because the next thing typed after If contained then. That causes problems if you type if heathen then because the then in heathen triggers it. The space before then should fix that, but it doesn't.
AHK help says that the MatchList respects spaces, but it doesn't seem to do that when the space is before the first (or only) item in MatchList. The two ways around that are to include a dummy word at the beginning or to use the % thingy to quote the MathList item and include the space.
See also http://ahkscript.org/boards/viewtopic.php?f=5&t=3979
I strongly recommend using RegEx powered hotstrings for this purpose:
#Include <Hotstrings>
hotstrings("if (.*?) then", "If %$1% then``nEnd If%A_SPACE%")
The definition of "T" in the AutoHotkey Help File states this:
T: Timeout (e.g. T3). The number of seconds to wait before terminating the
Input and setting ErrorLevel to the word Timeout. If the Input times out,
OutputVar will be set to whatever text the user had time to enter.
Basically, this is saying exactly what is to be expected (and what is actually happening) with your script. So, for me when I type "if x = 1 then" my "if" is immediately replaced with the caps lock IF and a space.
After 5 seconds, the first MsgBox appears with "Timeout" as the text (again, expected since ErrorLevel is set to the word "Timeout" when the "T" option is present). Once that MsgBox is dismissed, I receive the second MsgBox which (according to the help file) contains OutputVar which is what I (the user) had time to enter in before the Timeout.