Scripting and Compiling Swift on the Command Line

April 4, 2017

Apple’s Swift programming language is most widely used for iOS and macOS development in Xcode, however, it can also be used in a manner more like a traditional Unix shell script or even compiled into an executable using the command line. Below, I give some examples of these alternative uses.

For scripting, like other shell scripts, the first line of your script’s .swift file should be a “shebang”, which points to the swift executable. Following that, you can write Swift code as usual:


func fibonacci(_ n: Int) -> Int {
    if n <= 2 {
        return 1
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2)


You can make the script executable and run it as you would any other shell script:

% chmod +x fibonacci.swift
% ./fibonacci.swift

Printing the 10th integer in the Fibonacci sequence is hard coded above, but what if you want to print other values? We can modify the script to take a single command line argument, the index of the Fibonacci number you want to print. Replace the last line above with the following:

let arg = CommandLine.arguments[1]  // Store first argument.
if let n = Int(arg) {               // If it converts to Int,
    print(fibonacci(n))             // print fibonacci(n).
} else {                            // Otherwise,
    print("Usage: fibonacci <n>")   // print usage and exit.

Then invoke the script as follows:

% ./fibonacci.swift 36
% ./fibonacci.swift junk
Usage: fibonacci <n>

As with modern scripting languages such as Python and Ruby, you can also run Swift interactively (with Xcode 6.1 and later). The interactive command-line interface is called the Swift Read Eval Print Loop (REPL):

% swift
Welcome to Apple Swift version 3.1 (swiftlang-802.0.48 clang-802.0.48). Type :help for assistance.
  1> 1 + 2
$R0: Int = 3
  2> print("hello, world")
hello, world

Finally, you can also compile Swift code and run it as a binary:

% swiftc -o fibonacci fibonacci.swift
% ./fibonacci 7

As with C and other languages, you can compile multiple Swift files:

% swiftc first.swift second.swift third.swift -o program

Note: These instructions are valid on macOS Sierra with Xcode 8.3 and Swift 3.1, but as the Swift language evolves they may change.

Using Markdown Mode: Switching and Toggling Markup

February 18, 2016

Markdown Mode is a major mode for editing Markdown-formatted text files in Emacs. On the surface, it provides syntax highlighting (“font lock” in Emacs parlance) to provide visual cues when editing files and it defines commands and keyboard shortcuts for inserting certain markup. For example, surrounding a phrase in double asterisks (**) in Markdown makes the phrase appear in bold when converted to HTML or another format. The corresponding key sequence in Markdown Mode for inserting bold text, as you probably know if you’ve read this far, is C-c C-s s.

The documentation for Markdown Mode is now quite lengthy, so certain features go unnoticed even by long-time users. Two of these features involve ways to switch types of markup (e.g., from bold to italics). As an example, suppose I typed **really scary** and wish I had written it instead using italics as *really scary*. There are at least two ways in Markdown Mode to quickly fix the mistake.

  1. Using the kill ring: Move the point anywhere in the bold span and press C-c C-k to execute markdown-kill-thing-at-point. This removes the entire bold span and adds the contents (“really scary” without the asterisks) to the kill ring. Then press C-c C-s e to insert an empty italic span and yank the text with C-y.

  2. Using markup toggling: Markdown Mode allows you to “toggle” certain markup, including, bold, italics, and inline code. The second method is to move the point to the bold text and repeat the insertion key sequence (C-c C-s s) to remove (toggle) the asterisks. Then select the text “really scary” (i.e., place it in the active region) and press C-c C-s e to add the italic markup.

In this case, because there are multiple words, you have to activate and set the region (the default is for insertion commands to apply to the single word at the point if there is no active region, or insert empty markup otherwise). This means the first approach is a little faster in this case, but there are cases where both approaches are useful. Both methods also apply to other forms of markup such as bold, italics, and even links.

Extra Credit: Suppose I have *really scary* in the buffer now but I wish it was _really scary_ instead. Both will render in HTML as italics, but you might have a preference for the latter in plain text. You can use the Markdown Mode cycling commands to switch between underscores and asterisks in bold and italic phrases by pressing C-c C-= or C-c C– (markdown-demote and markdown-promote).

Preventing Emacs From Filling Up Your Clipboard History

February 9, 2016

I use a clipboard manager called Copied that syncs previously copied text across all my devices. Short of having an OS X version of Drafts, this is a very efficient way to get text from a Mac to an iOS device. However, when I’m working in Emacs, my clipboard history quickly becomes cluttered because every bit of text I “kill” in Emacs gets “copied” to the system pasteboard and then synchronized to all of my devices.

Indeed, every time I select a sentence or paragraph and kill it with C-w (kill-region), that text gets added to the clipboard history. Worse still, every time I press M-DEL (backward-kill-word) to kill the previous word, that word also gets added to my history. I use these commands a lot, so even with a history of 100 previous items, the important items in my history are quickly buried under a heap of words and phrases that I have killed in Emacs during the normal process of writing and editing text.

This is mitigated to some extent by the fact that Copied allows one to quickly filter the history by just typing a search string in the main window. However, I discovered today that Emacs has a minor mode called delete-selection-mode and when this mode is active, the region is replaced when a character is inserted or deleted (e.g., with backspace). The practical implication of this is that one can remove the active region by pressing DEL rather than C-w:

By default, text insertion occurs normally even if the mark is active–for example, typing a inserts the character ‘a’, then deactivates the mark. If you enable Delete Selection mode, a minor mode, then inserting text while the mark is active causes the text in the region to be deleted first. To toggle Delete Selection mode on or off, type M-x delete-selection-mode.

Source: GNU Emacs Manual, section 11.3.

Also see DeleteSelectionMode on the EmacsWiki and in the Emacs FAQ. To summarize, if one uses DEL instead of C-w to remove text in the active region, it won’t end up in the kill ring or clipboard history. Somehow this slipped by me, but delete-selection-mode is enabled by default in Emacs 24 and 25.

Replacing M-DEL with an alternative that deletes without adding to the kill ring is less obvious. Without adding a custom function, a long version would be C-SPC M-b DEL. This sequence activates the mark1, moves the point backward by one word, and deletes the active region. If you find yourself using this often, it might be better to define a backward-delete-word function to your init.el (source):

(defun backward-delete-word (arg)
  "Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
  (interactive "p")
  (delete-region (point) (progn (backward-word arg) (point))))

I moved the default backward-kill-word binding to C-M-DEL and set M-DEL to this new function:

(global-set-key (kbd "C-M-<backspace>") 'backward-kill-word)
(global-set-key (kbd "M-<backspace>") 'backward-delete-word)

  1. Use C-SPC C-SPC to activate the mark if you keep transient-mark-mode disabled.

On the Security Implications of Suggested Snippets in TextExpander

August 21, 2015


Suggested snippets in TextExpander 5.0 and 5.1 are stored in plain text and synchronize to the cloud and other devices in kind. This may be unexpected given the current wording of the “Privacy Details” section of the help file (below). This may seem harmless, but if not configured carefully to exclude certain apps (e.g., Terminal, iTerm 2, Emacs) then TextExpander may unintentionally save passwords you type as suggested snippets, which then are stored in plain text and will propagate to the cloud and other devices. I contacted Smile support about this, since I thought it must be a bug or an oversight given what I read in the documentation. They kindly clarified the behavior and indicated that they will consider updating the documentation or adding an FAQ entry to address these points. Read more below for additional background, suggested configuration changes, and details on how to remove any such sensitive information that may have been stored in Dropbox as a result.

Background and Details

TextExpander from Smile is a Mac (and iOS) application that allows one to define short abbreviations for longer words and phrases. A TextExpander “snippet” consists of an abbreviation, content (the full-text associated with the abbreviation), and rules about how and when the abbreviation can be used. TextExpander then watches what you type and when an abbreviation is noticed it automatically replaces the abbreviation with the content, provided that the rules are satisfied.

This is only a basic description the program. More advanced snippets can include date and time arithmetic, scripts, fill-in forms with drop-down menus and optional sections, etc. Because of this, TextExpander is one of a core set of utilities that I install on every Mac I work on (and every iOS device).

Snippet Suggestion

TextExpander 5.x Preferences: Snippet Suggestion
TextExpander 5.x Preferences: Snippet Suggestion

In TextExpander 5.0, released in May 2015, Smile added a new feature called “Suggestions” whereby TextExpander will automatically suggest new snippets based on things you frequently type. This raises obvious privacy and security concerns, which are addressed as follows in the TextExpander 5.1 documentation:

Privacy Details

TextExpander observes your keystrokes, as well as the contents of the pasteboard when you Paste using ⌘V.

TextExpander will track how many times you repeat the same group of characters and create a new suggestion after a certain amount of repetition. However, it does not save the tracking of what you type so the tracking is lost with each TextExpander restart. Therefore, frequent restarting of TextExpander won’t result in many suggestions. None of what you type is saved by TextExpander except for the snippets listed in the Suggested snippets group.

“Tracking” does not mean TextExpander keeps a list of the actual characters you type. Instead, it keeps an encoded record (called a “hash”) of that group of characters, similar to the way a password is securely stored so that no one reading it knows what it is. You might type “yourpetsname” but what TextExpander sees and records is “1739405847385.”

Source: TextExpander 5.1 Help.

After reading this, I was fully reassured about any potential security risks. If TextExpander only keeps an encoded record of what I type and that record doesn’t persist across restarts, then I assumed it only kept the information in memory and that nothing would be stored in the cloud.

Insecure Text Input and Snippet Suggestion

There are measures in place to prevent TextExpander from storing potentially sensitive text, like passwords. However, on my system it still managed to occasionally suggest a passwords as new snippets. I admit to being slightly terrified every time a notification popped up to suggest that I add one of my important, paranoia-grade passwords as a snippet, but at least they weren’t being stored in plain text anywhere, or so I thought.

To understand why TextExpander was able to see my passwords in the first place, it helps to know a little more about how text input in a modern OS X application works. Developers can flag certain text fields for secure text input (e.g., password fields that don’t display what you type). The operating system won’t allow TextExpander to see what you type in those fields and therefore it could not feasibly suggest snippets based on that input. Applications such as 1Password and Safari (for properly written web forms) have no problem properly flagging secure text fields.

In other cases, it’s nearly impossible for OS X to know when secure text is being requested. Consider a terminal emulator like Terminal or iTerm 2, or a programmable text editor like Emacs. These applications can run arbitrary, cross-platform code that is not specifically written for OS X and hence does not flag secure text entry in the way that OS X recognizes. Consider logging in to a remote server via SSH on the command line. When you type your password in the terminal, unless your terminal emulator is in the list of excluded apps, TextExpander will take note that you typed a certain string, one that happens to be your password. If you do that often enough and you have snippet suggestion turned on, then your password becomes a suggested snippet. Therefore, one has to be careful to exclude all applications where passwords and other sensitive information might be entered but not marked as secure text. Primary examples are Terminal, iTerm 2, Emacs, and so on.

TextExpander Preferences: Applications to Exclude from Snippet Suggestion
TextExpander Preferences: Applications to Exclude from Snippet Suggestion

Suggested Snippet Storage and Synchronization

It turns out that suggestions are stored in plain text in an XML file in the TextExpander settings bundle (a directory called Settings.textexpandersettings). The file is named group_<uuid>.xml, where <uuid> is a long string of numbers and letters, and is associated with the “Suggested Snippets” group. Furthermore, if you have sync enabled (via Dropbox, iCloud, etc.) then these suggestions also sync in plain text. Because I have Dropbox sync enabled, the group_<uuid>.xml file is stored on Dropbox. As an example, in the Settings.textexpandersettings directory in my Dropbox account, I found the following entry in an XML file:


Notice this section in particular:


Indeed, rather than REDACTED the value of the plainText key was actually one my most important passwords–all 47-characters in full, plain text glory.

In retrospect, I should have been much more vigilant in many ways. I should have excluded any apps that might result in insecure text being added as a snippet. The terminal entry weakness wasn’t obvious to me at first though. It also wasn’t obvious to me that the suggested snippets were being synchronized across machines because there tend to be a large number of suggestions to filter through and, since I type similar things on multiple machines, some similarities across machines are to be expected.

While I still think the documentation on suggested snippets and privacy is incomplete and potentially misleading, here is a more thorough description of the behavior I received from Smile support:

The help text you cited refers to the tracking of keystrokes up to the point at which a suggestion is made. Once a suggestion is made, yes, it is stored in the settings in plain text. TextExpander remembers the suggestions it’s found for later, so as to not keep suggesting them again. The Help text may need clarification, but in essence it is exactly true. The log of all keystrokes (tracking) is discarded and only suggestions are kept.

Clean Up and Prevention

If this happened to you as well and you want to clean things up, try the following:

  1. Disable snippet suggestion in the TextExpander for any apps that might not flag all secure text entry by adding them to the list of excluded apps, as discussed above.

  2. Note the name of the XML file in your settings bundle corresponding to the “Suggested Snippets” group. You’ll need to find this file on the Dropbox website later. This step can be tricky since Finder hides the contents of the setting bundle by default.

    One option is to control-click the bundle in finder and click “Show package contents”. Then preview the group_<uuid>.xml files until you find the one containing <key>name</key> followed by <string>Suggested Snippets</string>.

    Another option, if you’re comfortable on the command line, is to cd to the Settings.textexpandersettings directory and grep for "Suggested Snippets" to find the right file. For example:

    cd ~/Dropbox/TextExpander/Settings.textexpandersettings
    grep "Suggested Snippets" group*.xml
  3. Turn off snippet suggestions in the TextExpander preferences and delete the Suggested Snippets group.

  4. The previous step should delete the corresponding XML file, but you’ll also want to remove the Dropbox version history for the file. On the Dropbox website, navigate to the settings bundle and click the trashcan icon to show deleted files. Command-click (or right click) the deleted XML file and click “Permanently delete”.

  5. Optionally, re-enable snippet suggestion.

Permanently Delete Files in Dropbox
Permanently Delete Files in Dropbox

Pasteboard Cleaning on OS X

August 19, 2015

A common problem on OS X is to paste plain text without the associated style information. Some apps have an item in the Edit menu called “Paste and Match Style”, but many don’t. It’s also inconvenient to have to use the menu for this. Ideally, one could use a keyboard shortcut just like ⌘V for pasting text with styling intact. Fortunately, there are several good options including a system-wide shortcut, a simple Keyboard Maestro macro and a a more complicated one, and even a dedicated app. As it happens, I already had an app installed with similar functionality: Paste is a clipboard history manager with an option to paste as plain text (⌘↩) or to remove formatting and styles from all copied text.

Some brief notes: The system-wide shortcut doesn’t work everywhere since some apps don’t have the “Paste and Match Style” menu item. If you already own Keyboard Maestro, then one of the two macros should serve you well. Otherwise, I’d suggest looking into either Get Plain Text or Paste. I’m using the latter and although it’s a little flashy for my taste it does get the job done when I need to find something I copied previously and, now, for stripping styles from things I copy.

Paste Preferences Window
Paste Preferences Window

Sending Events to Fantastical 2 from Emacs

August 16, 2015

Last week, I wrote a function for sending tasks to OmniFocus from Emacs. This involved creating and running short AppleScript snippet on the fly to communicate with OmniFocus. Once this basic structure is available, it’s fairly easy to connect with other applications. The next application on my list was Fantastical 2.

A Newly Parsed Calendar Event from Emacs
A Newly Parsed Calendar Event from Emacs

The send-region-to-fantastical function below takes first line of the region and sends it to Fantastical which opens the mini window (from the menu bar) and, using its natural language parsing, creates a new event which you can then review and add to your calendar. Any remaining lines in the region are added to the event as a note. Finally, it appends a note indicating that the task came from Emacs along with a timestamp.

Sending the Emacs Region to OmniFocus
Sending the Emacs Region to OmniFocus
(defun send-region-to-fantastical (beg end)
  "Send the selected region to Fantastical.
Parse the first line to create the event and use the second
and subsequent lines as the event note."
  (interactive "r")
  (let* ((region (buffer-substring-no-properties beg end))
         (match (string-match "^\\(.*\\)$" region))
         (event (substring region (match-beginning 1) (match-end 1)))
         (notes (if (< (match-end 0) (length region))
                   (concat (substring region (+ (match-end 0) 1) nil) "\n\n")
     (format "set theDate to current date
              set eventText to %s
              set eventNotes to %s
              set eventNotes to (eventNotes) & \"Added from Emacs on \" & (theDate as string)
              tell application \"Fantastical\"
                parse sentence (eventText) notes (eventNotes)
              end tell"
             (applescript-quote-string event)
             (applescript-quote-string notes)))))

I call send-region-to-fantastical by pressing C-c f via the following global keybinding:

(global-set-key (kbd "C-c f") 'send-region-to-fantastical)

Note that this function calls applescript-quote-string, which is a function originally from omnifocus-capture.el from a previous post. You can download both functions together here: fantastical-capture.el.

If you don’t have Fantastical 2 already, you can purchase the Mac, iPhone, and iPad versions here:

Sending Tasks to OmniFocus from Emacs

August 13, 2015

Wouldn’t it be great if you could take the current region in Emacs and use it to create a new task in OmniFocus? I thought so, and it turns out this problem has been solved at least three times before. However, I either had some trouble getting the previous solutions to work or wished they worked differently. For example omnifocus-capture.el by Ken Case defines a function which sends the region to OmniFocus’s quick entry window, but then you still have to trigger the quick entry keyboard shortcut to save the task to the OmniFocus Inbox (or elsewhere). That introduced too much friction for my taste, so I decided to write a different function based on Ken’s original one.

A Task from Emacs in Quick Entry Limbo
A Task from Emacs in Quick Entry Limbo

The communication between Emacs and OmniFocus needs to happen using AppleScript, so I first borrowed Ken’s applescript-quote-string function for properly escaping strings in AppleScript (with a couple of very minor modifications):

(defun applescript-quote-string (argument)
  "Quote a string for passing as a string to AppleScript."
  (if (or (not argument) (string-equal argument ""))
    ;; Quote using double quotes, but escape any existing quotes or
    ;; backslashes in the argument with backslashes.
    (let ((result "")
          (start 0)
        (if (or (null (string-match "[^\"\\]" argument))
                (< (match-end 0) (length argument)))
            (while (string-match "[\"\\]" argument start)
              (setq end (match-beginning 0)
                    result (concat result (substring argument start end)
                                   "\\" (substring argument end (1+ end)))
                    start (1+ end))))
        (concat "\"" result (substring argument start) "\"")))))

Then I defined a new send-region-to-omnifocus function. The most important difference for me is that the task is sent straight to the OmniFocus Inbox rather than sitting around in the quick entry window waiting to be entered. This is a personal preference of mine, since I tend to first “capture” tasks quickly and process them later, when I clean them up and assign projects and contexts.

An Inbox Task from Emacs with a Title
An Inbox Task from Emacs with a Title

The new function is also different in how it handles the contents of the region. It uses the first line of the region as the task name and any subsequent lines as the task note. It also appends both a note indicating that the task was added from Emacs and a timestamp. Finally, the new function is also a little more efficient. Ken’s original function created the AppleScript as a string, wrote it to a temporary file, and then ran the script in a shell using osascript. Instead, this version generates the AppleScript in a string and calls do-applescript directly (which perhaps did not exist when the original function was written).

Sending the Emacs Region to OmniFocus
Sending the Emacs Region to OmniFocus
(defun send-region-to-omnifocus (beg end)
  "Send the selected region to OmniFocus.
Use the first line of the region as the task name and the second
and subsequent lines as the task note."
  (interactive "r")
  (let* ((region (buffer-substring-no-properties beg end))
         (match (string-match "^\\(.*\\)$" region))
         (name (substring region (match-beginning 1) (match-end 1)))
         (note (if (< (match-end 0) (length region))
                   (concat (substring region (+ (match-end 0) 1) nil) "\n\n")
     (format "set theDate to current date
              set taskName to %s
              set taskNote to %s
              set taskNote to (taskNote) & \"Added from Emacs on \" & (theDate as string)
              tell front document of application \"OmniFocus\"
                make new inbox task with properties {name:(taskName), note:(taskNote)}
              end tell"
             (applescript-quote-string name)
             (applescript-quote-string note)))))

I call send-region-to-omnifocus by pressing C-c o via the following global keybinding:

(global-set-key (kbd "C-c o") 'send-region-to-omnifocus)

You can download both functions here: omnifocus-capture.el.

If you’ve read this far you probably have OmniFocus already. If not, you can purchase the Mac and iPhone/iPad versions at either of these locations:


  1. Sending text from Emacs to OmniFocus by Ken Case on the Omni Group Forums.
  2. Omnifocus Quick Entry from Emacs by Tim Prouty.
  3. omnifocus.el by Rob Bevan on GitHub.

MATH77 and mathc90 Libraries

July 21, 2015

NASA’s Jet Propulsion Laboratory (JPL) has released two large math libraries under an open source (BSD) license. Via Degenerate Conic:

MATH77 is a library of Fortran 77 subroutines implementing various numerical algorithms. It was developed over decades at JPL, and contains some very high-quality and time-tested code. The code is released under a BSD-type license. There is also a C version for people who love semicolons.

This goldmine includes basic mathematical functions, random number generators, linear algebra routines, solvers for systems of nonlinear equations, curve fitting, interpolation, and quadrature routines, and much more. The libraries are available at Netlib and are accompanied by 619 pages of detailed documentation.

(Emacs) Keyboard Shortcuts for Editing Text Fields in OS X

July 17, 2015

As is widely known, OS X has a collection of keyboard shortcuts involving the arrow keys for editing most text fields including web forms, input boxes, plain text documents, and so on. For example, ⌘← moves the cursor to the beginning of the current line.

Although they are hidden in plain sight, it seems less widely known that OS X also natively supports certain Emacs keyboard shortcuts in those same text areas. For example, to move to the beginning or end of the current line you can press ⌃A or ⌃E. To delete everything on the current line after the cursor use ⌃K. To transpose the characters on the left and right of the cursor, press ⌃T. To recenter the viewport on the current line, press ⌃L. Shortcuts like these can be faster than using ones involving the arrow keys, which requires moving ones fingers away from the home row of the keyboard.

The table below compares the Emacs keybindings with the OS X ones (the Emacs-like ones and more standard ones). For OS X shortcuts we use the usual symbols for the Command , Shift , Option , Control , Caps Lock , Delete , and Function Fn keys and write all letter keys in uppercase. Emacs keybindings are expressed in the usual notation for Control C, Meta (Alt) M, Shift S prefixes and the Delete DEL key and we write the letter keys in lowercase.

Emacs and OS X Keyboard Shortcuts Compared
Entity Direction Emacs OS X
Moving the cursor: move the cursor by character, word, line, etc.
char left C-b ⌃B
right C-f ⌃F
word left M-b ⌃⌥B ⌥←
right M-f ⌃⌥F ⌥→
line begin C-a ⌃A ⌘←
end C-e ⌃E ⌘→
up C-p ⌃P
down C-n ⌃N
doc begin M-< ⌘↑
end M-> ⌘↓
Selecting text: extend the selection1 by character, word, paragraph, and line
char left C-b ⌃⇧B ⇧←
right C-f ⌃⇧F ⇧→
word left M-b ⌃⌥⇧B ⌥⇧←
right M-f ⌃⌥⇧F ⌥⇧→
line begin C-a ⌃⇧A ⇧⌘←
end C-e ⌃⇧E ⇧⌘→
up C-p ⌃⇧P ⇧↑
down C-n ⌃⇧N ⇧↓
Deleting text: remove characters, words, and lines
char left C-h, DEL ⌃H
right C-d ⌃D
word left M-DEL ⌥⌫
right M-d Fn+⌥⌫
line backwards C–0 C-k ⌘⌫
forwards C-k ⌃K
Search: find text and move between search results
result first C-s ⌘F
next C-s ⌘G
previous C-r ⇧⌘G
Scrolling: move and recenter the viewport
page up M-v Fn+
down C-v ⌃V Fn+
recenter C-l ⌃L
Miscellaneous: other insertion, editing, and kill ring2 commands
char transpose C-t ⌃T
line insert C-o ⌃O
kill C-w ⌃K
yank C-y ⌃Y

See Also:

  1. To enter transient-mark-mode in Emacs, press C-SPC first.

  2. The kill ring is an Emacs concept, much like the OS X pasteboard (clipboard), but with a history that can be cycled. The OS X kill and yank commands here make use of a kill ring which is separate from the pasteboard and which can contain only a single element (i.e., no history).

Syntax highlighting for code blocks in Emacs Markdown Mode

July 13, 2015

Charl Botha on syntax highlighting in Markdown Mode:

When I’m editing my Markdown, I’d obviously like to see this language-specific highlighting interspersed with my normal Markdown highlighting. Sublime Text’s MarkdownEditing package does a superb job of this, but of course we’re currently rediscovering the universe that is Emacs.

DuckDuckGoing around, we run into at least two Emacs packages that do this: mmm-mode and polymode. We decided to try out both of them…

The simple and direct approach is to install mmm-mode and add something like this to your .emacs file, or equivalent:

(require 'mmm-mode)
(setq mmm-global-mode 'maybe)

    :submode lisp-mode
    :front "^```lisp[\n\r]+"
    :back "^```$")))

(mmm-add-mode-ext-class 'markdown-mode nil 'markdown-lisp)

This asks mmm-mode, when in markdown-mode, to highlight all GFM-style fenced ```lisp blocks using lisp-mode. However, I have Markdown documents with code blocks in many different languages and I didn’t want to clutter my .emacs file with similar blocks for each language. Instead, I automated the creation of these “classes” as follows:

(defun my-mmm-markdown-auto-class (lang &optional submode)
  "Define a mmm-mode class for LANG in `markdown-mode' using SUBMODE.
If SUBMODE is not provided, use `LANG-mode' by default."
  (let ((class (intern (concat "markdown-" lang)))
        (submode (or submode (intern (concat lang "-mode"))))
        (front (concat "^```" lang "[\n\r]+"))
        (back "^```"))
    (mmm-add-classes (list (list class :submode submode :front front :back back)))
    (mmm-add-mode-ext-class 'markdown-mode nil class)))

;; Mode names that derive directly from the language name
(mapc 'my-mmm-markdown-auto-class
      '("awk" "bibtex" "c" "cpp" "css" "html" "latex" "lisp" "makefile"
        "markdown" "python" "r" "ruby" "sql" "stata" "xml"))
Markdown Mode and MMM Mode in Action
Markdown Mode and MMM Mode in Action

The function defined above works for languages where the language name and Emacs mode name are directly related (e.g., bibtex and bibtex-mode). The call to mapc applies the function to each of the languages in the list that follows. Since there is an optional mode argument, other cases can be handled easily as needed:

;; Mode names that differ from the language name
(my-mmm-markdown-auto-class "fortran" 'f90-mode)
(my-mmm-markdown-auto-class "perl" 'cperl-mode)
(my-mmm-markdown-auto-class "shell" 'shell-script-mode)

By default mmm-mode doesn’t automatically re-parse the buffer when new code blocks are added. However, you can ask it to automatically re-parse the buffer when Emacs is idle. This works well in my experience:

(setq mmm-parse-when-idle 't)

If you prefer not to burn your idle cycles checking for buffers that need re-fontifying then you can issue M-x mmm-parse-buffer as needed or via a keybinding:

(global-set-key (kbd "C-c m") 'mmm-parse-buffer)

And yes, the code above does indeed define a markdown-markdown subclass for Markdown code blocks within Markdown documents. Look out!1

  1. Of course, I couldn’t resist trying to nest a GFM code block inside a Markdown code block inside a Markdown document and of course, things got weird.


Scripting and Compiling Swift on the Command Line • April 4, 2017
Examples of using Swift for shell scripts and compiling Swift code on the command line.
Using Markdown Mode: Switching and Toggling Markup • February 18, 2016
A note on advanced Markdown Mode usage for Emacs.
Preventing Emacs From Filling Up Your Clipboard History • February 9, 2016
Ways to delete rather than kill text in Emacs to keep your clipboard history clear.
On the Security Implications of Suggested Snippets in TextExpander • August 21, 2015
If not configured properly, TextExpander 5.x suggested snippets may be stored as plain text, may sync to the cloud, and may include passwords.
Pasteboard Cleaning on OS X • August 19, 2015
Brief summary of some methods for removing styles from copied text in OS X.
Sending Events to Fantastical 2 from Emacs • August 16, 2015
An Emacs Lisp function for sending the region to Fantastical 2 to parse as a new event.
Sending Tasks to OmniFocus from Emacs • August 13, 2015
An Emacs Lisp function for creating an OmniFocus task using the region.
MATH77 and mathc90 Libraries • July 21, 2015
Two large mathematical libraries, MATH77 and mathc90, go open source.
(Emacs) Keyboard Shortcuts for Editing Text Fields in OS X • July 17, 2015
A comparison of Emacs and OS X keyboard shortcuts for editing text.
Syntax highlighting for code blocks in Emacs Markdown Mode • July 13, 2015
A follow-up to Charl Botha's post on using mmm-mode for syntax highlighting of fenced code blocks in Markdown mode.
Intel Fortran Compilers Now Free for Students on All Platforms • July 1, 2015
The Intel Fortran compiler was previously free for non-commercial use on Linux only, but now OS X and Windows are also included.
Lossless Optimization of PNG Image File Sizes • June 29, 2015
Brief comparison of pngout and optipng, command-line utilities for lossless compression (optimization) of PNG image files.
Visualizing Color Codes with rainbow-mode for Emacs • June 26, 2015
rainbow-mode is a minor mode which changes the background color of text representing color codes in various forms.
Git Workflows on iOS with Working Copy • June 25, 2015
A comprehensive Git client for iPhone and iPad with support for iOS 8 share extensions and the iCloud document picker.
How to write a book in Emacs • June 24, 2015
An article on planning, writing, editing, and publishing a book in Emacs by Mickey Petersen.
k • June 23, 2015
Directory listings for zsh with git features.
Drafts Actions for OmniFocus and TextExpander • June 23, 2015
Links to Drafts actions for integration with OmniFocus and TextExpander on iOS.
Update to Bicubic Interpolation Code (TOMS 760) • June 21, 2015
Regarding a typo in the Fortran 90 translation of TOMS algorithm 760.
Integrating OS X and Emacs Dired • June 15, 2015
A keyboard shortcut for using OS X open in Dired.
Highlights: A New App for Annotating PDFs, with Two-Way Markdown Sync • June 10, 2015
Highlights is a new app that is a promising for academics with mostly digital workflows who work with PDF files and like to write in Markdown.
New GitHub Repositories • June 4, 2015
Both Deft and Markdown Mode for Emacs are now on GitHub.
Working with Large LaTeX Documents (in Emacs) • September 8, 2014
Some tricks for handling large files in Emacs.
Gnuplot Line Styles for Display and Printing • August 22, 2014
A simple way to see the available line styles for any Gnuplot terminal.
An Interface Issue in ELSUNC • August 14, 2014
A bug fix for Alan Miller's elsunc.f90.
Running Marked 2 from the Command Line • August 14, 2014
A replacement for the mark script from Marked version 1.
Reproducibility vs. Replication • October 5, 2013
Dave Giles recently reminded us of the distinction between replication and reproducibility.
Emacs F90 Mode Quick Reference Update • October 3, 2013
A substantial update to my f90-mode quick reference.
A Small Update to simann.f90 • October 2, 2013
I have applied a small patch to fix a bug in Alan Miller's simann.f90.
Software and Hardware Volume Settings • October 1, 2013
How to set software and hardware volume for best audio quality.
Box and Beard Plot • September 30, 2013
A play on the box and whiskers plot.
Polynomial Zeros in Quadruple Precision • February 28, 2013
An enhancement to Alan Miller's rpoly.f90.
Title Case in Emacs • February 9, 2013
An Emacs Lisp library for converting text to title case.
Semicolons • February 7, 2013
Mary Norris, writing for The New Yorker on semicolons, quotes a book titled Punctuation..?
MathML and Chrome: On Again, Off Again • February 6, 2013
MathML has been disabled again in Google Chrome.
Solid State Drive Hosting Services • February 5, 2013
A2 Hosting is now offering SSD hosting plans.
Emacs Help Functions • February 4, 2013
An overview of the Emacs help system.
Citing Forthcoming Articles with BibTeX • January 19, 2013
Using @Article entries in BibTeX for "forthcoming" or "in press" articles.
ReadKit • January 19, 2013
ReadKit is a simple Mac app for reading articles from Instapaper, Pocket, and Readability.
Source Code Pro by Adobe • January 14, 2013
A monospace typeface designed for programming, complementary to the Source Sans family.
A Markdown Previewer with MathML Support • January 4, 2013
Marked is a Markdown previewer for OS X which can load MathJax to support MathML in previews.
Securely Erasing a Full Terabyte • December 13, 2012
On securely erasing drives using wipe and monitoring drive health.
MathML is Coming to Google Chrome • October 26, 2012
MathML has been enabled in Google Chrome Canary.
Emacs Speaks Statistics (ESS) in MacPorts • August 28, 2012
A new MacPorts port for Emacs Speaks Statistics (ESS).
Installing OS X Lion on a Mac Mini Second Hard Drive • May 19, 2012
Adding a second hard drive to a mid 2011 Mac Mini and installing OS X Lion on it.
LaTeX on the iPad • March 29, 2012
A collection of apps and a remote compile server shell script to build a complete LaTeX editing, compiling, and viewing system.
Default Virtual Host in Apache • March 26, 2012
How to configure the default virtual host in Apache.
Markdown and Tutorial • February 24, 2012
Build a simple web app which serves Markdown content as HTML.
Price Return vs. Total Return • February 24, 2012
Financial tools should report total returns, not simply price returns.
iOS Alternatives to Google Reader • February 23, 2012
A survey of feed reading apps on iOS that work independently of Google Reader.
Locate via Spotlight on OS X • February 5, 2012
Using the Spotlight database to implement locate on OS X.
Lightweight Launchers for Linux • January 31, 2012
Verve command line for Xfce4 and Synapse launcher.
Google's New Privacy Policy • January 25, 2012
Wherein Google's new privacy policy induces me to leave.
Parallel gzip and bzip2 • November 9, 2011
Using parallel versions of gzip and bzip2 on Linux.
Printing Left-Justified Values in Fortran • July 31, 2011
Using internal writes to print left-justified strings and numerical values in Fortran.
Kindle DX Graphite Review • February 1, 2011
A review of the Kindle DX for reading PDF files for academic use.
Emacs F90 Mode Quick Reference • January 21, 2011
Commands and abbrevs for Fortran programming in Emacs.
Debugging Memory Issues with Valgrind • December 22, 2010
Example Fortran and C programs with exceeded array bounds and memory leaks.
Version Control in Scientific Computing • December 21, 2010
Using version control systems to enhance code clarity and ensure reproducibility of results.
Writing Efficient Code • December 19, 2010
Notes on writing efficient Fortran and C code in scientific applications.
Your Apps Are Watching You • December 18, 2010
A Wall Street Journal investigation of iPhone and Android apps.
The Uncertain Future of Delicious • December 17, 2010
Rumors circulated yesterday that Yahoo! would shut down Delicious.
Unlimited Polymorphic Data Structures in Fortran • March 20, 2010
Using unlimited polymorphic pointers to create generic data structures in Fortran.
Lightweight Markup Languages • March 16, 2010
A list of several lightweight markup languages.
Stack Overflows in Fortran • March 13, 2010
Some stack overflows can be avoided by allocating large automatic arrays on the heap.
Parsing Command-Line Options in Fortran 2003 • September 17, 2009
A simple example which makes use of Fortran 2003's new command-line interface.
SSH SOCKS Proxy Tunnel • August 29, 2009
Browse securely using the built-in SOCKS proxy support of OpenSSH.
Google Groups URLs • July 26, 2009
How to link to a Usenet message in Google Groups using the Message-ID.
The Fortran Wiki • April 29, 2009
Announcing the opening of the Fortran Wiki.
Dates and Times in SQLite • April 1, 2009
Notes on using SQLite, a lightweight relational database.
Markdown • March 29, 2009
Examples of Markdown syntax and an exhaustive collection of external links.
2009-03-11 • March 11, 2009
Parallel compilation with GNU Make.
2009-02-29 • February 28, 2009
2009-02-26 • February 26, 2009
Elastic tabstops
The Greek Alphabet in LaTeX • February 5, 2009
A page containing the Greek alphabet in LaTeX for reference.
Dynamic Abbreviation in Emacs • January 29, 2009
dabbrev-expand will change the way you write.
Parallel Computing in Fortran with OpenMP • January 27, 2009
A simple parallel Monte Carlo exercise for getting started with OpenMP in Fortran.
Void Pointers in Fortran with the Transfer Intrinsic • January 26, 2009
A method for emulating C's type casting using the transfer intrinsic.
Maximum Likelihood Estimation in R • January 5, 2009
An example of maximum likelihood estimation in R which estimates the parameters of an AR(1) process using simulated data.
Tools for Converting LaTeX to XML • December 10, 2008
A survey of available tools for converting LaTeX to XHTML+MathML or, more generally, LaTeX to XML.
2008-12-07 • December 7, 2008
Free software tools for converting LaTeX documents to XHTML+MathML.
Fortran Unit Testing with fUnit • December 6, 2008
A short guide to test-first development in Fortran using fUnit.
2008-12-01 • December 1, 2008
COIN-OR; Definr
2008-11-30 • November 30, 2008
Bazaar branch diff.
Packaging and Distribution of Fortran Libraries • November 25, 2008
Thoughts on best practices for packaging and distributing modern Fortran libraries.
xml-ping • November 24, 2008
A simple Perl script for sending XML-RPC pings to update services.
Fortran Language Definition for GNU Source-highlight • November 22, 2008
An updated Fortran language definition for syntax highlighting via Source-highlight.
Calculating the Log Sum of Exponentials • November 21, 2008
How to avoid numeric overflow when taking the log of a sum of exponentials.
Collected Markdown Makefile Wisdom • November 20, 2008
A summary of methods for building websites using Markdown and Make.
2008-11-17 • November 17, 2008
Managing Websites with Git • November 16, 2008
Using Git hooks to automatically rebuild websites after updates.
2008-11-16 • November 16, 2008
Screenshots from the command-line; tufte-latex; Bera Mono; zsh word separators
Emacs color-theme-less • November 16, 2008
A minimalistic color theme for Emacs.
chsh -s /usr/bin/zsh • November 16, 2008
Changing from bash to zsh.
Advanced Emacs • November 14, 2008
Advanced and lesser known editing functions of GNU Emacs
2008-11-14 • November 14, 2008
Literate programming links
LaTeX to MathML using itex2MML • November 4, 2008
Notes on LaTeX to XHTML+MathML conversion posted to the pandoc-discuss mailing list.
Debian OpenSSH Vulnerability • October 21, 2008
Some background on the Debian OpenSSH vulnerability and instructions on generating new SSH keys.
Double Free or Corruption Error • September 18, 2008
How to diagnose double free errors caused by invalid array indexing.
Efficient BibTeX • August 16, 2008
Suggestions for a more efficient BibTeX workflow.
LaTeX Tips • July 28, 2008
A collection of LaTeX tips and tricks.
A2 Hosting Ubuntu Virtual Private Server Guide • May 8, 2008
A complete guide to setting up a cheap Ubuntu VPS server at A2 Hosting.
A Simple Fortran Control File Example • May 6, 2008
A Fortran program to load a control file with line labels.
Git Colors • April 29, 2008
How to enable color output in Git.
2008-04-15 • April 15, 2008
How to be a good referee and demand-based parking rates in San Francisco.
Git • April 5, 2008
Distributed version control with Git.
2008-04-05 • April 5, 2008
Epiphany on WebKit, Debian MathML fonts, and newsbeuter.
2008-03-30 • March 30, 2008
LaTeX documents and version control.
Extensionless URIs in Movable Type 4 • March 30, 2008
Modifying archive mappings to support extensionless, future-proof URIs.
bmf: Bayesian Mail Filter • March 29, 2008
A simple efficient Bayesian mail filter
2008-03-29 • March 29, 2008, ext3grep, a Blosxom history lesson, and some Blosxom derivatives.
Linux Hostname Configuration • March 5, 2008
An attempt to clarify the process of properly setting hostnames in Linux.
MySQL to SQLite Migration • February 26, 2008
How to convert a MySQL database to SQLite.
Tips for Processing Large Datasets • February 26, 2008
Avoid reading entire files into memory or uncompressing large files.
Blosxom: Less is More • January 22, 2008
In it's elegant simplicity, Blosxom makes for an effective minimalist content management system capable of serving XHTML+MathML+SVG.
def predicate_p • January 19, 2008
A Python alternative to Ruby's question marked predicate functions.
Atom Feeds of Comments in Blosxom • January 16, 2008
Generate Atom feeds of recent comments in Blosxom simply by creating a new flavour and modifying the feedback plugin.
XHTML+MathML+SVG in Movable Type 4 • January 13, 2008
A short guide to serving XHTML+MathML+SVG content in Movable Type 4.
bzr-feed HOWTO • January 2, 2008
A short introduction to bzr-feed
bzr-feed Patch for Shared Repositories • December 19, 2007
A patch for bzr-feed to enable shared repository support.
LaTeX in Inkscape • December 10, 2007
Create vector graphics containing LaTeX equations using Inkscape.
Scientific Computing in Python • December 10, 2007
An overview of various Python packages for scientific computing.
Typesetting Algorithms in LaTeX • December 7, 2007
A couple of packages for typesetting algorithms in LaTeX.
Migrating from RCS to Bazaar • October 22, 2007
How to convert an RCS-managed project to a Bazaar repository.
In Rainbows • October 14, 2007
Radiohead have released their new album, “In Rainbows.”
Subprime Mortgage Worries • August 15, 2007
Subprime mortgage worries continue to spread fear in markets around the world. What is the problem and who is to blame?
EXT3 Undelete • August 9, 2007
How to recover deleted files from an ext3 partition in Linux.
PDF Forms in Linux • June 3, 2007
An update on the status of PDF form editing in Linux.
Setting Up a 32-bit chroot Environment in Ubuntu • May 30, 2007
Notes on setting up a chroot environment to run 32-bit programs in a 64-bit version of Ubutnu Linux.
Feed Upgrades • May 25, 2007
The site now emits valid Atom 1.0 and RSS 2.0 feeds.
Emacs Keybindings in Gnome • February 21, 2007
How to enable Emacs-style keyboard shortcuts in Gnome.
MathML • February 21, 2007
Notes on browser support for MathML.
Structured Procrastination • February 10, 2007
Rather than fight procrastination directly, harness it and channel it towards highly productive activities.
Rails Migrations and MySQL Types • February 8, 2007
A test to determine how the types defined in Rails migrations translate into MySQL types.
Using Legacy Primary Keys in Rails • February 5, 2007
Rails, primary keys, legacy databases
Beck - The Information • October 14, 2006
Beck - The Information (2006)
Soft Paternalism • April 8, 2006
Soft paternalism and the role of the state in directing personal behavior
Music and Audioscrobbler on the Linux Console • March 30, 2006
Using mpd, mpdscribble, and ncmpc on the Linux console
Securing sshd • March 25, 2006
Methods to increase the security of an sshd server.
Printing Even and Odd Pages of a PDF • March 9, 2006
Instructions for manual duplex printing of PDF files in Linux
nVidia MCP51 and ALSA • March 7, 2006
Instructions for using the nVidia MCP51 with the ALSA intel8x0 driver.
Blosxom Security Measures • March 2, 2006
Several basic measures that can be taken to secure a blosxom weblog.
Printing a Fortran Array with write • February 6, 2006
How to print an array on a single line in Fortran 77.
In Praise of Low-Fidelity • February 5, 2006
Advocating simplicity and efficiency.
Google Transit • January 16, 2006
Google Transit lets you plan a trip using public transit.
Fortran 77 • January 16, 2006
A few introductory Fortran 77 links.
Work for Your Coffee • January 13, 2006
Walk to the coffee shop for practical exercise.
Time Magazine: How to Tune Up Your Brain • January 13, 2006
A summary of a Time article about productivity and focus.
Converting PNG Scans to PDF • January 6, 2006
How to convert PNG images to PDF files using free tools in Linux.
Blosxom • January 6, 2006
Introductory post about the weblog software Blosxom.
Initializing an Array of Pointers to a Class • June 7, 2004
How to initialize a variable-sided array of class pointers.
ipw2100 mini-HOWTO • May 31, 2004
A short guide to install the Intel PRO/Wireless 2100 Driver for Linux.
GNU/Linux on the Sony Vaio PCG-V505DX • March 30, 2004
Notes on installing GNU/Linux on the Sony Vaio PCG-V505DX laptop.