Evaluate and Format Clojure in Emacs Markdown Buffers

When writing documentation or blog posts about Clojure code, it is very useful to be able to format Clojure code blocks using clojure-mode and evaluate code with nrepl.el.

This can be enabled using mmm-mode, which allows a single buffer to use different major modes for different sections of the buffer (and is not limited to just web modes). Install mmm-mode using M-x package-install mmm-mode, or using M-x el-get-install mmm-mode from the excellent el-get, or by checking the project from github and installing manually.

To configure this for clojure and markdown, add this in your init.el or .emacs file.

(require 'mmm-auto)
(mmm-add-classes
 '((markdown-clojure
    :submode clojure-mode
    :face mmm-declaration-submode-face
    :front "^```clj[\n\r]+"
    :back "^```$")))

(setq mmm-global-mode 'maybe)
(mmm-add-mode-ext-class 'markdown-mode nil 'markdown-clojure)

After evaluating the above, or restarting emacs, you can test multi-mode support by opening a markdown document, or creating a new one, and adding a clojure source block, e.g.:

(defn my-fn [x]
  (inc x))

(my-fn 1)

Inside the code block you can format and evaluate your code as in any clojure-mode buffer, and the code will display exactly as in a .clj file. By default the evaluation uses a running inferior lisp process, which you must start yourself. To use a running nrepl session instead, use M-x nrepl-interaction-mode inside the code block.

Using with AsciiDoc

This technique is not limited to clojure and markdown, but could be made to work whenever you would like differing major modes in distinct parts of your Emacs buffers. You can add class to mmm-mode appropriately, for as many major mode combinations as you need. The regions for each major mode are detected using regular expressions (or by some function).

For example, if you're writing asciidoc, you might use:

(mmm-add-classes
 '((asciidoc-clojure
    :submode clojure
    :face mmm-declaration-submode-face
    :front "\\[source, clojure\\][\n\r]+----[\n\r]+"
    :back "^----$")))
(mmm-add-mode-ext-class 'adoc-mode nil 'asciidoc-clojure)
(mmm-add-mode-ext-class 'doc-mode nil 'asciidoc-clojure)

Summary

mmm-mode allows you to flexibly use multiple major modes in different parts of a single emacs buffer. Here we have shown how to use it for clojure-mode code blocks in markdown or asciidoc, but it is in no way limited to this, and it allows some fine grained customisation to the appearance and behaviour of each major mode block. I'm sure you'll find your own uses for mmm-mode.

Discuss this post here.

Published: 2013-08-26

Snarf PGP Keys from Signed Messages in Emacs mu4e

I just moved to mu for reading my email. One feature I was missing was the ability to receive PGP keys for signed messages.

When you receive a signed message, mu shows the verification status in the Signature field in the message view (see MSGV-Crypto). If you don't have the sender's PGP key on your keyring, this will show unverified. Click on the Details link within field will show the sender's key id. To manually import the key you can use gpg:

$ gpg --recv <the-key-id>

This seemed a little labourious, so some automation was in order. mu4e allows you to define actions that can be run on messages (or attachments), so I just wrote an action to do this.

(defun mu4e-view-snarf-pgp-key (&optional msg)
  "Snarf the pgp key for the specified message."
  (interactive)
  (let* ((msg (or msg (mu4e-message-at-point)))
          (path (mu4e-message-field msg :path))
          (cmd (format "%s verify --verbose %s"
                 mu4e-mu-binary
                 (shell-quote-argument path)))
          (output (shell-command-to-string cmd)))
    (let ((case-fold-search nil))
      (when (string-match "key:\\([A-F0-9]+\\)" output)
        (let* ((cmd (format "%s --recv %s"
                            epg-gpg-program (match-string 1 output)))
               (output (shell-command-to-string cmd)))
          (message output))))))

This works by parsing the output of the mu program itself, as displayed in the Details window, to obtain the PGP key id. It then executes the gpg --recv command, parsing in the parsed key id.

To install the action, we simply add it to mu4e-view-actions:

(add-to-list 'mu4e-view-actions
             '("Snarf PGP keys" . mu4e-view-snarf-pgp-key) t)

Discuss this post here.

Published: 2013-08-25

Archive