Exporting Org Mode Files… to Scheme?


Rewriting the Course in Scheme

Today I’m going to engage in a bizarre experiment: converting all of the Org Mode files that I wrote for my Guile Beginners course into Scheme files that can be used with the Skribilo document production tool.


  • Creating custom markup to automate certain tasks
  • Potentially easier to cross-reference and build indexes
  • Can customize the output of the course material per-iteration and per-participant
  • To have fun writing more Scheme!

I don’t know if I will stick with this approach, but I did want to give it a fair shot to see if it can speed up the process of developing and delivering educational material.

Here is the code we wrote:

(require 'ox)
(require 'ox-publish)

(defun org-skribe-bold (_bold contents _info)
  (format ",(bold [%s])" contents))

(defun org-skribe-italic (_italic contents _info)
  (format ",(emph [%s])" contents))

(defun org-skribe-code (code _contents info)
  (format ",(kbd [%s])" (org-element-property :value code)))

(defun org-skribe-verbatim (verbatim contents _info)
  (format ",(code [%s])"
          (org-element-property :value verbatim)))

(defun org-skribe-headline (headline contents info)
  (message "LEVEL IS %d" (org-export-get-relative-level headline info))
  (format "(section :title [%s]\n  %s)"
          (car (org-element-property :title headline))

;; (pcase (org-export-get-relative-level headline info)
;;   ((0) "section"))

(defun org-skribe-src-block (src-block _contents info)
  (let ((code (org-export-unravel-code src-block))
        (language (org-element-property :language src-block)))
    (pcase language
      ("scheme" (format "(scm [\n%s\n])" (car code)))
      (_ (format "(frame :width 50. (prog (source :language %s [%s])))"
                 (car code))))))

(defun org-skribe-link (link desc info)
  (format ",(ref :url %a :text %s)"
          (org-element-property :raw-link link)

(defun org-skribe-section (section contents info)

(defun org-skribe-paragraph (paragraph contents info)
  (format "(p [%s])" (string-trim-right contents)))

  '((bold . org-skribe-bold)
    ;;(center-block . org-skribe-center-block)
    ;;(clock . org-skribe-clock)
    (code . org-skribe-code)
    ;;(drawer . org-skribe-drawer)
    ;;(dynamic-block . org-skribe-dynamic-block)
    ;;(entity . org-skribe-entity)
    ;;(example-block . org-skribe-example-block)
    ;;(export-block . org-skribe-export-block)
    ;;(export-snippet . org-skribe-export-snippet)
    ;;(fixed-width . org-skribe-fixed-width)
    ;;(footnote-reference . org-skribe-footnote-reference)
    (headline . org-skribe-headline)
    ;; (horizontal-rule . org-skribe-horizontal-rule)
    ;; (inline-src-block . org-skribe-inline-src-block)
    ;; (inlinetask . org-skribe-inlinetask)
    ;; (inner-template . org-skribe-inner-template)
    (italic . org-skribe-italic)
    ;; (item . org-skribe-item)
    ;; (keyword . org-skribe-keyword)
    ;; (latex-environment . org-skribe-latex-environment)
    ;; (latex-fragment . org-skribe-latex-fragment)
    ;; (line-break . org-skribe-line-break)
    (link . org-skribe-link)
    ;; (node-property . org-skribe-node-property)
    (paragraph . org-skribe-paragraph)
    ;; (plain-list . org-skribe-plain-list)
    ;; (plain-text . org-skribe-plain-text)
    ;; (planning . org-skribe-planning)
    ;; (property-drawer . org-skribe-property-drawer)
    ;; (quote-block . org-skribe-quote-block)
    ;; (radio-target . org-skribe-radio-target)
    (section . org-skribe-section)
    ;; (special-block . org-skribe-special-block)
    (src-block . org-skribe-src-block)
    ;; (statistics-cookie . org-skribe-statistics-cookie)
    ;; (strike-through . org-skribe-strike-through)
    ;; (subscript . org-skribe-subscript)
    ;; (superscript . org-skribe-superscript)
    ;; (table . org-skribe-table)
    ;; (table-cell . org-skribe-table-cell)
    ;; (table-row . org-skribe-table-row)
    ;; (target . org-skribe-target)
    ;; (template . org-skribe-template)
    ;; (timestamp . org-skribe-timestamp)
    ;; (underline . org-skribe-underline)
    (verbatim . org-skribe-verbatim)
    ;; (verse-block . org-skribe-verse-block)

;; (setq org-publish-project-alist
;;       (list '("org-to-skb:main"
;;               :base-directory "./chapter-1"
;;               :base-extension "org"
;;               :publishing-directory "./skb-output"
;;               :publishing-function org-html-publish-to-html
;;               :with-title nil
;;               :with-timestamps nil)

(defun org-skribe-export-to-skb
    (&optional async subtreep visible-only body-only ext-plist)
  (let ((file (org-export-output-file-name ".skb" subtreep)))
    (org-export-to-file 'skribe file
      async subtreep visible-only body-only ext-plist)))
Subscribe to the System Crafters Newsletter!
Stay up to date with the latest System Crafters news and updates! Read the Newsletter page for more information.
Name (optional)
Email Address