Table of Contents
You customize rainbow-delimiters so that it is used with emacs lisp buffers at least.
(add-hook 'emacs-lisp-mode-hook 'rainbow-delimiters-mode)
and you write an org-mode buffer with an elisp src block (code block):
hello #+BEGIN_SRC elisp (((progn))) #+END_SRC
and you export the buffer to html by pressing
C-c C-e (bound to
org-export-dispatch). You expect to see the effect of rainbow-delimiters-mode in the resulting html file, but the html file doesn’t show rainbow delimiters.
2. one solution
This code will patch things up so that rainbow-delimiters-mode work with org html export feature and htmlize.
(eval-after-load 'htmlize '(progn ;; make htmlize to handle face name strings as well (defadvice htmlize-attrlist-to-fstruct (around my-make-it-accept-string activate) (if (stringp (ad-get-arg 0)) (progn (setq ad-return-value (htmlize-face-to-fstruct (intern (ad-get-arg 0))))) ad-do-it)))) (defvar my-htmlize-off-modes nil "list of minor modes to disable when using htmlize") (defun my-htmlize-before-hook-default () (dolist (mode my-htmlize-off-modes) (if (fboundp mode) (funcall mode 0))) (font-lock-fontify-buffer) (jit-lock-fontify-now) ;; copied from font-lock-default-function (make font-lock-face property act as alias for face property) (set (make-local-variable 'char-property-alias-alist) (copy-tree char-property-alias-alist)) (let ((elt (assq 'face char-property-alias-alist))) (if elt (unless (memq 'font-lock-face (cdr elt)) (setcdr elt (nconc (cdr elt) (list 'font-lock-face)))) (push (list 'face 'font-lock-face) char-property-alias-alist)))) (add-hook 'htmlize-before-hook 'my-htmlize-before-hook-default) ;; (add-to-list 'my-htmlize-off-modes 'rainbow-delimiters-mode)
This solution is dirty because it relies on a copy of part of undocumented internal details of font-lock-default-function.
This problem is caused by many bugs or non-bugs spread in many places, and it also turns out that htmlize provides a hook just right for patching things up:
There are many reasons why the current version 1.3.4 of rainbow-delimiters does not work with org export (org-mode version 8.0.7) and htmlize (20130207.2102).
One is that rainbow-delimiters-mode sets font-lock-face on buffer text using face name strings rather than face name symbols, and the current version of htmlize cannot work with face name strings. Older version of htmlize used to, and I don’t know why it’s changed. This is why when one calls htmlize-buffer on a rainbow-delimiters enabled elisp buffer, one will get an error like:
eq: Wrong type argument: listp, "rainbow-delimiters-depth-9-face"
Another reason is the use of
with-temp-buffer by htmlize and the org mode html export feature (implemented in
ox-html.el). Problem with
with-temp-buffer here is that it uses a temp buffer with name starting with a space, and
font-lock-mode avoids working with such temp buffers. Turning on
font-lock-mode on a normal buffer causes the value of
font-lock-function (which usually is
font-lock-default-function) to be called, and that doesn’t happen with temp buffers. What
font-lock-default-function does is it makes the text property
font-lock-face to act as an alias for the text property
face, and some other things.
Third reason is that
jit-lock-fontify-now is not getting called. There is a call to
htmlize.el and yet it’s not getting called. I don’t know why.
4. what official fixes might look like
htmlize should be changed to succeed to call
(jit-lock-fontify-now) and abandon the use of
with-temp-buffer. Speaking of htmlize, on a side note, it would be nice if htmlize could work with a face which is simply a list of face name symbols because that would solve a little problem with using fixed-with font in org-mode.
rainbow-delimiters should be changed to use face name symbols. On a side note, currently rainbow-delimiters rotates through 9 faces, it would be nice if it provides an option to rotate through less than 9 faces, and an option to make the top level paren special, that is, use one special face for the top level parens, and then start rotating with the rest of 8 faces for deeper parens. Maybe two options can be combined/generalized into one user option (which can be buffer local) by taking an idea from repeating decimal notation. Maybe I will come up with some code.
ox-html in the org package should abandon the use of
with-temp-buffer and provide its own official analog of
my-htmlize-off-modes so that users can use them to turn off rainbow-delimiters-mode or others on html export if they want to.
5. closing thoughts
Even if the bugs don’t get fixed, one can get by thanks to the hook variable
htmlize-before-hook, as seen here. The author of
htmlize doesn’t really have to implement a feature request such as “give us a user option to turn off some minor modes for htmlize” or a bug fix request such as “ensure a call to jit-lock-fontify-now” because
htmlize-before-hook can already take care of the two requests. When an Emacs package author decides to provide a hook, he is knowingly or unknowingly taking care of a lot of feature requests from the future. This is why hooks are great things.