Learning Shortcuts

I wanted to learn a little about the Shortcuts app and decided to write some simple shortcuts. The general process I followed was:

  1. Open the Shortcuts app and select File > New Shortcut.
  2. Click on “Shortcut Name” in the upper-left corner and enter the desired shortcut name.
  3. Search or scroll through actions in the sidebar to find the desired action.
  4. Drag the action found in step 3 into the main window and configure.
  5. After the shortcut is complete, run and make any necessary edits.
  6. Click on the information icon in the upper-right-hand corner of the app, select the Details tab, and enable “Pin in Menu Bar”.
  7. Save the shortcut by closing its window.

Some related information:

  • The shortcuts are stored in ~/Library/Shortcuts in a database.
  • You can export and import a shortcut. When exporting, maximum compatibility is achieved by enabling the “Anyone” option.
  • In most cases, I will provide a screenshot of the shortcut, and a link to a shortcut file, which can be downloaded and installed. If a shortcut is downloaded and installed, you will be prompted to set permissions the first time the shortcut is run.
  • The context menu for a shortcut contains an option to place the shortcut in the dock, which can be a convenient method to run a frequently-used shortcut.

This shortcut creates a PDF from files selected in a Finder window or on the Desktop. A few notes:

  • Source files are added to the PDF in the order they were selected.
  • The target PDF is placed on the desktop with the file name “Merged Files.pdf”.
  • The following screencapture only shows the first portion of the shortcut.

Make PDF.shortcut (23.4 KB)

This shortcut performs OCR on an image or PDF file and saves the resulting text to a file on the desktop. An error dialog is displayed if the extension of the selected file is not contained in the List action.

OCR Image.shortcut (23.1 KB)

@peavine
Nice try :wink:

  1. It use default name for your output (PDF Document.pdf) (I was selecting RTF)
  2. If the input is not acceptable format it return error.
  3. It only allow 1 input to be saved.

The 2) if you filter the input
The 3) I guess repeat loop could solve

Thanks Fredrik71 for looking at my thread. I assume your comments relate to the shortcut in post 2.

As regards item 1, I modified the shortcut to save the target PDF file to the desktop with the name, “Merged Image Files.pdf”.

As regards item 2, a generic error notification is shown if a selected file cannot be made into a PDF, but I need to improve that. I haven’t yet considered error correction in a shortcut.

As regards item 3, multiple input files are allowed and saved. The way the shortcut is written, you select the input files in a Finder window and then run the shortcut. As originally written, the shortcut prompted the user for a target folder, but I’ve changed that.

The following saves a copy of every shortcut in a backup folder. On my Ventura computer, it will not save shortcuts to an external drive. A workaround is to disable the Overwrite if File Exists option.

Backup.shortcut (22.2 KB)

@peavine
Here is some Shortcuts for you to try

1 Like

Thanks Fredrik71–that’s a useful site. I note that it contains the following:

Anyone is free to download, modify, and redistribute shortcuts from the MacStories archive. Our shortcuts are provided for free and out of love for the Shortcuts automation community. In fact, we encourage readers to download shortcuts and optimize them to their needs. No attribution is necessary, but we always appreciate it.

And here is some actions with source from GitHub

Its looks like a nice project for learning Swift coding :wink:

One of the biggest issues I’ve encountered in running Shortcuts is assigning them a keyboard shortcut. This can be done with a Quick Action, but it doesn’t seem to work very well in my experience. An alternative that is somewhat better in preliminary testing is to create an AppleScript, which I then run by way of FastScripts.

tell application "Shortcuts Events" to run shortcut named "Tile Apps"

@peavine
Shortcuts could also be running from terminal.

shortcuts run <your_name>

So you do not need AppleScript you could also use unix shell

The Late Night Software forum contains a thread (by Dirk) that discusses passing a parameter to a shortcut and getting the result back (it can be found here). I decided to investigate how this might work in one use scenario.

The AppleScript is:

set theFolder to (choose folder)
tell application "Shortcuts Events"
	set theFiles to (run shortcut named "Get Files" with input theFolder)
end tell

The shortcut is:

The shortcut returns a list of aliases of files in the target folder and its subfolders, and the timing result with a folder that contained 395 files in 85 folders was 1.214 second, which is clearly a poor result. However, this same general approach could be useful in calling regular macOS apps.

This shortcut moves and resizes the frontmost app to the values specified in the Dictionary action. A few comments:

  • If an app is not in the dictionary, a default value is used.
  • The shortcut does nothing if the active app is Finder.
  • The following screenshot only shows the first section of the shortcut.

Window Set.shortcut (24.3 KB)

The Shortcuts app has a Run Shell Script action which does a good job. Running a shell command and setting the output to a variable is simple:

Quoting a portion of the command line when that is necessary is fairly straightforward:

Screencapture.shortcut (22.3 KB)

I spent some time investigating date handling in Shortcuts and thought I would summarize available actions.

Date. Returns the current date and time.

Format Date. Separate options are provided for date and time, and these options include none (nothing is returned), short, medium, long, and custom.

Get Dates from Input. This action gets a date from a large number of inputs including text, calendar events, weather conditions, and iTunes and photo media.

Convert Time Zone. Change a date from a specified time zone to a specified time zone. In limited testing, this action appears to respect Daylight Savings Time.

