Using Associative Arrays to Solve the Instant Hotkey Data Recall Problem (AutoHotkey Technique)

While Many Other Approaches Work (Sort of), AutoHotkey Associative Arrays Provides a Simple Solution

Elegant Solution

Refinement and simplicity are implied, rather than fussiness, or ostentation. An elegant solution, often referred to in relation to problems in disciplines such as mathematics, engineering, and programming, is one in which the maximum desired effect is achieved with the smallest or simplest effort.

In the last few blogs, I figured out a number of solutions for returning the insertion text via Hotkey combinations for multiple GUIs in the InstantHotkey.ahk script. Many of these approaches worked, yet I continued searching for a more elegant answer. Now, I present my best solution (so far) which includes the use of an AutoHotkey associative array.

If you’re new to AutoHotkey with little or no scripting experience, then this blog may venture a little too far into the weeds. I don’t like to discourage new users with more involved concepts because the journey into Windows scripting is well worthwhile. Most find it easy to get started with AutoHotkey with many simple-to-implement tools. However, it takes a little time to understand the nuances of the more advanced techniques. I recommend that AutoHotkey noobies start with the fundamentals such as found in the “Introduction to AutoHotkey: A Review and Guide for Beginners” page. You’ll obtain immediate, rewarding results with basic AutoHotkey. Then, as your comfort with scripting increases, introduce yourself to more of AutoHotkey’s power with some of the slightly elevated topics.

AutoHotkey Variable Arrays

Variable arrays provide a method for creating multiple variables from the same root word. The advantage to arrays lies in the fact that you can store numerous variable values without assigning new variable names—later recalling those values with either an index or key. The fact that an AutoHotkey Loop command can recall or search all the array values creates a tremendous advantage over totally unconnected variables. In AutoHotkey, you’ll find three types of arrays: pseudo-arrays, simple arrays, and associative arrays. AutoHotkey users tend to feel more comfortable with pseudo-arrays since so many AutoHotkey scripts commonly use them. However, you might find that true arrays (simple and associative) often provide better solutions for certain applications.

I discuss an example of associative arrays in “Chapter Seventeen: Reduce Code and Increase Power with the AutoHotkey Input Command” of my book Beginning AutoHotkey Hotstrings.

Pseudo-Arrays

ProgrammingRobot
“He fired me for an array of reasons—Reason[4] and Reason[23] to be exact.”
A true array uses built-in capabilities to store multiple values in one variable name through the use of indexes or keys (e.g. Array[index]). A pseudo-array (fake array?) manipulates the variable name to create multiple, yet independent, variables linked only by a similar root name and, usually, a sequential number appended to the root name. AutoHotkey calls these variables pseudo-arrays because AutoHotkey uses the traditional double-percent-sign replacement technique (e.g. Array%index%) to create unique sequential variable names.

Programmers understand that, while the pseudo-array technique works, it doesn’t constitute a true array. A true array (called a simple or associative array in AutoHotkey) uses indexes or keys within brackets to save and access variable values (e.g. Array[index/key]). True arrays don’t require modification of the variable name to create more variables. The root name of both array types never changes, although, they behave in substantially different manners.

My various InstantHotkey.ahk scripts use pseudo-arrays to name each of the multiple GUIs (e.g. InstantHotkey%GuiNum%). This provides an easy method for distinguishing the various GUIs. Furthermore, the previous versions of the script used those variable names as two-deep variables for saving the Hotkey combinations and insertion text. This enabled AutoHotkey to track each GUI and its values as users set up more and more Instant Hotkeys.

The persistent problem discussed in the last couple of blogs occurred when executing an Instant Hotkey combination. I found no easy way to associate the GUI number portion of the variable (InstantHotkey%GuiNum%) with the pressed Hotkey combination. While I found pseudo-arrays worked well for creating unique variable names, they established no automatic association between the variables after the GUI closed—even though they used the same index number. Associative arrays solved the problem.

Simple and Associative Arrays

The most basic form of a true array, called a simple array, uses the same root name to track any number of values. You distinguish each variable by its index number (e.g. Array[Index]). Calling the array variable with the index number (or a variable containing an index number) does the job.

Note: With AutoHotkey arrays, you don’t need to use the double-percent-sign form of evaluation (%variable%). In fact, you can’t use double-percent-sign variable evaluation. You must treat true arrays as expressions rather than a simple variable macro replacement. (If you apply the tradition %var% variable evaluation to a true array e.g. %Array[Index]%, it generates an error when AutoHotkey detects the square brackets as illegal characters in a variable name.)

