Htmlize your Erlang code buffer

by Ruslan Spivak on August 18, 2007

Recently I’ve begun to make blog posts and now want to have highlighting of Erlang’s code(actually any code , be it Python, Lisp, etc) in my posts. I’m using The One True Editor and it goes without saying that i want to convert my erlang code into html from within emacs to have corresponding syntax coloring. Htmlize package to the rescue!

After you downloaded package and put

(add-to-list 'load-path "path_to_your_htmlize.el")
(require 'htmlize)

into your dot emacs – you are ready to use it.

M-x htmlize-buffer or M-x htmlize-region will convert whole buffer or selected region with associated decorations into HTML( See C-h a htmlize RET for more functions). By default htmlize will make HTML output in css mode which is not very suitable for inserting into blog post as output includes also style sheets. Excerpt from htmlize documentation:

;; htmlize supports three types of HTML output, selected by setting
;; `htmlize-output-type': `css', `inline-css', and `font'.  In `css'
;; mode, htmlize uses cascading style sheets to specify colors; it
;; generates classes that correspond to Emacs faces and uses <span
;; class=FACE>...</span> to color parts of text.  In this mode, the
;; produced HTML is valid under the 4.01 strict DTD, as confirmed by
;; the W3C validator.  `inline-css' is like `css', except the CSS is
;; put directly in the STYLE attribute of the SPAN element, making it
;; possible to paste the generated HTML to other documents.  In `font'
;; mode, htmlize uses <font color="...">...</font> to colorize HTML,
;; which is not standard-compliant, but works better in older
;; browsers.  `css' mode is the default.

inline-css is the type of output i want. This can be achieved by customizing htmlize-output-type variable with M-x customize htmlize RET or directly modifying dot emacs. Converting:

(add-to-list 'load-path "path_to_your_htmlize.el")
(require 'htmlize)

with htmlize-region and then applying nxml-mode to produced result gives:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.34 in inline-css mode. -->
<html>
  <head>
    <title>.emacs</title>
  </head>
  <body style="color: #ffffff; background-color: #000000;">
    <pre>
(add-to-list 'load-path <span style="color: #ffa07a;">"path_to_your_htmlize.el"</span>)
(<span style="color: #00ffff;">require</span> '<span style="color: #7fffd4;">htmlize</span>)
</pre>
  </body>
</html>

As you see I need to cut contents between <pre> </pre> including
<pre> tags itself to insert that then directly into blog post. After that i need manually copy/paste styles from <body> tag into <pre> tag and also add font-size: 8pt to meet my taste. Being lazy i’ve implemented function my-htmlize-region in elisp to make that job for me every time i press F5 key:

(defun my-htmlize-region (beg end)
  "Htmlize region and put into <pre> tag style that is left in <body> tag
plus add font-size: 8pt"
  (interactive "r")
  (let* ((buffer-faces (htmlize-faces-in-buffer))
         (face-map (htmlize-make-face-map (adjoin 'default buffer-faces)))
         (pre-tag (format
                   "<pre style="%s font-size: 8pt">"
                   (mapconcat #'identity (htmlize-css-specs
                                          (gethash 'default face-map)) " ")))
         (htmlized-reg (htmlize-region-for-paste beg end)))
    (switch-to-buffer-other-window "*htmlized output*")
    ; clear buffer
    (kill-region (point-min) (point-max))
    ; set mode to have syntax highlighting
    (nxml-mode)
    (save-excursion
      (insert htmlized-reg))
    (while (re-search-forward "<pre>" nil t)
      (replace-match pre-tag nil nil))
    (goto-char (point-min))))

(global-set-key [(f5)] (lambda (beg end)
                         (interactive "r") (my-htmlize-region beg end)))

So now selecting:

(add-to-list 'load-path "path_to_your_htmlize.el")
(require 'htmlize)

and pressing F5 i get this in another buffer:

<pre style="color: #ffffff; background-color: #000000; font-size: 8pt">
(add-to-list 'load-path <span style="color: #ffa07a;">"path_to_your_htmlize.el"</span>)
(<span style="color: #00ffff;">require</span> '<span style="color: #7fffd4;">htmlize</span>)
</pre>

As you see it’s just what i want:
<pre> tags with content and <pre> tag contains style from above mentioned <body> tag plus font-size is added too.

Factorial in Erlang with syntax coloring as i have it in my Emacs:

-module(factorial).
-export([factorial/1, factorial_rec/1]).

%% tail recursion
factorial(Num) ->
    factorial(Num, 1).

factorial(1, Acc) -> Acc;
factorial(Num, Acc) ->
    factorial(Num-1, Num * Acc).

%% recursion
factorial_rec(1) -> 1;
factorial_rec(Num) ->
    Num * factorial_rec(Num-1).

This is a joy of using Emacs.

If you enjoyed this post why not subscribe via email or my RSS feed and get the latest updates immediately. You can also follow me on GitHub or Twitter.

{ 4 comments… read them below or add one }

Doug Hellmann August 20, 2007 at 9:51 PM

Thanks for the tip! Using htmlize is much easier than what I have been doing.

Reply

Ruslan Spivak August 22, 2007 at 9:23 AM

I’m using Wordpress blog engine + inline-css html output(i guess you do too) in Htmlize package and for me it works just fine, but your mileage may vary and i would take a look at html source code of your published page, maybe style attributes of your htmlized code were stripped off by your blog engine.

Reply

Shane Celis September 6, 2007 at 2:21 AM

Very cool stuff. I was hoping that htmlize-region-for-paste might do exactly what your function does. Unfortunately, it doesn’t. So I’m very glad to have your function, but it’d be nice if the code went upstream into htmlize.el. Have you considered submitting a patch to it?

Reply

Ruslan Spivak September 8, 2007 at 3:03 PM

Glad you liked the stuff, Shane and thanks for feedback. As for submitting a patch – no, i didn’t consider that (yet) as function contains some hardcoded stuff, like font-size and may not be well suited for including into htmlize.el in its current form.

Reply

Speak your mind

{ 6 trackbacks }

Previous post:

Next post: