Reduce Code and Increase Power with the AutoHotkey Input Command (Part 13, Beginning Hotstrings)

Use the Input Command to Eliminate Code While Creating Multiple Hotstrings. You’re Going to Like This One! It Includes Arrays and Hiding Data in Substrings.

*          *          *

Beginning AutoHotkey Hotstrings 200pxAs a convenience for people who want to get this entire series (plus more) in one place, I have now published the e-book Beginning AutoHotkey Hotstrings which is available on the ComputorEdge E-Books site (in three formats—EPUB for mobile devices, MOBI for Kindle, and PDF for printing and computer) and through Amazon. Regardless of whether you’re interested in the book or not, it’s worth your time to peruse some of the blogs linked at “Beginning AutoHotkey Hotstring Techniques” found under the “AutoHotkey Topics and Series” tab in the top menu bar. They just might inspire your next AutoHotkey script.

*          *          *

New to AutoHotkey? See “Introduction to AutoHotkey: A Review and Guide for Beginners.”

*          *          *

My eyes were opened to the AutoHotkey Input command in my last blog. It offers unique capabilities which can multiply the power of many scripts. I quickly dug up one of my old Hotstring scripts as a good candidate for updating with the Input command. I offer this example to provide insight into how this rarely-used command may work in your scripts. Plus, there’s a bonus discussion of AutoHotkey Associative Arrays for quickly storing various sets of data.

ComputorEdge AutoHotkey E-BooksA while back I wrote a short script for inserting into any editing field the date of a coming day of the week. If I want next Friday’s date, I type dfri1 and the short date is added to any document (e.g. 12-18-15). For the long date I key in dfri2 (e.g. Friday, December 18, 2015). Each day of the week requires a separate Hotstring, but the total amount of code is reduced by a reusable function for calculating the date—then returning it to the document. The script is still relatively long since three lines of code are needed for each day of the week for each date format:

:c*:dsun1::
  Weekday(1,1)
return

:c*:dmon1
  Weekday(2,1)
return

:c*:dtue1:
  Weekday(3,1)
return

:c*:dwed1::
  Weekday(4,1)
return

:c*:dthu1::
  Weekday(5,1)
return

:c*:dfri1::
  Weekday(6,1)
return

:c*:dsat1::
  Weekday(7,1)
return

:c*:dsun2::
  Weekday(1,2)
return

:c*:dmon2::
  Weekday(2,2)
return

:c*:dtue2::
  Weekday(3,2)
return

:c*:dwed2::
  Weekday(4,2)
return

:c*:dthu2::
  Weekday(5,2)
return

:c*:dfri2::
  Weekday(6,2)
return

:c*:dsat2::
  Weekday(7,2)
return

Weekday(Day,Format)
{
   Today := A_Now

   If abs(A_WDay) >= Day
      Today += Day + 7-A_WDay, days
   Else
      Today += Day-A_WDay, day
   If Format = 1
      FormatTime,  Weekday, %Today%,  M-d-yy  
   If Format = 2
      FormatTime,  Weekday, %Today%,  LongDate
   SendInput %Weekday%
}

Each Hotstring simply calls the Weekday(Day,Format) function for a different day of the week and different date format. It’s not as bad as it looks, but since the Hotstring format is unchangeable once the script is loaded, there is little flexibility. That makes 14 distinct Hotstrings— with more required if you want additional date formats. Extending the number of date formats could quickly become tedious…if not unwieldy.

While it works great, this snippet of code is pretty long. Plus, I found that the Hotstrings are not particularly easy to remember without looking them up. It wasn’t until working on the Input command discussion in my last blog that I realized this script was a candidate for Input command simplification. With Input I could eliminate the use of the redundant Hotstring code making the script shorter. Plus, it’s easier to add more date formats to the function, thus decreasing the likelihood of a conflict with other Hotstrings.

Converting the Script for the Input Command

