Despite my comment about a minor bug in TextExpander, I do find it very useful. I decided if I want to make more effective use of TextExpander (and justify me paying the subscription cost), I needed to come up with a simple way to make use of the JavaScript functionality regularly. Partially inspired by listening to Grey’s review of his 2024 “year of small improvements” theme on the Cortex podcast, I decided to spend a little time figuring out how to use JavaScript in TextExpander effectively. The two or three times I’ve tried to use JavaScript in TextExpander before, I didn’t have much luck finding good examples beyond very simple things.
As an example, I wanted a snippet to create a Python unit test file given the name of the file you want to test. I wanted the name of the unit test class to have the first letter capitalized. Despite programming for over four decades, I’ve managed not to learn or write much JavaScript so when I need some JavaScript code, I usually end up searching the web. Of course now, ChatGPT (or similar) is great for writing simple JavaScript functions (which is why there’s a decent chance of me using it in TextExpander more often). I used ChatGPT to create the capitalizeFirstLetter
function in the snippet below.
The next step was figuring out how to incorporate TextExpander fill-in fields into a JavaScript snippet. It’s actually simple, but I couldn’t find good examples showing this. In this case, I want the name of the file we are testing to be a fill-in field. The line:
let filename = "%filltext:name=filename:width=20%";
takes the value of the fill-in field and assigns it to the filename property. The documentation I had found said to use TextExpander.filledValues["filename"]
but this seems simpler. Since the filename is a string of characters (not a number), you need the quotes before and after the TextExpander macro that begins and ends with the percent characters so that JavaScript sees the fill-in as a string. Instead of needing to type it like that, you can write let filename = "";
and then place the cursor between the quotes and use the TextExpander interface to create a fill-in (click on icon for fill-ins and select “Single Line Field”). In my actual snippet (not included in the example below), I also used the TextExpander date snippets you can create by clicking on the TextExpander UI to insert a date such as 01/05/2025 on the line after my name in the expanded snippet.
Next I can use the function capitalizeFirstLetter
function to make a capitalized version of that fill-in value:
let capitalizedFilename = capitalizeFirstLetter(filename);
We can now use template strings in JavaScript to copy the majority of the text we want for the snippet and insert the values of the JavaScript variables (that hold the filename and capitalized version of it) where they should be in the snippet. The syntax is the single backtick quote character to make a multi-line template string containing what I want the result of my expanded snippet to be. In the full snippet example below, the let output =
line starts that. We can use our JavaScript variables filename
(from the fill-in) and capitalizedFilename
from calling the function inside the template string by putting ${filename}
or ${capitalizedFilename}
inside the template string. We end the template string with a matching single backtick quote character.
Finally in TextExpander JavaScript snippets, the result of the last expression can be used to specify what the snippet expands to so I simply add the line output
as the last line of the snippet since that is the name of the template string variable we created. The TextExpander docs mention using the code TextExpander.appendOutput()
function which you can do but that is tedious to use for every line. Using a JavaScript template string makes it easier to paste in most of the content you want for the snippet. The following is the snippet (other than the date portion). If you want to try it out, copy the text below into a TextExpander snippet and be certain to mark the “Content Type” of the snippet as JavaScript (not Plain Text, etc.). In case it doesn’t copy/paste easily from this post, here is a GitHub gist you can copy it from (link). I hope this saves time for others who want to write TextExpander JavaScript snippets.
function capitalizeFirstLetter(input) { // Capitalize the first letter and append the rest of the string return input.charAt(0).toUpperCase() + input.slice(1); } let filename = "%filltext:name=filename:width=20%"; let capitalizedFilename = capitalizeFirstLetter(filename); let output = `#!/usr/bin/env python3 # ---------------------------------------------------------------------- # test_${filename}.py # Dave Reed # # ---------------------------------------------------------------------- import unittest from ${filename} import * # ---------------------------------------------------------------------- class ${capitalizedFilename}Test(unittest.TestCase): def test1(self): pass def test2(self): pass def test3(self): pass # ---------------------------------------------------------------------- if __name__ == '__main__': unittest.main() `; output