summaryrefslogtreecommitdiff
path: root/.emacs.d/org-7.4/contrib/babel
diff options
context:
space:
mode:
Diffstat (limited to '.emacs.d/org-7.4/contrib/babel')
-rw-r--r--.emacs.d/org-7.4/contrib/babel/langs/ob-oz.el306
-rw-r--r--.emacs.d/org-7.4/contrib/babel/library-of-babel.org370
2 files changed, 676 insertions, 0 deletions
diff --git a/.emacs.d/org-7.4/contrib/babel/langs/ob-oz.el b/.emacs.d/org-7.4/contrib/babel/langs/ob-oz.el
new file mode 100644
index 0000000..e1e6e35
--- /dev/null
+++ b/.emacs.d/org-7.4/contrib/babel/langs/ob-oz.el
@@ -0,0 +1,306 @@
+;;; ob-oz.el --- org-babel functions for Oz evaluation
+
+;; Copyright (C) 2009 Torsten Anders and Eric Schulte
+
+;; Author: Torsten Anders and Eric Schulte
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+;; Version: 0.01
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating Oz source code.
+;;
+;; Oz code is always send to the Oz Programming Environment (OPI), the
+;; Emacs mode and compiler interface for Oz programs. Therefore, only
+;; session mode is supported. In practice, non-session code blocks are
+;; handled equally well by the session mode. However, only a single
+;; session is supported. Consequently, the :session header argument is
+;; ignored.
+;;
+;; The Org-babel header argument :results is interpreted as
+;; follows. :results output requires the respective code block to be
+;; an Oz statement and :results value requires an Oz
+;; expression. Currently, results are only supported for expressions
+;; (i.e. the result of :results output is always nil).
+;;
+;; Expression evaluation happens synchronously. Therefore there is an
+;; additional header argument :wait-time <number>, which specifies the
+;; maximum time to wait for the result of a given expression. nil
+;; means to wait as long as it takes to get a result (potentially wait
+;; forever).
+;;
+;; NOTE: Currently the copyright of this file may not be in a state to
+;; permit inclusion as core software into Emacs or Org-mode.
+
+;;; Requirements:
+
+;; - Mozart Programming System, the implementation of the Oz
+;; programming language (http://www.mozart-oz.org/), which includes
+;; the major mode mozart for editing Oz programs.
+;;
+;; - StartOzServer.oz which is located in the contrib/scripts
+;; directory of the Org-mode repository
+
+;;; TODO:
+
+;; - Decide: set communication to \\switch -threadedqueries?
+;;
+;; - Only start Oz compiler when required, e.g., load Org-babel only when needed?
+;;
+;; - Avoid synchronous evaluation to avoid blocking Emacs (complex
+;; Strasheela programs can take long to find a result..). In order
+;; to cleanly map code blocks to their associated results (which can
+;; arrive then in any order) I could use IDs
+;; (e.g. integers). However, how do I do concurrency in Emacs Lisp,
+;; and how can I define org-babel-execute:oz concurrently.
+;;
+;; - Expressions are rarely used in Oz at the top-level, and using
+;; them in documentation and Literate Programs will cause
+;; confusion. Idea: hide expression from reader and instead show
+;; them statement (e.g., MIDI output statement) and then include
+;; result in Org file. Implementation: for expressions (:results
+;; value) support an additional header argument that takes arbitrary
+;; Oz code. This code is not seen by the reader, but will be used
+;; for the actual expression at the end. Alternative: feed all
+;; relevant code as statement (:results output), then add expression
+;; as extra code block which outputs, e.g., file name (so the file
+;; name must be accessible by global var), but the code of this
+;; extra codeblock is not seen. Hm, in that case it might be even
+;; more easy to manually add this link to the Org file.
+;;
+
+
+(require 'ob)
+;;; major mode for editing Oz programs
+(require 'mozart)
+
+;;
+;; Interface to communicate with Oz.
+;; (1) For statements without any results: oz-send-string
+;; (2) For expressions with a single result: oz-send-string-expression
+;; (defined in org-babel-oz-ResultsValue.el)
+;;
+
+;; oz-send-string-expression implements an additional very direct
+;; communication between Org-babel and the Oz compiler. Communication
+;; with the Oz server works already without this code via the function
+;; oz-send-string from mozart.el.in, but this function does not get
+;; back any results from Oz to Emacs. The following code creates a
+;; socket for sending code to the OPI compiler and results are
+;; returned by the same socket. On the Oz side, a socket is opened and
+;; conected to the compiler of the OPI (via oz-send-string). On the
+;; Emacs side, a connection to this socket is created for feeding code
+;; and receiving results. This additional communication channel to the
+;; OPI compiler ensures that results are returned cleanly (e.g., only
+;; the result of the sent code is returned, no parsing or any
+;; processing of *Oz Emulator* is required).
+;;
+;; There is no buffer, nor sentinel involved. Oz code is send
+;; directly, and results from Oz are send back, but Emacs Lisp
+;; requires a filter function for processing results.
+
+(defvar org-babel-oz-server-dir
+ (file-name-as-directory
+ (expand-file-name
+ "scripts"
+ (file-name-as-directory
+ (expand-file-name
+ "../../.."
+ (file-name-directory (or load-file-name buffer-file-name))))))
+ "Path to the contrib/scripts directory in which
+StartOzServer.oz is located.")
+
+(defvar org-babel-oz-port 6001
+ "Port for communicating with Oz compiler.")
+(defvar org-babel-oz-OPI-socket nil
+ "Socket for communicating with OPI.")
+
+(defvar org-babel-oz-collected-result nil
+ "Aux var to hand result from org-babel-oz-filter to oz-send-string-expression.")
+(defun org-babel-oz-filter (proc string)
+ "Processes output from socket org-babel-oz-OPI-socket."
+;; (setq org-babel-oz-collected-results (cons string org-babel-oz-collected-results))
+ (setq org-babel-oz-collected-result string)
+ )
+
+
+(defun org-babel-oz-create-socket ()
+ (message "Create OPI socket for evaluating expressions")
+ ;; Start Oz directly
+ (run-oz)
+ ;; Create socket on Oz side (after Oz was started).
+ (oz-send-string (concat "\\insert '" org-babel-oz-server-dir "StartOzServer.oz'"))
+ ;; Wait until socket is created before connecting to it.
+ ;; Quick hack: wait 3 sec
+ ;;
+ ;; extending time to 30 secs does not help when starting Emacs for
+ ;; the first time (and computer does nothing else)
+ (sit-for 3)
+ ;; connect to OPI socket
+ (setq org-babel-oz-OPI-socket
+ ;; Creates a socket. I/O interface of Emacs sockets as for processes.
+ (open-network-stream "*Org-babel-OPI-socket*" nil "localhost" org-babel-oz-port))
+ ;; install filter
+ (set-process-filter org-babel-oz-OPI-socket #'org-babel-oz-filter)
+)
+
+;; communication with org-babel-oz-OPI-socket is asynchronous, but
+;; oz-send-string-expression turns is into synchronous...
+(defun oz-send-string-expression (string &optional wait-time)
+ "Similar to oz-send-string, oz-send-string-expression sends a string to the OPI compiler. However, string must be expression and this function returns the result of the expression (as string). oz-send-string-expression is synchronous, wait-time allows to specify a maximum wait time. After wait-time is over with no result, the function returns nil."
+ (if (not org-babel-oz-OPI-socket)
+ (org-babel-oz-create-socket))
+ (let ((polling-delay 0.1)
+ result)
+ (process-send-string org-babel-oz-OPI-socket string)
+ ;; wait for result
+ (if wait-time
+ (let ((waited 0))
+ (unwind-protect
+ (progn
+ (while
+ ;; stop loop if org-babel-oz-collected-result \= nil or waiting time is over
+ (not (or (not (equal org-babel-oz-collected-result nil))
+ (> waited wait-time)))
+ (progn
+ (sit-for polling-delay)
+;; (message "org-babel-oz: next polling iteration")
+ (setq waited (+ waited polling-delay))))
+;; (message "org-babel-oz: waiting over, got result or waiting timed out")
+;; (message (format "wait-time: %s, waited: %s" wait-time waited))
+ (setq result org-babel-oz-collected-result)
+ (setq org-babel-oz-collected-result nil))))
+ (unwind-protect
+ (progn
+ (while (equal org-babel-oz-collected-result nil)
+ (sit-for polling-delay))
+ (setq result org-babel-oz-collected-result)
+ (setq org-babel-oz-collected-result nil))))
+ result))
+
+(defun org-babel-expand-body:oz (body params &optional processed-params)
+ (let ((vars (second (or processed-params (org-babel-process-params params))))))
+ (if vars
+ ;; only add var declarations if any variables are there
+ (concat
+ ;; prepend code to define all arguments passed to the code block
+ "local\n"
+ (mapconcat
+ (lambda (pair)
+ (format "%s=%s"
+ (car pair)
+ (org-babel-oz-var-to-oz (cdr pair))))
+ vars "\n") "\n"
+ "in\n"
+ body
+ "end\n")
+ body))
+
+(defun org-babel-execute:oz (body params)
+ "Execute a block of Oz code with org-babel. This function is
+called by `org-babel-execute-src-block' via multiple-value-bind."
+ (let* ((processed-params (org-babel-process-params params))
+;; (session (org-babel-ruby-initiate-session (first processed-params)))
+ (vars (second processed-params))
+;; (result-params (third processed-params))
+ (result-type (fourth processed-params))
+ (full-body (org-babel-expand-body:oz body params processed-params))
+ (wait-time (plist-get params :wait-time))
+ ;; set the session if the session variable is non-nil
+;; (session-buffer (org-babel-oz-initiate-session session))
+;; (session (org-babel-prep-session:oz session params))
+ )
+ ;; actually execute the source-code block
+ (org-babel-reassemble-table
+ (case result-type
+ (output
+ (progn
+ (message "Org-babel: executing Oz statement")
+ (oz-send-string full-body)))
+ (value
+ (progn
+ (message "Org-babel: executing Oz expression")
+ (oz-send-string-expression full-body (if wait-time
+ wait-time
+ 1)))))
+ (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+ (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))))
+
+;; This function should be used to assign any variables in params in
+;; the context of the session environment.
+(defun org-babel-prep-session:oz (session params)
+ "Prepare SESSION according to the header arguments specified in PARAMS."
+ (error "org-babel-prep-session:oz unimplemented"))
+;; TODO: testing... (copied from org-babel-haskell.el)
+;; (defun org-babel-prep-session:oz (session params)
+;; "Prepare SESSION according to the header arguments specified in PARAMS."
+;; (save-window-excursion
+;; (org-babel-oz-initiate-session session)
+;; (let* ((vars (org-babel-ref-variables params))
+;; (var-lines (mapconcat ;; define any variables
+;; (lambda (pair)
+;; (format "%s=%s"
+;; (car pair)
+;; (org-babel-ruby-var-to-ruby (cdr pair))))
+;; vars "\n"))
+;; (vars-file (concat (make-temp-file "org-babel-oz-vars") ".oz")))
+;; (when vars
+;; (with-temp-buffer
+;; (insert var-lines) (write-file vars-file)
+;; (oz-mode)
+;; ;; (inferior-oz-load-file) ; ??
+;; ))
+;; (current-buffer))))
+;;
+
+
+;; TODO: testing... (simplified version of def in org-babel-prep-session:ocaml)
+;;
+;; BUG: does not work yet. Error: ad-Orig-error: buffer none doesn't exist or has no process
+;; UNUSED DEF
+(defun org-babel-oz-initiate-session (&optional session params)
+ "If there is not a current inferior-process-buffer in SESSION
+then create. Return the initialized session."
+ (unless (string= session "none")
+ ;; TODO: make it possible to have multiple sessions
+ (save-window-excursion
+ ;; (run-oz)
+ (get-buffer oz-compiler-buffer))))
+
+(defun org-babel-oz-var-to-oz (var)
+ "Convert an elisp var into a string of Oz source code
+specifying a var of the same value."
+ (if (listp var)
+;; (concat "[" (mapconcat #'org-babel-oz-var-to-oz var ", ") "]")
+ (eval var)
+ (format "%s" var) ; don't preserve string quotes.
+;; (format "%s" var)
+ ))
+
+;; TODO:
+(defun org-babel-oz-table-or-string (results)
+ "If the results look like a table, then convert them into an
+Emacs-lisp table, otherwise return the results as a string."
+ (error "org-babel-oz-table-or-string unimplemented"))
+
+
+(provide 'ob-oz)
+;;; org-babel-oz.el ends here
diff --git a/.emacs.d/org-7.4/contrib/babel/library-of-babel.org b/.emacs.d/org-7.4/contrib/babel/library-of-babel.org
new file mode 100644
index 0000000..abc15a9
--- /dev/null
+++ b/.emacs.d/org-7.4/contrib/babel/library-of-babel.org
@@ -0,0 +1,370 @@
+#+title: The Library of Babel
+#+author: Org-mode People
+#+STARTUP: odd hideblocks
+
+* Introduction
+ The Library of Babel is an extensible collection of ready-made and
+ easily-shortcut-callable source-code blocks for handling common
+ tasks. Org-babel comes pre-populated with the source-code blocks
+ located in this file. It is possible to add source-code blocks from
+ any org-mode file to the library by calling =(org-babel-lob-ingest
+ "path/to/file.org")=.
+
+ This file is included in worg mainly less for viewing through the
+ web interface, and more for contribution through the worg git
+ repository. If you have code snippets that you think others may
+ find useful please add them to this file and [[file:~/src/worg/worg-git.org::contribute-to-worg][contribute them]] to
+ worg.
+
+ The raw Org-mode text of this file can be downloaded at
+ [[repofile:contrib/babel/library-of-babel.org][library-of-babel.org]]
+
+* Simple
+A collection of simple utility functions
+
+#+srcname: echo
+#+begin_src emacs-lisp :var input="echo'd"
+ input
+#+end_src
+
+* File I/O
+** reading and writing files
+Read the contents of the file at =file=. The =:results vector= and
+=:results scalar= header arguments can be used to read the contents of
+file as either a table or a string.
+#+srcname: read
+#+begin_src emacs-lisp :var file="" :var format=""
+ (if (string= format "csv")
+ (with-temp-buffer
+ (org-table-import (expand-file-name file) nil)
+ (org-table-to-lisp))
+ (with-temp-buffer
+ (insert-file-contents (expand-file-name file))
+ (buffer-string)))
+#+end_src
+
+Write =data= to a file at =file=. If =data= is a list, then write it
+as a table in traditional Org-mode table syntax.
+#+srcname: write
+#+begin_src emacs-lisp :var data="" :var file="" :var ext='()
+ (flet ((echo (r) (if (stringp r) r (format "%S" r))))
+ (with-temp-file file
+ (case (and (listp data)
+ (or ext (intern (file-name-extension file))))
+ ('tsv (insert (orgtbl-to-tsv data '(:fmt echo))))
+ ('csv (insert (orgtbl-to-csv data '(:fmt echo))))
+ (t (org-babel-insert-result data)))))
+ nil
+#+end_src
+
+** remote files
+**** json
+Read local or remote file in [[http://www.json.org/][json]] format into emacs-lisp objects.
+#+srcname: json
+#+begin_src emacs-lisp :var file='() :var url='()
+ (require 'json)
+ (cond
+ (file
+ (with-temp-filebuffer file
+ (goto-char (point-min))
+ (json-read)))
+ (url
+ (require 'w3m)
+ (with-temp-buffer
+ (w3m-retrieve url)
+ (goto-char (point-min))
+ (json-read))))
+#+end_src
+
+**** Google docs
+The following code blocks make use of the [[http://code.google.com/p/googlecl/][googlecl]] Google command line
+tool. This tool provides functionality for accessing Google services
+from the command line, and the following code blocks use /googlecl/
+for reading from and writing to Google docs with Org-mode code blocks.
+
+****** read a document from Google docs
+The =google= command seems to be throwing "Moved Temporarily" errors
+when trying to download textual documents, but this is working fine
+for spreadsheets.
+#+source: gdoc-read
+#+begin_src emacs-lisp :var title="example" :var format="csv"
+ (let* ((file (concat title "." format))
+ (cmd (format "google docs get --format %S --title %S" format title)))
+ (message cmd) (message (shell-command-to-string cmd))
+ (prog1 (if (string= format "csv")
+ (with-temp-buffer
+ (org-table-import (shell-quote-argument file) '(4))
+ (org-table-to-lisp))
+ (with-temp-buffer
+ (insert-file-contents (shell-quote-argument file))
+ (buffer-string)))
+ (delete-file file)))
+#+end_src
+
+For example, a line like the following can be used to read the
+contents of a spreadsheet named =num-cells= into a table.
+: #+call: gdoc-read(title="num-cells"")
+
+A line like the following can be used to read the contents of a
+document as a string.
+: #+call: gdoc-read(title="loremi", :format "txt")
+
+****** write a document to a Google docs
+Write =data= to a google document named =title=. If =data= is tabular
+it will be saved to a spreadsheet, otherwise it will be saved as a
+normal document.
+#+source: gdoc-write
+#+begin_src emacs-lisp :var title="babel-upload" :var data=fibs(n=10) :results silent
+ (let* ((format (if (listp data) "csv" "txt"))
+ (tmp-file (make-temp-file "org-babel-google-doc" nil (concat "." format)))
+ (cmd (format "google docs upload --title %S %S" title tmp-file)))
+ (with-temp-file tmp-file
+ (insert
+ (if (listp data)
+ (orgtbl-to-csv
+ data '(:fmt (lambda (el) (if (stringp el) el (format "%S" el)))))
+ (if (stringp data) data (format "%S" data)))))
+ (message cmd)
+ (prog1 (shell-command-to-string cmd) (delete-file tmp-file)))
+#+end_src
+
+example usage
+: #+source: fibs
+: #+begin_src emacs-lisp :var n=8
+: (flet ((fib (m) (if (< m 2) 1 (+ (fib (- m 1)) (fib (- m 2))))))
+: (mapcar (lambda (el) (list el (fib el))) (number-sequence 0 (- n 1))))
+: #+end_src
+:
+: #+call: gdoc-write(title="fibs", data=fibs(n=10))
+
+* Plotting code
+
+** R
+ Plot column 2 (y axis) against column 1 (x axis). Columns 3 and beyond, if present, are ignored.
+
+#+srcname: R-plot(data=R-plot-example-data)
+#+begin_src R
+plot(data)
+#+end_src
+
+#+tblname: R-plot-example-data
+| 1 | 2 |
+| 2 | 4 |
+| 3 | 9 |
+| 4 | 16 |
+| 5 | 25 |
+
+#+lob: R-plot(data=R-plot-example-data)
+
+#+resname: R-plot(data=R-plot-example-data)
+: nil
+
+** Gnuplot
+
+* Org reference
+** headline references
+#+source: headline
+#+begin_src emacs-lisp :var headline=top :var file='()
+ (save-excursion
+ (when file (get-file-buffer file))
+ (org-open-link-from-string (org-make-link-string headline))
+ (save-restriction
+ (org-narrow-to-subtree)
+ (buffer-string)))
+#+end_src
+
+#+call: headline(headline="headline references")
+
+* Tables
+** LaTeX Table export
+*** booktabs
+This block can be used to wrap a table in the latex =booktabs=
+environment, it takes the following arguments -- all but the first two
+are optional.
+| arg | description |
+|-------+--------------------------------------------|
+| table | a reference to the table |
+| align | optional alignment string |
+| env | optional environment, default to "tabular" |
+| width | optional width specification string |
+
+#+srcname: booktabs
+#+begin_src emacs-lisp :var table='((:head) hline (:body)) :var align='() :var env="tabular" :var width='() :noweb yes :results latex
+ (flet ((to-tab (tab)
+ (orgtbl-to-generic
+ (mapcar (lambda (lis)
+ (if (listp lis)
+ (mapcar (lambda (el)
+ (if (stringp el)
+ el
+ (format "%S" el))) lis)
+ lis)) tab)
+ (list :lend " \\\\" :sep " & " :hline "\\hline"))))
+ (org-fill-template
+ "
+ \\begin{%env}%width%align
+ \\toprule
+ %table
+ \\bottomrule
+ \\end{%env}\n"
+ (list
+ (cons "env" (or env "table"))
+ (cons "width" (if width (format "{%s}" width) ""))
+ (cons "align" (if align (format "{%s}" align) ""))
+ (cons "table"
+ ;; only use \midrule if it looks like there are column headers
+ (if (equal 'hline (second table))
+ (concat (to-tab (list (first table)))
+ "\n\\midrule\n"
+ (to-tab (cddr table)))
+ (to-tab table))))))
+#+end_src
+
+*** longtable
+This block can be used to wrap a table in the latex =longtable=
+environment, it takes the following arguments -- all but the first two
+are optional.
+| arg | description |
+|-----------+-------------------------------------------------------------|
+| table | a reference to the table |
+| align | optional alignment string |
+| width | optional width specification string |
+| hline | the string to use as hline separator, defaults to "\\hline" |
+| head | optional "head" string |
+| firsthead | optional "firsthead" string |
+| foot | optional "foot" string |
+| lastfoot | optional "lastfoot" string |
+
+#+srcname: longtable
+#+begin_src emacs-lisp :var table='((:table)) :var align='() :var width='() :var hline="\\hline" :var firsthead='() :var head='() :var foot='() :var lastfoot='() :noweb yes :results latex
+ (org-fill-template
+ "
+ \\begin{longtable}%width%align
+ %firsthead
+ %head
+ %foot
+ %lastfoot
+
+ %table
+ \\end{longtable}\n"
+ (list
+ (cons "width" (if width (format "{%s}" width) ""))
+ (cons "align" (if align (format "{%s}" align) ""))
+ (cons "firsthead" (if firsthead (concat firsthead "\n\\endfirsthead\n") ""))
+ (cons "head" (if head (concat head "\n\\endhead\n") ""))
+ (cons "foot" (if foot (concat foot "\n\\endfoot\n") ""))
+ (cons "lastfoot" (if lastfoot (concat lastfoot "\n\\endlastfoot\n") ""))
+ (cons "table" (orgtbl-to-generic
+ (mapcar (lambda (lis)
+ (if (listp lis)
+ (mapcar (lambda (el)
+ (if (stringp el)
+ el
+ (format "%S" el))) lis)
+ lis)) table)
+ (list :lend " \\\\" :sep " & " :hline hline)))))
+#+end_src
+
+** Elegant lisp for transposing a matrix.
+
+#+tblname: transpose-example
+| 1 | 2 | 3 |
+| 4 | 5 | 6 |
+
+#+srcname: transpose
+#+begin_src emacs-lisp :var table=transpose-example
+ (apply #'mapcar* #'list table)
+#+end_src
+
+#+resname:
+| 1 | 4 |
+| 2 | 5 |
+| 3 | 6 |
+
+* Misc
+#+srcname: python-identity(a=1)
+#+begin_src python
+a
+#+end_src
+#+srcname: python-add(a=1, b=2)
+#+begin_src python
+a + b
+#+end_src
+* GANTT Charts
+
+The =elispgantt= source block was sent to the mailing list by Eric
+Fraga. It was modified slightly by Tom Dye.
+
+#+source: elispgantt
+#+begin_src emacs-lisp :var table=gantttest
+ (let ((dates "")
+ (entries (nthcdr 2 table))
+ (milestones "")
+ (nmilestones 0)
+ (ntasks 0)
+ (projecttime 0)
+ (tasks "")
+ (xlength 1))
+ (message "Initial: %s\n" table)
+ (message "Entries: %s\n" entries)
+ (while entries
+ (let ((entry (first entries)))
+ (if (listp entry)
+ (let ((id (first entry))
+ (type (nth 1 entry))
+ (label (nth 2 entry))
+ (task (nth 3 entry))
+ (dependencies (nth 4 entry))
+ (start (nth 5 entry))
+ (duration (nth 6 entry))
+ (end (nth 7 entry))
+ (alignment (nth 8 entry)))
+ (if (> start projecttime) (setq projecttime start))
+ (if (string= type "task")
+ (let ((end (+ start duration))
+ (textposition (+ start (/ duration 2)))
+ (flush ""))
+ (if (string= alignment "left")
+ (progn
+ (setq textposition start)
+ (setq flush "[left]"))
+ (if (string= alignment "right")
+ (progn
+ (setq textposition end)
+ (setq flush "[right]"))))
+ (setq tasks
+ (format "%s \\gantttask{%s}{%s}{%d}{%d}{%d}{%s}\n"
+ tasks label task start end textposition flush))
+ (setq ntasks (+ 1 ntasks))
+ (if (> end projecttime)
+ (setq projecttime end)))
+ (if (string= type "milestone")
+ (progn
+ (setq milestones
+ (format
+ "%s \\ganttmilestone{$\\begin{array}{c}\\mbox{%s}\\\\ \\mbox{%s}\\end{array}$}{%d}\n"
+ milestones label task start))
+ (setq nmilestones (+ 1 nmilestones)))
+ (if (string= type "date")
+ (setq dates (format "%s \\ganttdateline{%s}{%d}\n"
+ dates label start))
+ (message "Ignoring entry with type %s\n" type)))))
+ (message "Ignoring non-list entry %s\n" entry)) ; end if list entry
+ (setq entries (cdr entries)))) ; end while entries left
+ (format "\\pgfdeclarelayer{background}
+ \\pgfdeclarelayer{foreground}
+ \\pgfsetlayers{background,foreground}
+ \\renewcommand{\\ganttprojecttime}{%d}
+ \\renewcommand{\\ganttntasks}{%d}
+ \\noindent
+ \\begin{tikzpicture}[y=-0.75cm,x=0.75\\textwidth]
+ \\begin{pgfonlayer}{background}
+ \\draw[very thin, red!10!white] (0,1+\\ganttntasks) grid [ystep=0.75cm,xstep=1/\\ganttprojecttime] (1,0);
+ \\draw[\\ganttdatelinecolour] (0,0) -- (1,0);
+ \\draw[\\ganttdatelinecolour] (0,1+\\ganttntasks) -- (1,1+\\ganttntasks);
+ \\end{pgfonlayer}
+ %s
+ %s
+ %s
+ \\end{tikzpicture}" projecttime ntasks tasks milestones dates))
+#+end_src