I’ve seen very little discussion on the Web about the Input command. This may be because it’s not easy to understand how or where to use it. Or, maybe, it’s just been overlooked. There is an InputBox command, but that is an entirely different animal. Commonly, if you Google “AutoHotkey input” most of the results refer to the SendInput command. However, Input is an AutoHotkey feature worth knowing. The Input command is a specialized tool which, when used properly, greatly expands your AutoHotkey toolbox.

One major advantage to creating Hotstrings with the Input command is that they are only in effect when activated—usually with a Hotkey combination. That means I can create any number of pseudo Hotstrings by adding them to the Input command’s MatchList parameter. Plus, I no longer need to worry about conflicts with other embedded Hotstrings since the new, temporarily activated key series will not trigger a standard Hotstring. Now, I can use combinations of keys which are even easier to remember.

I use a couple of tricks in this script I consider immediate rather than beginning level techniques. But, even for the novice, they give more insight into what can be done with AutoHotkey. The completed script is as follows:

^!]::
  Input, UserInput, V T10 L3, {enter}.{esc}{tab}
      , su1,mo1,tu1,we1,th1,fr1,sa1
       ,su2,mo2,tu2,we2,th2,fr2,sa2
       ,su3,mo3,tu3,we3,th3,fr3,sa3

  if (ErrorLevel != "Match")  ;entry does not match
  {
    Send, {backspace 3}
    MsgBox, "%UserInput%" is not a valid entry.
    return
  }
  WeekDay := {su: 1, mo: 2, tu: 3, we: 4,th: 5, fr: 6, sa: 7}
  NextDay := WeekDay[Substr(UserInput,1,2)]
  DayFormat := Substr(UserInput,3,1)
  SendInput, {backspace 3}
  WeekDay(Nextday,DayFormat)
Return

Weekday(Day,Format)
{
  Today := A_Now
  If abs(A_WDay) >= Day
    Today += Day + 7-A_WDay, days
  Else
    Today += Day-A_WDay, days
  If Format = 1
    FormatTime, Weekday, %Today%, LongDate
  If Format = 2
    FormatTime, Weekday, %Today%, MMMM d, yyyy 
  If Format = 3
    FormatTime, Weekday, %Today%, M-d-yy 
  SendInput %Weekday%
}

First, the entire snippet is activate with the Hotkey combination CTRL+ALT+] (^!]). Whenever this key combination is pressed simultaneously, the ensuing weekday Hotstrings found in the Input commands MatchList are activated.

The Input command which appears on the second line of the script sets up the temporary Hotstrings. (AutoHotkey line continuation is used to wrap the Input command line for better readability.) Each text entry in the MatchList (as described last time) is a separate temporary Hotstring. If the keyed string of characters matches one of the entries in the MatchList, then the remainder of the routine is executed. Otherwise, the Input command is terminated either by the timeout (T10 for 10 seconds) or a false keyed-in entry (MsgBox, “%UserInput%” is not a valid entry).

If a true value is found in the MatchList, then the script continues past the ErrorLever condition into the remainder of the routine. (This is where it gets interesting.)

AutoHotkey Variable Arrays

One of the problems in any programming language is how to create multiple variables which are similar in nature, yet each has a distinctive value. In most cases, AutoHotkey uses pseudo variable arrays which create separate variable names for each data item in a set of values.

For example, when using the StringSplit command, each parsed value is assigned to a new variable name (e.g. Var1, Var2, Var3, …) which can be recalled by concatenating a number string to the original output variable name (e.g. “Var” . “1” or Var%A_Index%). A true array uses parameters within the array to recall the variable value.

The newer array techniques in AutoHotkey are part of the Object model which is now integrated into the latest version of AutoHotkey. It’s a method for quickly creating and using one variable name to hold numerous values (an array) by calling parameters rather than individual variable names.

Note: While I am borrowing the array techniques from the Object model, Object Oriented Programming (OOP) is another, more advanced topic which deserves more attention. OOP is used regularly by most accomplished programmers and adds flexibility to scripts. However, it requires a  different way of thinking about the process and writing routines. It is not as linear as most traditional forms of programming and takes a little getting used to. Perhaps I will dig deeper into OOP at sometime in the future.

