I recently switched to Mac OS X as my primary desktop operating system after spending over a decade on Linux. Although Apple's operating system supplies practically all of the command line tools I know and love, I want to spend less time in a terminal window and start cultivating workflows that integrate better with the Mac user experience.

In my quest to tear the power of the command line out of the terminal, I have found that Apple's Automator tool is a powerful ally. Although it's not as mighty as the command line for improvisational automation, it's useful for defining stand-alone operations that you want to be able to repeat. I've used Automator over the past week to build simple applications that replace some of my personal shell scripts.

One of the most compelling features of Automator is support for building services—headless applications that are pervasively accessible throughout the operating system. Many services are context-sensitive and designed to process or operate on user input. A brief and unscientific poll of Mac enthusiasts revealed that few actually use the Services menu. Despite its relative obscurity among users, I've learned to appreciate its value.

Apple offers a number of its own services—like one that supports dictionary lookup on a selected word—that work with the platform's standard applications. Third-party developers can also create services to deploy with their applications. Automator makes it really easy for regular end users to create their own services with specialized behaviors.

As a Linux refugee, one of the features that makes Automator particularly compelling is that it allows me to integrate command-line operations, commands, and pipelines into my Automator workflows. In this tutorial, I'm going to show you two of the ways that I use shell scripting in Automator services in order to simplify my work.

A trivial example

I write virtually all of my articles in the Vim text editor and use Markdown syntax for formatting. On Linux, I used a Markdown processing tool from the command-line to convert my articles to HTML and then piped the output into the xclip command so that I could just paste the finished article directly into Ars Technica's content management system. I had a simple shell script that I could call directly from within Vim itself to perform those steps.

This same approach is still viable on Mac OS X, but I wanted to explore a more Mac-native solution to the same problem. More importantly, I wanted a solution that wasn't tied solely to Vim. That's where Automator comes into play. I built a trivial service that wraps a command-line Markdown processor. I can select a block of editable text with Markdown formatting in any Mac application and use the Markdown service to convert it to HTML in place.

To create a service, you start by selecting New from Automator's File menu. Automator will show you a list of available templates and prompt you to choose one for your new project. You should select the Service option, which is accompanied by a gear icon. In your new service, you will see a bar at the top of the Automator flow pane. It has combo boxes that allow you to set filters that establish the conditions in which your service should be made accessible. You want to make a service that receives selected text and will operate in any application.

Below those combo boxes is a checkbox that you can toggle to specify whether you want the output of your service to replace the selected text block. We definitely want that to be checked for our Markdown service, because we are replacing the Markdown-formatted input text with the HTML output provided by the Markdown processing engine.

The behavior of our Markdown workflow is really simple, so it will only require one action. From the left-hand action library pane, drag the Run Shell Script action out into the workflow pane. It will automatically create a connection with the top bar, indicating that it will use the user's selected text as the initial input.

The shell script action has a few simple options. You can choose the shell environment that you want to use for the operation and you can choose how you want it to handle the input. For the purpose of this example, we want to use the standard Bash shell. We also want to configure the action to pass the input into stdin, the UNIX standard input stream. This is a really useful capability in Automator, because it makes it possible to seamlessly mix Automator workflows with shell pipelines.

In the main text area of the shell action, we need to specify what command-line expression we want Bash to execute. In this case, all we want it to do is run the markdown command. I have already installed the markdown command using the relevant Homebrew package, but Automator's Bash shell doesn't seem to find it in my command path. To work around Automator's difficulty finding the command, I simply put the full path into the text box, as you can see below.

Now that the workflow is complete, you just have to save it under the name Markdown. By default, Automator will store your custom services in the ~/Library/services directory. Any Automator service that is copied into that path will be made available through the services menu under applicable conditions. To run the new service, you just have to select some text and then click the Markdown item in the services menu.

There are a number of ways that you can customize this service to achieve alternate behaviors. For example, you could use the Copy to Clipboard action at the end of the workflow to make the output go to the user's clipboard rather than replacing the selected text.