Attaching code blocks to a pdf file during export

| categories: org-mode | tags:

This post is a further exploration of using the export filters to modify construction of content exported from org-mode. In this post we look at some code that will save all of the code-blocks in an org-buffer to systematically named files, and then attach the files to an exported pdf file. We will use the attachfileLaTeX package to attach the scripts. We will build off of this postfor the filters.

First, let us put in a gratuitous code block. In the rendered pdf, this script will be embedded in the pdf. I am not quite ready to build a filter that supports multiple backends, so in this post we just modify the latex export.

name = 'John'
print 'Hello {0}'.format(name)
Hello John

We are only going to attach the python code blocks in this example, and ignore all the other blocks. We will basically use the same kind strategy we have used before. We will initially parse the buffer to get a list of all the code blocks. Then we create a filter for the src-blocks that keeps a counter of src-blocks, and depending on the type of the nth src-block, we will save the file, and modify the text for that block. Here is our code for the list of code blocks.

(setq src-block-list 
      (org-element-map (org-element-parse-buffer) 'src-block 
        (lambda (src-block) src-block)))

Now we create the filter.

(defun ox-mrkup-filter-src-block (text back-end info)
  (catch 'return text)
  (let ((src-block (nth counter src-block-list)))
    (if (string= (org-element-property :language src-block) "python")
        (progn 
          (setq scriptname (format "py-%d.py" counter))
          ;; save code block
          (with-temp-buffer
            (insert (org-element-property :value src-block))
            (write-region (point-min) (point-max) scriptname ))
         
          (setq output (format "%s\n\\attachfile{%s} Double click me to open" text scriptname)))
      ;; else
      (setq output text)))
  ;; increment counter no matter what so next block is processed
  (setq counter (+ counter 1))
  ;; return output
  output)

Finally, we export the document to LaTeX, and run pdflatex on it to generate the pdf.

(let ((counter 0)
      ;; these packages are loaded in the latex file
      (org-latex-default-packages-alist 
       '(("utf8" "inputenc" nil)
         ("T1" "fontenc" nil)
         ("" "fixltx2e" nil)
         ("" "lmodern" nil)
         ("" "minted" nil) ;; for code syntax highlighting
         ;; customize how pdf links look
         ("linktocpage,
           pdfstartview=FitH,
           colorlinks,
           linkcolor=blue,
           anchorcolor=blue,
           citecolor=blue,
           filecolor=blue,
           menucolor=blue,
           urlcolor=blue" "hyperref" nil)))
      (org-export-filter-src-block-functions '(ox-mrkup-filter-src-block))
      (async nil)
      (subtreep nil)
      (visible-only nil)
      (body-only nil)
      (ext-plist '()))
  (org-latex-export-to-pdf async subtreep visible-only body-only ext-plist))

Check out the result: attaching-code-blocks-to-a-pdf.pdf. This text won't show up in the pdf. I had some difficulty including the link via org-links. The export engine wanted to embed it as a pdf in itself! That does not seem to work.

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

org-mode source

Discuss on Twitter