In the example above, the array by the name WeekDay is created with:

  WeekDay := {su: 1, mo: 2, tu: 3, we: 4,th: 5, fr: 6, sa: 7}

The multiple values in this Associative Array are the numeric days of the week. This array associates abbreviations for the days of the week with its respective number values. The array Keys are two-letter abbreviations which appear before the colon in each set. The keys are used to call up the AutoHotkey numeric value of the weekday (as defined for the built-in AutoHotkey variable A_WDay—Sunday is 1). Each Key and Value is separated by a colon with a comma between each Key/Value set. If the key th is called, then the value 5 is returned. The beauty of an Associative Array is that both the Key and Value can be almost anything—even random keys with random values.

The value of the next weekday (NextDay) is assigned by calling the correct key from the array:

NextDay := WeekDay[Substr(UserInput,1,2)]

This line of code offers two learning points. The first is the method for returning a value from the array WeekDay using the two-letter weekday key. For example, the following line:

NextDay := WeekDay["fr"]

assigns the value 6 (the numeric weekday value for Friday) to the variable NextDay.

Second, the entered Hotstring combination is parsed with the Substr() function to return that portion of the text which represents the weekday (Substr(UserInput,1,2)—the first two characters of the Hotstring). Thus, whenever a true value is found in the Input command’s MatchList, the first two characters always result in the array key which coincides with numeric value of the desired day of the week.

Note: There are other methods for doing the same day abbreviation⇒weekday number conversion . One includes assigning the corresponding weekday values to each two-letter weekday abbreviation as individual variables—then using the same Substr() function to parse the Hotstring. But in that case it’s at least a two-step process to extract the value from the parsed substring variable. The Associative Array simplifies the process and shorten the number of lines of code.

Storing Data in a Text Strings

The function WeekDay(Day,Format) requires two parameters. Day is the numeric day of the week and is provided as described above. Format is a numeric value used to pick which date format should be inserted into the document. In this case, the easy way to include the Format in the Input statement is by adding it to the Hotstring as the last character. The numbers 1, 2, and 3 are used in this example, but they could just as easily be letters—especially if they are easier to remember later. Rather than creating more variables or arrays, it’s simpler to use the same Substr() function to directly parse the value off the end of the Hotstring:

DayFormat := Substr(UserInput,3,1)

There are often times when the least complex way to save data is by writing it to a text string and later parsing out the value for use.

The next line of the script is included to delete the entered Hotstring with the SendInput command:

SendInput, {backspace 3}

This line of code removes the typed string if a true value from the MatchList is entered. (The same text deletion line is included in the included ErrorLevel condition for a non-match.)

Finally, the WeekDay(Day,Format) function is called with the parameter values NextDay and DayFormat:

WeekDay(Nextday,DayFormat)

This function calculates the date of the next weekday, then returning it in the desired format.

Note: You may notice that both the array variable and function have the same name, WeekDay: Weekday[] and WeekDay() respectively. They do not conflict since they are not same type of creature. However, to save confusion, you may want to change one of the names to something less likely to cause confusion.

WeekDay() Function Explanation Remains a Mystery

You may be disappointed that I don’t explain how the WeekDay() works here. This Blog represents the last chapter in a new e-book I’m currently putting together about AutoHotkey Hotstrings for beginners. It will include all of the previous parts found here, plus other older, but updated, no longer published articles only available in archives. (For the archived PDF of ComputorEdge which includes an explanation for the included function, get the download here.) An explanation for how the WeekDay() function works will appear in one of those other chapters in the new book.

Take It to the Next Step

While it is fairly easy to remember the two-letter abbreviations for the days of the week, the format number is a little more cryptic. If you have trouble remembering the various date format numbers, then you can integrate the Hotstring menu technique from this blog on Hotstring Menus, then simply use the two-letter weekday combination (su, mo, tu, we, th, fr, sa) to pop up a list of date options. That way you can add as many date formats as you like without needing another seven sets of three-character combination in your Input command MatchList. It’s a little bit of a challenge for a beginner, but I’ll leave that task to you.

*         *          *

Find Jack’s AutoHotkey e-Books at ComputorEdgeBooks.com.

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s