Drafts Actions Keyboard Shortcuts Audit

As you may already know, the Drafts app by AgileTortoise is a highly flexible application, and through it’s actions functionality, it effectively provides a framework through which to create customisable operations such as those you might find with plug-ins on desktop only applications.

One of the features of the actions is that you can tie them to particular keyboard shortcut combinations. But what isn’t quite so easy is the auditing of those keyboard shortcuts, and a number of people on the Drafts forums voiced their desire to have something to do this. To that end, I created a way to do this.

How? By using an action of course!

Overview

The action I created is the TAD-Export Action Shortcut Keys action, which can be found in the ThoughtAsylum - Power User action group, part of the ThoughtAsylum Action Group Suite. Like the majority of the actions in the action group, it utilises TADpoLe for some of the functionality.

The main JavaScript code for the action is shown below, but I’ll first describe how it works.

Breakdown

The first part of the code initialises some arrays, creates an array of all action groups, and then builds an array that combines all of the actions from those action groups. That’s effectively an array of all actions in Drafts as every action must belong to one, and only one, action group.

//Initialise
let aactAll = [];
let astrOutput = [];

//Get all actions
let aactgrpAll = ActionGroup.getAll();
aactgrpAll.forEach(function(actgrpCurrent){aactAll = aactAll.concat(actgrpCurrent.actions);});

The next part of the code loops through every action in the array. Because the action object does not currently make all attributes of an action available, we have t dig in and do some processing ourselves. Fortunately, the action’s installation URL is available, and that contains all of the information needed to create the action, so we just need to process it to get any keyboard shortcut data.

//Process each action
aactAll.forEach(function(acCurrent)
{
	//Process the install URL
	
	//If we can find any shortcut data, add the details to the output list
});

The processing of the action installation URL involves stripping the installter part of the URL to get the installation data part, decoding it from being a URL (percent encoding) to the original JSON data, and then parsing that into a JavaScript object.

//Process the install URL
let strLink = acCurrent.installURL.replace("drafts5://action?data=","");
strLink = decodeURIComponent(strLink);
let jsonData = JSON.parse(strLink);

With the object, we can then access the keyboard shortcut information. Here we make use of some of a TADpoLe function, TA_actionKeys() to compile the various data items for the keyboard shortcut into a single string that describes the keyboard shortcut. If a keyboard shortcut is identified, the details are added to the array to be used for output.

//If we can find any shortcut data, add the details to the output list
if (jsonData.hasOwnProperty("keyCommand"))
{
	let strShortcut = tadMisc.TA_actionKeys(jsonData.keyCommand);
	if (strShortcut != "") astrOutput.push(`${strShortcut.padEnd(6)}${acCurrent.name}`);
}

Note that the keyboard shortcut string is padded to a specific length before adding the shortcut name. This is simply for (fixed-width font) alignment purposes.

Once the array has been populated, it is output to a plain text-based draft with each keyboard shortcut and action being output to a new line.

//Output to a new draft
let draftNew = draft.TA_draftNew(astrOutput.join("\n"));
draftNew.languageGrammar = "Plain Text";
draftNew.update();

The Code

The combined code for the action looks as follows.

//Initialise
let aactAll = [];
let astrOutput = [];

//Get all actions
let aactgrpAll = ActionGroup.getAll();
aactgrpAll.forEach(function(actgrpCurrent){aactAll = aactAll.concat(actgrpCurrent.actions);});

//Process each action
aactAll.forEach(function(acCurrent)
{
	//Process the install URL
	let strLink = acCurrent.installURL.replace("drafts5://action?data=","");
	strLink = decodeURIComponent(strLink);
	let jsonData = JSON.parse(strLink);

	//If we can find any shortcut data, add the details to the output list
	if (jsonData.hasOwnProperty("keyCommand"))
	{
		let strShortcut = tadMisc.TA_actionKeys(jsonData.keyCommand);
		if (strShortcut != "") astrOutput.push(`${strShortcut.padEnd(6)}${acCurrent.name}`);
	}
});	

//Output to a new draft
let draftNew = draft.TA_draftNew(astrOutput.join("\n"));
draftNew.languageGrammar = "Plain Text";
draftNew.update();

The Result

The results are obviously individual, but the output should look something like this.

⌃⌥⌘N  !! Add Numbered Line
⌃⌥⌘B  !! Add Bulleted Line
⌘R    Call TAD-Execute Draft
⌘§    Call TAD-Execute Test Function
⌥⌘B   Call TAD-Beautify JavaScript
⌃⌘/   Call TAD-Slash Command In-Situ
⌥H    MD-Header
⌥B    MD-Bold
⌥I    MD-Italic

However…

After I’d implemented that action, I had need to do a few more things with actions, and so to make this easier for anyone to work with I added some more TADpoLe functionality and in the next update to the action group, the TAD-Export Action Shortcut Keys action code will be simplified to the following.

//Initialise
let astrOutput = [];

//Process each action
Action.TA_getAllActions().forEach(function(acCurrent)
{
	acCurrent.TA_populateMore();
	if (acCurrent._keyShortcut != "") astrOutput.push(`${acCurrent._keyShortcut.padEnd(6)}${acCurrent.name}`);
});	

//Output to a new draft
draft.TA_draftNew(astrOutput.join("\n"), "Plain Text");

Only one array is now initialised, and instead a direct call to a function to get an array of all actions is used for the loop to populate the output array.

The TA_populateMore() action is used to add extra data to each action object. Behind the scenes, this is functioning in just the same way as it did previously, but is actually assigning many more items of data form the installation URL to the action. As before these are added to the output array.

The final step has also been simplified with an optional parameter for the grammar having been added to the TA_draftNew() function.

Conclusion

This approach and shift typifies the way my development-cycle and the evolution of TADpoLe in general has come about. Things always begin with something that is perhaps heavy on the front-end and then over time as I see opportunity, and as time permits, I build more of the functionality into TADpoLe and simplify the front-end. Then subsequent developments can take advantage of that investment.

The real power here isn’t really in the actions I create using TADpoLe. They are of great use to me, and I know that many people find the ThoughtAsylum Action Group Suite useful too, but it is the personal actions people develop on top of Drafts and TADpoLe that I believe are the most useful on aggregate.

Author: Stephen Millard
Tags: | drafts | tadpole |

Buy me a coffeeBuy me a coffee



Related posts that you may also like to read