Colored text in org-mode with export to HTML

| categories: orgmode, emacs | tags:

Just for fun, I want to put colored text in org-mode using links. This is a simple hack that uses the description in an org-mode link as the text to color, and the path in link to specify the color. I use an overlay to do this because I could not figure out how to change the face foreground color. We provide a simple export to HTML. LaTeX is also doable, but a trickier export as you need to define the colors in the LaTeX header also.

Here is the code to make the color link, and put overlays on them with font-lock.

(require 'ov)

(org-add-link-type
 "color"
 (lambda (path)
   "No follow action.")
 (lambda (color description backend)
   (cond
    ((eq backend 'html)
     (let ((rgb (assoc color color-name-rgb-alist))
           r g b)
       (if rgb
           (progn
             (setq r (* 255 (/ (nth 1 rgb) 65535.0))
                   g (* 255 (/ (nth 2 rgb) 65535.0))
                   b (* 255 (/ (nth 3 rgb) 65535.0)))
             (format "<span style=\"color: rgb(%s,%s,%s)\">%s</span>"
                     (truncate r) (truncate g) (truncate b)
                     (or description color)))
         (format "No Color RGB for %s" color)))))))

(defun next-color-link (limit)
  (when (re-search-forward
         "color:[a-zA-Z]\\{2,\\}" limit t)
    (forward-char -2)
    (let* ((next-link (org-element-context))
           color beg end post-blanks)
      (if next-link
          (progn
            (setq color (org-element-property :path next-link)
                  beg (org-element-property :begin next-link)
                  end (org-element-property :end next-link)
                  post-blanks (org-element-property :post-blank next-link))
            (set-match-data
             (list beg
                   (- end post-blanks)))
            (ov-clear beg end 'color)
            (ov beg
                (- end post-blanks)
             'color t
             'face
             `((:foreground ,color)))
            (goto-char end))
        (goto-char limit)
        nil))))

(font-lock-add-keywords
    nil
    '((next-color-link (0  'org-link t)))
    t)

I do not love the use of overlays on this, but it is the only way I could figure out how to do this without creating a face for every single color. Setting the foreground color property on the links did not work.

Now, we use a loop to generate a lot of colored links to check it out. It basically works. I see some overlays pop up in folded headlines sometimes, but I don't mind that too much. Emacs slows down when the screen is full of these links, but it seems fine under normal numbers of links. Since colors are likely to only be for accent, I do not think performance will be a problem. This might be a nice way to add accents to draw attention to some text in org-mode. If you like this, you might can get the code here: https://github.com/jkitchin/jmax/blob/master/org-colored-text.el

Here is what the text looks like in my buffer.

(loop for color in color-name-rgb-alist
      do
      (princ (format "[[color:%s][Text colored in %s]]\n" (car color) (car color))))

Text colored in snow Text colored in ghostwhite Text colored in whitesmoke Text colored in gainsboro Text colored in floralwhite Text colored in oldlace Text colored in linen Text colored in antiquewhite Text colored in papayawhip Text colored in blanchedalmond Text colored in bisque Text colored in peachpuff Text colored in navajowhite Text colored in moccasin Text colored in cornsilk Text colored in ivory Text colored in lemonchiffon Text colored in seashell Text colored in honeydew Text colored in mintcream Text colored in azure Text colored in aliceblue Text colored in lavender Text colored in lavenderblush Text colored in mistyrose Text colored in white Text colored in black Text colored in darkslategray Text colored in darkslategrey Text colored in dimgray Text colored in dimgrey Text colored in slategray Text colored in slategrey Text colored in lightslategray Text colored in lightslategrey Text colored in gray Text colored in grey Text colored in lightgrey Text colored in lightgray Text colored in midnightblue Text colored in navy Text colored in navyblue Text colored in cornflowerblue Text colored in darkslateblue Text colored in slateblue Text colored in mediumslateblue Text colored in lightslateblue Text colored in mediumblue Text colored in royalblue Text colored in blue Text colored in dodgerblue Text colored in deepskyblue Text colored in skyblue Text colored in lightskyblue Text colored in steelblue Text colored in lightsteelblue Text colored in lightblue Text colored in powderblue Text colored in paleturquoise Text colored in darkturquoise Text colored in mediumturquoise Text colored in turquoise Text colored in cyan Text colored in lightcyan Text colored in cadetblue Text colored in mediumaquamarine Text colored in aquamarine Text colored in darkgreen Text colored in darkolivegreen Text colored in darkseagreen Text colored in seagreen Text colored in mediumseagreen Text colored in lightseagreen Text colored in palegreen Text colored in springgreen Text colored in lawngreen Text colored in green Text colored in chartreuse Text colored in mediumspringgreen Text colored in greenyellow Text colored in limegreen Text colored in yellowgreen Text colored in forestgreen Text colored in olivedrab Text colored in darkkhaki Text colored in khaki Text colored in palegoldenrod Text colored in lightgoldenrodyellow Text colored in lightyellow Text colored in yellow Text colored in gold Text colored in lightgoldenrod Text colored in goldenrod Text colored in darkgoldenrod Text colored in rosybrown Text colored in indianred Text colored in saddlebrown Text colored in sienna Text colored in peru Text colored in burlywood Text colored in beige Text colored in wheat Text colored in sandybrown Text colored in tan Text colored in chocolate Text colored in firebrick Text colored in brown Text colored in darksalmon Text colored in salmon Text colored in lightsalmon Text colored in orange Text colored in darkorange Text colored in coral Text colored in lightcoral Text colored in tomato Text colored in orangered Text colored in red Text colored in hotpink Text colored in deeppink Text colored in pink Text colored in lightpink Text colored in palevioletred Text colored in maroon Text colored in mediumvioletred Text colored in violetred Text colored in magenta Text colored in violet Text colored in plum Text colored in orchid Text colored in mediumorchid Text colored in darkorchid Text colored in darkviolet Text colored in blueviolet Text colored in purple Text colored in mediumpurple Text colored in thistle Text colored in snow1 Text colored in snow2 Text colored in snow3 Text colored in snow4 Text colored in seashell1 Text colored in seashell2 Text colored in seashell3 Text colored in seashell4 Text colored in antiquewhite1 Text colored in antiquewhite2 Text colored in antiquewhite3 Text colored in antiquewhite4 Text colored in bisque1 Text colored in bisque2 Text colored in bisque3 Text colored in bisque4 Text colored in peachpuff1 Text colored in peachpuff2 Text colored in peachpuff3 Text colored in peachpuff4 Text colored in navajowhite1 Text colored in navajowhite2 Text colored in navajowhite3 Text colored in navajowhite4 Text colored in lemonchiffon1 Text colored in lemonchiffon2 Text colored in lemonchiffon3 Text colored in lemonchiffon4 Text colored in cornsilk1 Text colored in cornsilk2 Text colored in cornsilk3 Text colored in cornsilk4 Text colored in ivory1 Text colored in ivory2 Text colored in ivory3 Text colored in ivory4 Text colored in honeydew1 Text colored in honeydew2 Text colored in honeydew3 Text colored in honeydew4 Text colored in lavenderblush1 Text colored in lavenderblush2 Text colored in lavenderblush3 Text colored in lavenderblush4 Text colored in mistyrose1 Text colored in mistyrose2 Text colored in mistyrose3 Text colored in mistyrose4 Text colored in azure1 Text colored in azure2 Text colored in azure3 Text colored in azure4 Text colored in slateblue1 Text colored in slateblue2 Text colored in slateblue3 Text colored in slateblue4 Text colored in royalblue1 Text colored in royalblue2 Text colored in royalblue3 Text colored in royalblue4 Text colored in blue1 Text colored in blue2 Text colored in blue3 Text colored in blue4 Text colored in dodgerblue1 Text colored in dodgerblue2 Text colored in dodgerblue3 Text colored in dodgerblue4 Text colored in steelblue1 Text colored in steelblue2 Text colored in steelblue3 Text colored in steelblue4 Text colored in deepskyblue1 Text colored in deepskyblue2 Text colored in deepskyblue3 Text colored in deepskyblue4 Text colored in skyblue1 Text colored in skyblue2 Text colored in skyblue3 Text colored in skyblue4 Text colored in lightskyblue1 Text colored in lightskyblue2 Text colored in lightskyblue3 Text colored in lightskyblue4 Text colored in slategray1 Text colored in slategray2 Text colored in slategray3 Text colored in slategray4 Text colored in lightsteelblue1 Text colored in lightsteelblue2 Text colored in lightsteelblue3 Text colored in lightsteelblue4 Text colored in lightblue1 Text colored in lightblue2 Text colored in lightblue3 Text colored in lightblue4 Text colored in lightcyan1 Text colored in lightcyan2 Text colored in lightcyan3 Text colored in lightcyan4 Text colored in paleturquoise1 Text colored in paleturquoise2 Text colored in paleturquoise3 Text colored in paleturquoise4 Text colored in cadetblue1 Text colored in cadetblue2 Text colored in cadetblue3 Text colored in cadetblue4 Text colored in turquoise1 Text colored in turquoise2 Text colored in turquoise3 Text colored in turquoise4 Text colored in cyan1 Text colored in cyan2 Text colored in cyan3 Text colored in cyan4 Text colored in darkslategray1 Text colored in darkslategray2 Text colored in darkslategray3 Text colored in darkslategray4 Text colored in aquamarine1 Text colored in aquamarine2 Text colored in aquamarine3 Text colored in aquamarine4 Text colored in darkseagreen1 Text colored in darkseagreen2 Text colored in darkseagreen3 Text colored in darkseagreen4 Text colored in seagreen1 Text colored in seagreen2 Text colored in seagreen3 Text colored in seagreen4 Text colored in palegreen1 Text colored in palegreen2 Text colored in palegreen3 Text colored in palegreen4 Text colored in springgreen1 Text colored in springgreen2 Text colored in springgreen3 Text colored in springgreen4 Text colored in green1 Text colored in green2 Text colored in green3 Text colored in green4 Text colored in chartreuse1 Text colored in chartreuse2 Text colored in chartreuse3 Text colored in chartreuse4 Text colored in olivedrab1 Text colored in olivedrab2 Text colored in olivedrab3 Text colored in olivedrab4 Text colored in darkolivegreen1 Text colored in darkolivegreen2 Text colored in darkolivegreen3 Text colored in darkolivegreen4 Text colored in khaki1 Text colored in khaki2 Text colored in khaki3 Text colored in khaki4 Text colored in lightgoldenrod1 Text colored in lightgoldenrod2 Text colored in lightgoldenrod3 Text colored in lightgoldenrod4 Text colored in lightyellow1 Text colored in lightyellow2 Text colored in lightyellow3 Text colored in lightyellow4 Text colored in yellow1 Text colored in yellow2 Text colored in yellow3 Text colored in yellow4 Text colored in gold1 Text colored in gold2 Text colored in gold3 Text colored in gold4 Text colored in goldenrod1 Text colored in goldenrod2 Text colored in goldenrod3 Text colored in goldenrod4 Text colored in darkgoldenrod1 Text colored in darkgoldenrod2 Text colored in darkgoldenrod3 Text colored in darkgoldenrod4 Text colored in rosybrown1 Text colored in rosybrown2 Text colored in rosybrown3 Text colored in rosybrown4 Text colored in indianred1 Text colored in indianred2 Text colored in indianred3 Text colored in indianred4 Text colored in sienna1 Text colored in sienna2 Text colored in sienna3 Text colored in sienna4 Text colored in burlywood1 Text colored in burlywood2 Text colored in burlywood3 Text colored in burlywood4 Text colored in wheat1 Text colored in wheat2 Text colored in wheat3 Text colored in wheat4 Text colored in tan1 Text colored in tan2 Text colored in tan3 Text colored in tan4 Text colored in chocolate1 Text colored in chocolate2 Text colored in chocolate3 Text colored in chocolate4 Text colored in firebrick1 Text colored in firebrick2 Text colored in firebrick3 Text colored in firebrick4 Text colored in brown1 Text colored in brown2 Text colored in brown3 Text colored in brown4 Text colored in salmon1 Text colored in salmon2 Text colored in salmon3 Text colored in salmon4 Text colored in lightsalmon1 Text colored in lightsalmon2 Text colored in lightsalmon3 Text colored in lightsalmon4 Text colored in orange1 Text colored in orange2 Text colored in orange3 Text colored in orange4 Text colored in darkorange1 Text colored in darkorange2 Text colored in darkorange3 Text colored in darkorange4 Text colored in coral1 Text colored in coral2 Text colored in coral3 Text colored in coral4 Text colored in tomato1 Text colored in tomato2 Text colored in tomato3 Text colored in tomato4 Text colored in orangered1 Text colored in orangered2 Text colored in orangered3 Text colored in orangered4 Text colored in red1 Text colored in red2 Text colored in red3 Text colored in red4 Text colored in deeppink1 Text colored in deeppink2 Text colored in deeppink3 Text colored in deeppink4 Text colored in hotpink1 Text colored in hotpink2 Text colored in hotpink3 Text colored in hotpink4 Text colored in pink1 Text colored in pink2 Text colored in pink3 Text colored in pink4 Text colored in lightpink1 Text colored in lightpink2 Text colored in lightpink3 Text colored in lightpink4 Text colored in palevioletred1 Text colored in palevioletred2 Text colored in palevioletred3 Text colored in palevioletred4 Text colored in maroon1 Text colored in maroon2 Text colored in maroon3 Text colored in maroon4 Text colored in violetred1 Text colored in violetred2 Text colored in violetred3 Text colored in violetred4 Text colored in magenta1 Text colored in magenta2 Text colored in magenta3 Text colored in magenta4 Text colored in orchid1 Text colored in orchid2 Text colored in orchid3 Text colored in orchid4 Text colored in plum1 Text colored in plum2 Text colored in plum3 Text colored in plum4 Text colored in mediumorchid1 Text colored in mediumorchid2 Text colored in mediumorchid3 Text colored in mediumorchid4 Text colored in darkorchid1 Text colored in darkorchid2 Text colored in darkorchid3 Text colored in darkorchid4 Text colored in purple1 Text colored in purple2 Text colored in purple3 Text colored in purple4 Text colored in mediumpurple1 Text colored in mediumpurple2 Text colored in mediumpurple3 Text colored in mediumpurple4 Text colored in thistle1 Text colored in thistle2 Text colored in thistle3 Text colored in thistle4 Text colored in gray0 Text colored in grey0 Text colored in gray1 Text colored in grey1 Text colored in gray2 Text colored in grey2 Text colored in gray3 Text colored in grey3 Text colored in gray4 Text colored in grey4 Text colored in gray5 Text colored in grey5 Text colored in gray6 Text colored in grey6 Text colored in gray7 Text colored in grey7 Text colored in gray8 Text colored in grey8 Text colored in gray9 Text colored in grey9 Text colored in gray10 Text colored in grey10 Text colored in gray11 Text colored in grey11 Text colored in gray12 Text colored in grey12 Text colored in gray13 Text colored in grey13 Text colored in gray14 Text colored in grey14 Text colored in gray15 Text colored in grey15 Text colored in gray16 Text colored in grey16 Text colored in gray17 Text colored in grey17 Text colored in gray18 Text colored in grey18 Text colored in gray19 Text colored in grey19 Text colored in gray20 Text colored in grey20 Text colored in gray21 Text colored in grey21 Text colored in gray22 Text colored in grey22 Text colored in gray23 Text colored in grey23 Text colored in gray24 Text colored in grey24 Text colored in gray25 Text colored in grey25 Text colored in gray26 Text colored in grey26 Text colored in gray27 Text colored in grey27 Text colored in gray28 Text colored in grey28 Text colored in gray29 Text colored in grey29 Text colored in gray30 Text colored in grey30 Text colored in gray31 Text colored in grey31 Text colored in gray32 Text colored in grey32 Text colored in gray33 Text colored in grey33 Text colored in gray34 Text colored in grey34 Text colored in gray35 Text colored in grey35 Text colored in gray36 Text colored in grey36 Text colored in gray37 Text colored in grey37 Text colored in gray38 Text colored in grey38 Text colored in gray39 Text colored in grey39 Text colored in gray40 Text colored in grey40 Text colored in gray41 Text colored in grey41 Text colored in gray42 Text colored in grey42 Text colored in gray43 Text colored in grey43 Text colored in gray44 Text colored in grey44 Text colored in gray45 Text colored in grey45 Text colored in gray46 Text colored in grey46 Text colored in gray47 Text colored in grey47 Text colored in gray48 Text colored in grey48 Text colored in gray49 Text colored in grey49 Text colored in gray50 Text colored in grey50 Text colored in gray51 Text colored in grey51 Text colored in gray52 Text colored in grey52 Text colored in gray53 Text colored in grey53 Text colored in gray54 Text colored in grey54 Text colored in gray55 Text colored in grey55 Text colored in gray56 Text colored in grey56 Text colored in gray57 Text colored in grey57 Text colored in gray58 Text colored in grey58 Text colored in gray59 Text colored in grey59 Text colored in gray60 Text colored in grey60 Text colored in gray61 Text colored in grey61 Text colored in gray62 Text colored in grey62 Text colored in gray63 Text colored in grey63 Text colored in gray64 Text colored in grey64 Text colored in gray65 Text colored in grey65 Text colored in gray66 Text colored in grey66 Text colored in gray67 Text colored in grey67 Text colored in gray68 Text colored in grey68 Text colored in gray69 Text colored in grey69 Text colored in gray70 Text colored in grey70 Text colored in gray71 Text colored in grey71 Text colored in gray72 Text colored in grey72 Text colored in gray73 Text colored in grey73 Text colored in gray74 Text colored in grey74 Text colored in gray75 Text colored in grey75 Text colored in gray76 Text colored in grey76 Text colored in gray77 Text colored in grey77 Text colored in gray78 Text colored in grey78 Text colored in gray79 Text colored in grey79 Text colored in gray80 Text colored in grey80 Text colored in gray81 Text colored in grey81 Text colored in gray82 Text colored in grey82 Text colored in gray83 Text colored in grey83 Text colored in gray84 Text colored in grey84 Text colored in gray85 Text colored in grey85 Text colored in gray86 Text colored in grey86 Text colored in gray87 Text colored in grey87 Text colored in gray88 Text colored in grey88 Text colored in gray89 Text colored in grey89 Text colored in gray90 Text colored in grey90 Text colored in gray91 Text colored in grey91 Text colored in gray92 Text colored in grey92 Text colored in gray93 Text colored in grey93 Text colored in gray94 Text colored in grey94 Text colored in gray95 Text colored in grey95 Text colored in gray96 Text colored in grey96 Text colored in gray97 Text colored in grey97 Text colored in gray98 Text colored in grey98 Text colored in gray99 Text colored in grey99 Text colored in gray100 Text colored in grey100 Text colored in darkgrey Text colored in darkgray Text colored in darkblue Text colored in darkcyan Text colored in darkmagenta Text colored in darkred Text colored in lightgreen

Copyright (C) 2016 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.10

Discuss on Twitter

org-ref is on Melpa

| categories: orgmode, orgref, emacs | tags:

org-ref is out on Melpa !

Checkout this video (≈ 10 min.) of what it can do: https://www.youtube.com/watch?v=2t925KRBbFc

Here are the files that we used/generated:

  1. Emacs configuration: org-ref-melpa.el
  2. Here is the "manuscript" manuscript.org (note, I extracted the bibtex entries into this file)
  3. The resulting PDF: manuscript.pdf

Some killer new features:

  1. Drag-n-drop a PDF or url onto a bibtex file to add bibtex entries. This works when org-ref knows how to get a DOI from the PDF or url.
  2. Tooltips on cite links

Thanks everyone who has already tried it out and reported bugs!

Copyright (C) 2015 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.10

Discuss on Twitter

Introduction to a citation processor in org-ref

| categories: orgmode, citations, orgref, emacs | tags:

As a potential solution for citations in org-mode for non-LaTeX export, here we introduce csl (citation syntax lisp). The idea is heavily influenced by the xml-based Citation Syntax Language, but uses lisp sexps instead.

Briefly, there is a csl file that contains two variables: citation-style and bibliography-style. The citation-style defines how the in-text citations are represented for different types of citations. The bibliography-style defines how the bibliography is constructed.

What do we gain by this?

  1. No need for external citeproc program, and hackability by org-mode experts.
  2. Punctuation transposition and space chomping, i.e. put superscripts on the right side of punctuation if you want it, and remove whitespace before superscripts if you want it.
  3. Total tunability of the citation format to different backends.
  4. Easy to change bibliography format with the bibliographystyle link.
  5. The use of Bibtex databases. These are plain text, and flexible.

The real code for this is too long to blog about. Instead, you should check it out here: https://github.com/jkitchin/org-ref/tree/master/citeproc

1 Reference types

  • A book.1
  • An article2
  • A miscellaneous bibtex type.3

There is work to do in supporting other types of entry types that are common in bibtex files.

2 Citation types

  • Regular citation:2
  • citenum: See Ref. 2
  • citeauthor: Kitchin
  • citeyear: 2015

There is work to do in supporting other types of citations.

3 Multiple citations and sorting within citation

You can specify that the cites within a citation are consistently sorted in the export.

  • a,b:2,4
  • b,a:2,4

There is work to do for range collapsing, e.g. to turn 1,2,3 into 1-3.

4 Space chomping and punctuation testing

I think citations should always be put in the sentence they logically belong to. LaTeX has a feature through natbib I think where for some styles, e.g. superscripts, the citations are moved to the right side of punctuation, and whitespace is chomped so the superscript is next to words, not separated by spaces. We can do that here too.

  • Citation at end of sentence.2
  • Citation in clause,2,4 with a comma.
  • Citation in middle of2,4 a sentence.

5 Building

At the moment, you have to add a hook function to put the replacements in the document before parsing.

(add-to-list 'load-path ".")
(require 'org-ref-citeproc)

(when (file-exists-p "readme.html") (delete-file "readme.html"))
(let ((org-export-before-parsing-hook '(orcp-citeproc)))
  (browse-url (org-html-export-to-html)))
#<process open ./readme.html>
(add-hook 'org-export-before-parsing-hook 'orcp-citeproc)
orcp-citeproc

6 Summary thoughts

This looks promising. There is probably a lot of work to do to make this as robust as say citeproc-js or the Zotero handler. I am not sure if we could write this in a way to directly use the CSL. My feeling is it would not be as flexible as this, and we would have to add to it anyway.

Here are some remaining things that could be worked on if we continue this direction.

  1. Other bibtex entries need to be tested out.
  2. Remaining bibtex fields need to be defined.
  3. Standardization of styling that can be done. Not all features described in my csl are supported, e.g. et. al. and probably others.
  4. The author-year style needs name disambiguation somehow.
  5. Hyperlinking in html.
  6. Make sure export to other backends works.
  7. Can this work for notes-based styles?

7 Bibliography

You use a bibliographystyle link to specify a csl. These are similar to bibtex styles, and in some cases no change is needed for LaTeX export (although you may have to remove the citeproc hook function).

  1. Kittel, Charles, Introduction to Solid State Physics, (2005).
  2. Kitchin, John R., Examples of Effective Data Sharing in Scientific Publishing, ACS Catalysis, 5(6), pp. 3894-3899 (2015). https://doi.org/10.1021/acscatal.5b00538.
  3. Xu, Zhongnan; Rossmeisl, Jan and Kitchin, John R., Supporting data for: A linear response, {DFT+U} study of trends in the oxygen evolution activity of transition metal rutile dioxides. doi:10.5281/zenodo.12635, https://doi.org/https://zenodo.org/record/12635. https://doi.org/10.5281/zenodo.12635.
  4. Kitchin, John R., Data Sharing in Surface Science, Surface Science , N/A, pp. in press (2015). https://doi.org/10.1016/j.susc.2015.05.007.

Copyright (C) 2015 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.10

Discuss on Twitter

Post-processing an org-buffer on export

| categories: orgmode, emacs | tags:

In a previous post we examined getting tooltips on emacs keybindings and command syntax in an org-buffer. Someone asked in a comment if we could get that to export to html, or LaTeX. The short answer is not directly, org-mode doesn't recognize our functionalized syntax as an element, and there is no direct way to modify their appearance on export.

There is, however, a hook function that runs before parsing, and we can use that to transform these patterns to what we want. Here, I illustrate how to make the key-bindings and commands bold with a tooltip on them for an html export. Basically, we do an export, and then post-process the html output to put what we want in. I found this easier than pre-processing because the documentation for the command tooltip was too big to fit into an html snippet, and an html block causes carriage returns in the html. I didn't find a more elegant solution to that problem.

Here we replace the key-binding syntax with the actual keybinding in bold, and a tooltip of the command, and the command syntax we replace with bold command and a tooltip for the documentation. It works pretty well. The documentation for helm is pretty extensive, and gets cutoff in the tooltip. Otherwise, this seems pretty satisfactory.

This won't show in the blog post, so you will have to checkout the exported html here: blog.html .

Try \C-x C-f to open a file. You might enjoy using helm too. Or this variable org-agenda-files.

(require 'rx)

(defvar elisp-symbol-keybinding-re
  (rx
   ;; opening \\[
   (eval "\\[")
   ;; one or more characters that are not ]
   (group (one-or-more (not (any "]"))))
   ;; The closing ]
   "]")
"Regexp for an elisp command keybinding syntax. \\[some-command]
Regexp group 1 matches src_emacs-lisp[:results html]{(command-html "some-command")}.")

(defun org-process-key-bindings (backend)
  (goto-char (point-min))
  (while (re-search-forward elisp-symbol-keybinding-re nil t)
    (replace-match
     (cond
      ((eq backend 'html)
       (format "<b title=\"The command is %s.\">%s</b>"
               (match-string 1)
               (substitute-command-keys (match-string 0))))))))


(defun org-process-emacs-commands (backend)
  (goto-char (point-min))
  (while (re-search-forward "`\\([^']+\\)'" nil t)
    (replace-match
     (cond
      ((eq backend 'html)
       (format "<b title=\"%s\">%s</b>"
          (if (or (fboundp (intern (match-string 1)))
                  (boundp (intern (match-string 1))))
              (documentation (intern (match-string 1)))
            "No command found.")
          (match-string 1)))))))

(with-current-buffer (org-html-export-as-html)
  (org-process-key-bindings 'html)
  (org-process-emacs-commands 'html)
  (write-file "blog.html")
  (browse-url "blog.html"))
org-process-emacs-commands

1 Update: A filter approach to exporting

Our patterns are all in org-paragraphs. We can use a filter to modify the paragraph after it is "transcoded". Here is the filter function. It basically does the same thing, through another mechanism.

(defun my-paragraph-filter (data backend info)
  (cond
   ((eq 'html backend)
    ;; emacs commands
    (setq data (replace-regexp-in-string
                "`\\([^']+\\)'"
                (lambda (x)
                  (string-match "`\\([^']+\\)'" x)
                  (when (match-string 1 x)
                    (format "<b title=\"%s\">%s</b>"
                            (if (or (fboundp (intern (match-string 1 x)))
                                    (boundp (intern (match-string 1 x))))
                                (documentation (intern (match-string 1 x)))
                              "No command found.")
                            (match-string 1 x))))
                data))
    ;; keybindings
    (setq data (replace-regexp-in-string
                "\\\\\\[\\([^]]+\\)]"
                (lambda (x)
                  (string-match "\\\\\\[\\([^]]+\\)]" x)
                  (when (fboundp  (intern (match-string-no-properties 1 x)))
                    (format "<b title=\"The command is %s.\">%s</b>"
                            (match-string 1 x)
                            (substitute-command-keys (match-string 0 x)))))
                data)))))

(add-to-list 'org-export-filter-paragraph-functions 'my-paragraph-filter)
(browse-url (org-html-export-to-html))
#<process open ./blog.html>

Try the command org-ref to check your document for issues. Insert a citation with org-ref using \M-ESC C.

Now, this should show up in the blog!

Copyright (C) 2015 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.10

Discuss on Twitter

Contextual help in org-mode

| categories: orgmode, emacs | tags:

org-mode is great, plain text and all, but it can be difficult to figure out all the things you can do at any particular place in the buffer. Here, we explore some ideas on making org-mode a bit more discoverable. One way to do this that we explore here is to create a help function that you run, and it tells you about the element that `org-element-context' knows about, then gives you some hints of what you can do there. To do this, we create a series of functions for each kind of element we provide help on.

You may want to see the video: https://www.youtube.com/watch?v=99uxJWqZGzA

The kind of help we want is a description of the element, some commands we can run on the element and what they do, and if there are some key-bindings. We also want to make sure if the user has changed the key-bindings, the right values get shown. Finally, it would be nice to allow users to add their own documentation if they want.

So, here is the lengthy block of code we use for this purpose. We create a function for each element type that we provide documentation for. We also provide a mechanism for users to add their own notes for future reference. I leverage the help-buffer here to simplify some functional text, e.g. the key commands and clickable functions, as well as history navigation. I could also do most of that in org-mode buffers, with different functionality, but I save that for another day.

(defvar ore-user-directory "~/.emacs.d/ore/"
  "Directory to store user additions to the notes.")


(defun ore-user-documentation (type)
  "Return user documentation for org element TYPE if it exists.
Notes are returned as plain text, and will be rendered in `help-mode'."
  (let ((fname (expand-file-name (format "%s.org" type) ore-user-directory)))
    (concat
     "User documentation:\n"
     (if (file-exists-p fname)
         (with-temp-buffer
           (insert "\n")
           (insert-file-contents fname)
           (indent-rigidly (point-min) (point-max) 5)
           (buffer-string))
       "None defined.")
     (format  "\n\nEdit [[file:%s]]" fname))))


(defun ore-latex (element)
  "`ore' documentation for latex fragment."
  (concat
   (substitute-command-keys "You are on a LaTeX fragment or environment.

\\[org-toggle-latex-overlays] or `org-toggle-latex-overlays' to toggle LaTeX images on it.

")
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'latex)))


(defun ore-link (element)
  "`ore' documentation for org links."
  (let* ((link (org-element-context))
         (type (org-element-property :type link))
         (protocols (assoc type org-link-protocols))
         (follow-func (cadr protocols))
         (export-func (caddr protocols)))
    (concat
     (format
      (substitute-command-keys "You are on a %s link.

Link path: %s
%s

Clicking on the link will run `%s'.

This link uses this function for export: `%s'

If you are on an image link, you can toggle it with \\[org-toggle-inline-images] or `org-toggle-inline-images'.

You can toggle the link display with `org-toggle-link-display'.

See Info node `(org) Hyperlinks'.

%s

%s\n\n")
      type
      (org-element-property :path link)
      (format "Whole link: %s" (buffer-substring
                                (org-element-property :begin link)
                                (org-element-property :end link)))
      (pp-to-string follow-func)
      (pp-to-string export-func)
      (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
      (ore-user-documentation 'link)))))


(defun ore-src-block-header-p (element)
  "Return whether point is in a src-block header."
  (and (eq 'src-block (car element))
       (save-excursion
         (let ((cp (point))
               (lp (line-number-at-pos)))
           (goto-char (org-element-property :begin element))
           (= lp (line-number-at-pos))))))


(defun ore-src-block-header (element)
  "`ore' documentation for src-block header."
  (concat
   "You are in a src-block header.

This line tells org-mode that
it is a src-block, and language of the src-block. There are
also optional header arguments. See Info node `(org) Header arguments'

"
   (format "The default headers are described here: `org-babel-default-header-args:%s'

" (org-element-property :language element))
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'src-block-header)))


(defun ore-src-block (element)
  "`ore' documentation for a src-block."
  (concat
   (substitute-command-keys "You are in a src-block.

C-c C-c to execute this block.
\\[org-babel-tangle]  org-babel-tangle

You can edit the block with \\[org-edit-special] or `org-edit-special'.

See Info node `(org) Working with source code' for more details.\n\n")
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'src-block)))


(defun ore-headline (element)
  "`ore' documentation for a headline."
  (concat
   (when (bolp)
     (format  "You are at the beginning of a headline.

\\[org-cycle] to cycle Info node `(org) Global and local cycling'.

Check `org-use-speed-commands'\n\n"))

   ;; in a headline
   (substitute-command-keys
    "You are in a headline. You can change:

 Visibility with \\[org-cycle]

 TODO state \\[org-shiftleft] and \\[org-shiftright] or
 `org-todo'.

 Your current todo sets can be found in `org-todo-sets'.

 Priority \\[org-shiftup] (`org-priority-up') and
 \\[org-shiftdown] (`org-priority-down')

 Tags  \\[org-ctrl-c-ctrl-c] or `org-set-tags'

 Set a property with \\[org-set-property] `org-set-property'.

 Delete a property with \\[org-delete-property] or `org-delete-property'.

")
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'headline)))


;; timestamp
(defun ore-timestamp (element)
  "`ore' documentation for timestamps."
  (concat
   (substitute-command-keys "You are on a timestamp.

If you click on it, you will see the date in the agenda. With the
cursor on the <> or [] \\[org-shiftup] and \\[org-shiftdown] will
switch from active to inactive timestamps.

You can change the date by putting the cursor on a date part and
using \\[org-shiftup] and \\[org-shiftdown] or \\[org-shiftleft]
and \\[org-shiftright]

See Info node `(org) Dates and times'.

")
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'timestamp)))


;; table table-row table-cell
(defun ore-table (element)
  "`ore' documentation for tables."
  (concat
   "You are in a table.

Move cell to cell with [TAB]. When you are in the last cell, TAB adds a new row.

Move rows up and down with \\[org-metaup] and \\[org-metadown].
Move columns left and right with \\[org-metaleft] and \\[org-metaright].

Sort a column with \\[org-sort] `org-sort'.

Insert a row with `org-table-insert-row'.
Delete a row with `org-table-kill-row'.

Insert a column with `org-table-insert-column'.
Delete a column with `org-table-delete-column'.

`C-c -     (`org-table-insert-hline')'
     Insert a horizontal line below current row.  With a prefix
     argument, the line is created above the current line.

`C-c <RET>     (`org-table-hline-and-move')'
     Insert a horizontal line below current row, and move the cursor
     into the row below that line.

You can transpose a table with `org-table-transpose-table-at-point'.

Info node `(org) Tables'.

"
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'table)))


(defun ore-plain-list (element)
  "`ore' doucmentation for plain lists."
  (concat
   (substitute-command-keys
    "You are on a plain list.
See Info node `(org) Plain lists'.

")
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'plain-list)))


(defun ore-item (element)
  "`ore' documentation for items in a list"
  (concat
   (substitute-command-keys
    "You are on an item in a list.

You can move items up and down with \\[org-metaup] or `org-metaup' and \\[org-meta-down] or `org-metadown'.

You can add a new item with \\[org-meta-return] or `org-meta-return'.

You can change the indentation of an item with  \\[org-metaleft] or `org-metaleft' and \\[org-meta-right] or `org-meta-right'.

You can change the bullet of the item with  \\[org-shiftleft] or `org-shiftleft' and \\[org-shiftright] or `org-shiftright'.

See Info node `(org) Plain lists' for other things like sorting, cycling, checkboxes, etc...

")
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'item)))


(defun ore-keyword (element)
  "`ore' documentation for a keyword."
  (concat
   (substitute-command-keys
    "You are on a keyword.

You may need to run \\[org-ctrl-c-ctrl-c] or `org-ctrl-c-ctrl-c' to refresh its value if you change it.

You can move keywords up and down with \\[org-metaup] or `org-metaup' and \\[org-metadown] or `org-metadown'.

")
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'keyword)))


(defun ore-paragraph (element)
  "`ore' documentation for a paragraph."
  (concat
   (substitute-command-keys
    "You are in a paragraph.

You can move a paragraph up with \\[org-metaup] or `org-metaup'.

You can move a paragraph up with \\[org-metadown] or `org-metadown'.

You can mark the paragraph with `mark-paragraph'.


")
   (format  "\nClick for details on the face [[face:%s]]\n" (face-at-point))
   (ore-user-documentation 'paragraph)))


(defun ore ()
  "Help function for the org-mode element at point."
  (interactive)
  (with-help-window
      (help-buffer)
    (let* ((oeap (org-element-context))
           (ore-func (intern (format "ore-%s" (car oeap))))
           (s (if (fboundp ore-func)
                  (funcall ore-func oeap)
                (format
                 "No documentation found for %s.

%s"
                 (car oeap)
                 (ore-user-documentation (car oeap))))))
      ;; There are some special cases.
      (cond
       ((and  (eq 'src-block (car oeap))
              (ore-src-block-header-p oeap))
        (setq s (ore-src-block-header oeap)))

       ((or (eq 'table (car oeap))
            (eq 'table-row (car oeap))
            (eq 'table-cell (car oeap)))
        (setq s (ore-table oeap)))

       ((or (eq 'latex-fragment (car oeap))
            (eq 'latex-environment (car oeap)))
        (setq s (ore-latex oeap))))

      (princ s)
      (princ "\n\nHere is how org-mode sees the element.\n\n")
      (pp oeap))))


(defun match-next-ore-file (&optional limit)
  "Font-lock function to make file links clickable in help-mode."
  (when  (re-search-forward "\\[\\[file:\\([^]]*\\)\\]\\]" limit t)
    (let* ((fname (expand-file-name
                   (match-string 1)
                   ore-user-directory))
           (beg (match-beginning 0))
           (end (match-end 0))
           (find-func `(lambda ()
                         (interactive)
                         (find-file ,fname))))

      (add-text-properties
       beg
       end
       `(mouse-face
         highlight
         display "User documentation"
         local-map ,(let ((map (copy-keymap help-mode-map)))
                      (define-key map [mouse-1] find-func)
                      map)
         help-echo (format
                    "Click to edit User documentation.\n%s"
                    fname))))))

(defun match-next-ore-face (&optional limit)
  "Font-lock function to make face links clickable in help-mode."
  (when  (re-search-forward "\\[\\[face:\\([^]]*\\)\\]\\]" limit t)
    (let* ((face (match-string 1))
           (beg (match-beginning 0))
           (end (match-end 0))
           (func `(lambda ()
                    (interactive)
                    (describe-face ,face))))

      (add-text-properties
       beg
       end
       `(mouse-face
         highlight
         local-map ,(let ((map (copy-keymap help-mode-map)))
                      (define-key map [mouse-1] func)
                      map)
         display ,face
         help-echo (format
                    "Click to show face information.\n%s"
                    face))))))

(add-hook 'help-mode-hook
          (lambda ()
            (font-lock-add-keywords
             nil
             '((match-next-ore-file . font-lock-keyword-face)
               (match-next-ore-face . font-lock-keyword-face)))))


;; Let's add to the org menu for "Help at point"
(easy-menu-change
 '("Org")
 "Help"
 '(["Help at point" ore])
 "Show/Hide")

xu-suppor \(e^x\)

1 TODO elements

a b
3 4

list (plain/numbered)

  • add element
    • move elements (up/down indent/outdent)
  • item 1
  • item 2
  • item 3

checkbox

  • [ ] check it

org#External links

lizzit-2001-surfac-ru

\(latex_fragment\)

\(latex fragment\)

\begin{equation} 2-3 \end{equation}
(+ 3 4 5)
12

<2015-10-18 Sun> [2015-10-18 Sun]

Copyright (C) 2015 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.10

Discuss on Twitter
« Previous Page -- Next Page »