Advertisement
  1. Computer Skills
  2. Alfred
Computers

Creating Alfred Workflows in Haskell

by
Difficulty:AdvancedLength:LongLanguages:
Final product image
What You'll Be Creating

Functional Programming is the programming paradigm where you program without using variables. Functions call other functions with the variable passing between.

This paradigm allows for constants and strong type casting. It is also characterized with lazy evaluation: expressions are not evaluated until a result is required.

Haskell is a functional programming language that has been around since 1987. It has a great community of programmers behind it and is available on the Mac, Windows, and Linux platforms.

In this tutorial, I’ll create an Alfred library to help make workflows in Haskell. Then I am going to create a workflow using this library.

In this tutorial, I’ll assume that you’re already familiar with writing workflows in Alfred. If not, please check out these tutorials:

Since a complete description of Haskell programming is outside the scope of this tutorial, you can read A Gentile Introduction to Haskell: Version 98. I personally learned Haskell from the free book Write Yourself a Scheme in 48 Hours. I like to learn new languages by writing a program that is useful.

Installing Haskell

To use Haskell on the Mac, you first need XCode installed. This is a free install from the Mac App Store. When downloaded, launch XCode and open the Preferences Panel.

Opening XCode Preferences

In the Preferences Panel, click on the Locations item. At the bottom, make sure the Command Line Tools is pointing to your version of XCode. It will ask for a user login. Once given, the command line tools are set up to use.

With XCode installed and set up, download the Haskell compiler and support files from Haskell for Mac OS X.

After unzipping the file, move the ghc-7.10.1.app to the Applications folder (7.10.1 was the latest version as I wrote this tutorial).

Haskell Compiler Installer

The installer shows the code to add to your ~/.bash_profile file and your ~/.zshrc file (if you use Z-shell). Once you add that code to your shell files, click the Refresh Checklist. All of the checkboxes should be green. You are now ready to create Haskell programs.

Alfred Library in Haskell

Haskell has a package manager similar to NodeJS’s npm. It is cabal. With cabal you can download and install many third-party libraries that others have written in Haskel. For the Alfred Haskell Library, you need to install the TagSoup library. This helps retrieve the bundleid of the Alfred workflow. On the command line, type:

Now create a new file called Alfred.hs. All Haskell program files end with the .hs extension. In this file, start placing this code:

The module Alfred ( starts a module. All Haskell files are modules. Inside the parenthesis defines the functions that this module will make available. All Haskell functions start with a lower case letter. If the module is to be the main program, it has to have a main function. Since this is a library, it just has functions and constants declarations.

After declaring the module and what it exports, you write the list of the different libraries used. This library makes use of three libraries: System.Process, System.Directory, System.Environment, and the Text.HTML.TagSoup that we downloaded with cabal.

Next, I define three constants. The first line is the type declaration with the actual definition below it. The :: symbol declares that the next items are type declarations. Here, we are defining the constants as a String type.

The addItem function takes seven String inputs and creates the XML item String as output. Notice the type declaration looks like eight String types separated by ->. The -> symbol shows the next type. The first seven types are the input with the last one being the return value. All functions in Haskell have to have a return value.

The addItemBasic uses the addItem function to create an XML item with three of the inputs set to a default value.

The getBundleID get the ID of the Alfred Workflow bundle from the info.plist file in the workflow directory. This file is a plain text plist. Since this is a type of XML or HTML format, TextSoup library works real well to read it in and decode it. This is a monad function (simply put, a function that interacts with the item outside the program. For instance: files, GUI, etc) You can learn more about monads in the monads tutorial. Any function with the return type of IO () is a monad for input or output functions.

Here, the functional programming style breaks down to a list of items. The do keyword says, “do the following in order”.

The first line after the do reads in the info.plist file and parsed out the tags using parseTags from the TextSoup library. The second line finds the first dict tag and drops everything until the string tag. It then extracts the tags contents and places it in the trasistional constant id. id is a constant because it’s value can not change. Since all Alfred info.plist files have the exact same layout, I do not need to test the key to be correct. The id value is then returned.

The next monad function gets the contents of a file that is in the Alfred Data Directory for the workflow and returns it to the calling function. The function first gets the user’s home dirctory, gets the bundle ID, creates a path to the Alfred Data Directory for the workflow, and returns the contents of that file if it exists. Otherwise, the function returns an empty string.

The next monad does the exact opposite. It takes a file name and the data to store in that file. Since the contents will be put in to the file named whether or not it exists, the existence of the file does not need to be determined.

The last two monad function in the library reads and writes files in the Alfred Cache directory for the workflow.

Haskell Case Converter

With the library created, it is to write a workflow. Create a new workflow in Alfred called Haskell Text Converter as shown:

Haskell Text Converter Alfred Workflow

The Script Filter should look like this:

Script Filter for Workflow

Now, click on Open workflow folder. This opens the folder for the workflow in finder. Put a copy of the Alfred.hs in it. Now, create the file cases.hs and place this code there:

This code takes in a string from the command line and generates the Alfred Script Filter xml format with nine different case types.

The title case format uses two lists of words to make all upper case or all lower case. The actual function toTitleCase uses conditionals to see if the word is in the upper case list or the lower case list. If it is, make it that way. Otherwise, just make the first letter upper case.

The helper function processLine takes a string and a function, applies the function to all entries in a list of strings, adds the string to each entry, and concatenates the resulting strings together. This function processes many of the case conversions on a full string.

I created a helper function addItemCase that duplicates the arg value to the title value in the addItemBasic function in the Alfred library. Functional programming is about creating function of functions that get the job done without varialbles!

Most of the other functions are fairly easy to figure out. I give you the assignment to study this so that you can make your own Haskell workflow.

To compile the program, type this on the command line in the directory of the workflow:

With the program compiled and the workflow created, you can now use it to convert strings. In the Alfred Prompt, type ht:conv this is a test .

Test String in Haskell Text Converter

The above picture shows the result. Select the one you want and it is placed in to the clipboard. The download file contains a copy of this workflow. I also have an expanded version available at Haskell Text Converter on Packal.org.

Also, I am constantly improving and adding to the Alfred Library in Haskell. You can always get the lastest version at Alfred Library in Haskell GitHub Repository.

Conclusion

In this tutorial I have shown you how to install Haskell on your Mac, create an Alfred library to help create new workflows, and made a sample workflow with the library. Now, it is your turn to make some great Alfred Workflows. Please share them in the comments below.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.