Simple arrays work in situations where you only need to recall a consecutive number of values tracked by the array index. You’ll find a couple of methods for creating a simple array :

Array := [Item1, Item2, ..., ItemN]
Array := Array(Item1, Item2, ..., ItemN)

However, if you want to connect seemingly unrelated items with a key, then turn to associative arrays. This works for connecting a Hotkey combination to the specific insertion text in the InstantHotkeyArrays.ahk script.

With associative arrays, you can create special sets of variables which both create relationships and store values. Each associative array includes a key and value:

Array := {KeyA: ValueA, KeyB: ValueB, ..., KeyZ: ValueZ}
Array := Object("KeyA", ValueA, "KeyB", ValueB, ..., "KeyZ", ValueZ)

You can use almost anything as a key in an associative array—including Hotkey combinations. That means we can directly access particular Instant Hotkey text by saving it in an array variable keyed on the pressed Hotkey combination (A_ThisHotkey).

Setting Up True Arrays

Once we add an associative array to the InstantHotkeyArrays.ahk script,  we can connect the Hotkey combination directly to the proper insertion text. But, first a couple of important notes about true arrays:

  1. Before using an array, you must declare it.
  2. You can only evaluate true arrays as expressions, not traditional double-percent-sign variable substitution (%var%).

Creating Arrays

In AutoHotkey, you’ll find a number of methods for creating arrays via declaration statements. Each of the statements above creates an array, but they also add values. If you don’t yet know the values (as in the case of InstantHotkeyArrays.ahk, then any one of the following statements works:

InstantHotkey := []
InstantHotkey := {}
InstantHotkey := Object()
InstantHotkey := Array()

One of these lines of code must appear in the script before adding any values or {key: values} to the array. I don’t think it matters which one. (If immediately adding values to an array, as in the earlier examples, AutoHotkey automatically creates the array.) When using Object() or Array(), use the exact term, otherwise, AutoHotkey treats it as a function.

I added the first statement InstantHotkey := [] to the auto-execute section of the script.

Saving Instant Hotkey Data

I have two values which I must save and connect: the assigned Hotkey combination and the associated insertion text. I don’t need to save the GUI numbers because I can match the array indexes to the GUI names (e.g. InstantHotkey[1] ⇒ InstantHotkey1, InstantHotkey[2] ⇒ InstantHotkey2, InstantHotkey[3] ⇒ InstantHotkey3, …)—as I did previously with the GUI numbers and the System Tray menu items.

Note: You may observe that I continue to use the pseudo-array InstantHotkey%IH_Count% for each new GUI name. Since I can’t use the traditional variable replacement (%var%) with true arrays, I found it less complicated to stick with the pseudo-array. I could have used a true array to contain the GUI name by using the forced expression (%) operator to evaluate an array in the Gui, name:add, control portion of the Gui command:

Gui, % InstantHotkey[GuiName] . ":add", add, …

However, this would require me to also save the GUI name in the array which only makes things more complex. Sometimes pseudo-arrays offer the elegant solution.

I used the InstantHotkey[] array to save the two needed data values from any new or updated GUI with:

InstantHotkey[GuiNum] := KeyCombo     ; Hotkey combination
InstantHotkey[KeyCombo] := TextInsert ; Insertion text

The first line saves the Hotkey combination (KeyCombo—e.g. ^!o) in the InstantHotkey[GuNum] array keyed to the GuiNum. The second line saves the associated insertion text (TextInsert) in the InstantHotkey[KeyCombo] array keyed to the Hotkey combination itself. This creates the needed connection between the Hotkey combination and the insertion text.

If we set up three separate Instant Hotkeys, the InstantHotkey[] array might contain values similar to the following:

InstantHotkey[1] = "^!o"
InstantHotkey[2] = "^!n"
InstantHotkey[3] = "^!b"
InstantHotkey["^!o"] = "This is the text for Hotkey CTRL+ALT+O."
InstantHotkey["^!n"] = "This is the text for Hotkey CTRL+ALT+N."
InstantHotkey["^!b"] = "This is the text for Hotkey CTRL+ALT+B."

Now, whenever pressing one of the Hotkey combinations, we only require one line of code to insert the text into any document or text editing field:

TextAdd:
  SendInput, % InstantHotkey[A_ThisHotkey]
Return

Using the value of the built-in AutoHotkey variable A_ThisHotkey (the most recently pressed Hotkey combination) as the array key, the script uses the forced expression operator (%) to return the insertion text from the matching InstantHotkey[KeyCombo] array variable and Send it (SendInput command) to a document or editing field.

Next time, I look at a special array loop (For index, element in array) and use it to display a Hotkey reminder window.

jack

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