Adjust Date. Add a specified number of date or time intervals to a date.

Get Time between Dates. I’ll use an example here

@peavine
If you like to know how to do the same in AppleScriptObjC

use framework "Foundation"
use scripting additions

set dateFormatter to current application's NSDateFormatter's alloc()'s init()
dateFormatter's setDateFormat:"yyyy-MM-dd HH:mm:ss"
set dateString1 to "2023-08-28 10:00:00"
set dateString2 to "2023-08-28 11:30:00"

set date1 to dateFormatter's dateFromString:dateString1
set date2 to dateFormatter's dateFromString:dateString2
set timeInterval to date2's timeIntervalSinceDate:date1
set minutesDifference to timeInterval / 60

And the above could be also be done like this

on minutesDifferenceFromDates2(firstDate, secondDate, dateFormat)
	set dateFormatter to current application's NSDateFormatter's alloc()'s init()
	dateFormatter's setDateFormat:dateFormat
	set dateString1 to firstDate
	set dateString2 to secondDate
	
	set date1 to dateFormatter's dateFromString:dateString1
	set date2 to dateFormatter's dateFromString:dateString2
	
	set calendar to current application's NSCalendar's currentCalendar()
	set unitFlags to current application's NSCalendarUnitMinute
	set components to calendar's components:unitFlags fromDate:date1 toDate:date2 options:0
	return components's minute()
end minutesDifferenceFromDates2

And here is other approach…

set hoursMinutes to its hoursMinutesDifferenceFromDates("2023-08-28 10:00:00", "2023-08-28 11:30:00", "yyyy-MM-dd HH:mm:ss")

on hoursMinutesDifferenceFromDates(firstDate, secondDate, dateFormat)
	set dateFormatter to current application's NSDateFormatter's alloc()'s init()
	dateFormatter's setDateFormat:dateFormat
	set dateString1 to firstDate
	set dateString2 to secondDate
	
	set date1 to dateFormatter's dateFromString:dateString1
	set date2 to dateFormatter's dateFromString:dateString2
	
	set calendar to current application's NSCalendar's currentCalendar()
	set unitFlags to ((current application's NSCalendarUnitHour as integer) + (current application's NSCalendarUnitMinute as integer))
	set components to calendar's components:unitFlags fromDate:date1 toDate:date2 options:0
	set hoursDifference to components's hour()
	set minutesDifference to components's minute()
	return {|hours|:hoursDifference, |minutes|:minutesDifference}
end hoursMinutesDifferenceFromDates

The following shortcut adds a user-specified time interval to the current date. I wrote this primarily to demonstrate two issues.

Apple encourages the use of Magic (unnamed) Variables, which makes it unnecessary to formally set the output of an action to a Manual Variable. This contributes to code brevity but can make a shortcut difficult to follow. The shortcut contained below uses Magic Variables only.

The Shortcuts app has an if…otherwise…endif statement but that’s all. The workarounds are to nest if statements (which is clumsy), to use multiple consecutive if statements (which can be inefficient), and to use a repeat loop (which doesn’t always work). The shortcut included below use multiple consecutive if statements and doesn’t suffer any inefficiency as a result.

Date Calculator.shortcut (24.0 KB)

Primarily for comparison purposes, I rewrote the above Date Calculator shortcut and incorporated the following changes:

  • The allowed date intervals are day, week, month, and year.
  • The shortcut returns a date only.
  • Manual Variables are used where this aids in understanding the flow of the shortcut.
  • Nested if statements are utilized.
  • Date formatting and a copy-to-clipboard option are included.

Date Calculator 1.shortcut (24.6 KB)

Apple states that “a shortcut is a quick way to get one or more tasks done with your apps.” I wasn’t sure how to accomplish this in all circumstances and thought I would quickly summarize what I’ve learned.

You can create shortcuts for specific apps, and a simple example is one that directs the Music app to play a particular song. Shortcuts that fall in this category are run by any of methods described in earlier posts (for example the Shortcuts Menu).

You can also write a shortcut that gets input from a running app and then outputs to the app. The following shortcut–which alphabetically sorts lines of selected text–is a good example. This shortcut can be run by way of an app’s Services menu or a keyboard shortcut but not by way of the Shortcuts Menu or a dock icon.

Sort Lines.shortcut (21.8 KB)

Here is example using ASObjC to use NSPasteboard to sort text.

  1. Select any text that you like to be sorted.
  2. Copy → command + c
  3. Run the AppleScript to sort the paragraphs
  4. Paste → command + v
use framework "Foundation"
use scripting additions

set pasteboard to current application's NSPasteboard's generalPasteboard()
set theData to pasteboard's dataForType:(current application's NSPasteboardTypeString)
set theString to current application's NSString's alloc()'s initWithData:theData encoding:(current application's NSUTF8StringEncoding)
set theParagraphs to theString's componentsSeparatedByString:linefeed
set sortedParagraphs to theParagraphs's sortedArrayUsingSelector:"compare:"
set sortedText to sortedParagraphs's componentsJoinedByString:linefeed
set theData to sortedText's dataUsingEncoding:(current application's NSUTF8StringEncoding)
pasteboard's clearContents()
pasteboard's setData:theData forType:"public.utf8-plain-text"