;;; ob-ditaa.el --- Babel Functions for ditaa -*- lexical-binding: t; -*- ;; Copyright (C) 2009-2024 Free Software Foundation, Inc. ;; Authors: Eric Schulte, Jarmo Hurri ;; Keywords: literate programming, reproducible research ;; URL: https://orgmode.org ;; This file is part of GNU Emacs. ;; GNU Emacs 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 of the License, or ;; (at your option) any later version. ;; GNU Emacs 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. If not, see . ;;; Commentary: ;; Org-Babel support for evaluating ditaa source code. ;; ;; Source code blocks of type ditaa have some special features: ;; ;; - there is no such thing as a "session" ;; ;; - there is no "output", so source code blocks always export "results" ;; ;; - only results of type "file" are returned ;; ;; - there are no variables ;; ;; - output file type is deduced from result file suffix by default, ;; but can be overwritten; if no type is specified and none can be ;; deduced, the default is png ;; ;; - three different variants of "ditaa" exist: a ditaa executable ;; (shell script), ditaa.jar Java archive and DitaaEPS.jar Java ;; archive; the third one is a fork generating eps output, and is ;; also a prerequisite for producing pdf output; ob-ditaa supports ;; all three of these; if ditaa.jar or DitaaEPS.jar is used, paths ;; to file(s) must be set; the following table summarizes which ;; variant is used in which case; column mode refers to ;; `org-ditaa-default-exec-mode' ;; ;; | mode | output | command | ;; |----------------+----------+-----------------------------------------------------| ;; | `ditaa' | png, svg | `org-ditaa-exec' | ;; | `jar' | png, svg | `org-ditaa-java-exec' -jar `org-ditaa-jar-path' | ;; | `ditaa', `jar' | eps | `org-ditaa-java-exec' -jar `org-ditaa-eps-jar-path' | ;; | `ditaa', `jar' | pdf | `org-ditaa-java-exec' -jar `org-ditaa-eps-jar-path' | ;; ;; - the following header arguments are added: ;; "file" : path to generated result file ;; "png" : toggle for generating png file (default) ;; "svg" : toggle for generating svg file (requires ditaa version >= 0.11.0) ;; "eps" : toggle for generating eps file (requires org-ditaa-eps-jar-path) ;; "pdf" : toggle for generating pdf file (requires org-ditaa-eps-jar-path and epstopdf) ;; "cmdline" : command line parameters passed to ditaa ;; "encoding" : character encoding (default UTF-8) ;; "java" : additional parameters passed to java if ditaa run via a jar ;; ;;; Requirements: ;; at least one of the following: ;; ;; ditaa (executable) ;; - packaged in some distributions ;; - configurable via `org-ditaa-exec' ;; ;; ditaa.jar | when exec mode is `jar' ;; - `org-ditaa-jar-path' must point to this jar file ;; - see https://github.com/stathissideris/ditaa ;; ;; DitaaEps.jar | when generating eps or pdf output ;; - `org-ditaa-eps-jar-path' must point to this jar file ;; - see https://sourceforge.net/projects/ditaa-addons/files/DitaaEps/ ;;; Code: (require 'org-macs) (org-assert-version) (require 'ob) (require 'org-compat) (defvar org-babel-default-header-args:ditaa '((:results . "file") (:exports . "results") (:encoding . "UTF-8")) "Default arguments for evaluating a ditaa source block.") (defcustom org-ditaa-default-exec-mode 'jar "Method to use for ditaa diagram generation when generating png or svg output. `jar' means to use java together with a JAR. The JAR must be set via `org-ditaa-jar-path'. `ditaa' means to use the ditaa executable. The executable can be configured via `org-ditaa-exec'." :group 'org-babel :package-version '(Org . "9.8") :type 'symbol :options '(ditaa jar)) (defcustom org-ditaa-exec "ditaa" "File name of the ditaa executable." :group 'org-babel :package-version '(Org . "9.8") :type 'string) (defcustom org-ditaa-java-exec "java" "Java executable to use when evaluating ditaa blocks using a JAR." :group 'org-babel :type 'string) (defcustom org-ditaa-jar-path (expand-file-name "ditaa.jar" (file-name-as-directory (expand-file-name "scripts" (file-name-as-directory (expand-file-name "../contrib" (file-name-directory (org-find-library-dir "org"))))))) "Path to the ditaa.jar file." :group 'org-babel :type 'string) (defcustom org-ditaa-eps-jar-path (expand-file-name "DitaaEps.jar" (file-name-directory org-ditaa-jar-path)) "Path to the DitaaEps.jar executable. Used when generating eps or pdf output." :group 'org-babel :version "24.4" :package-version '(Org . "8.0") :type 'string) ;;; small helper function returning file if it exists and signalling ;;; error otherwise (defun org-ditaa-ensure-jar-file (file) (if (file-exists-p file) file (error "could not find jar file %s" file))) (defun org-babel-execute:ditaa (body params) "Execute BODY of ditaa code with org-babel according to PARAMS. This function is called by `org-babel-execute-src-block'." (let* ((out-file (or (cdr (assq :file params)) (error "ditaa code block requires :file header argument"))) (png (cdr (assq :png params))) (svg (cdr (assq :svg params))) (eps (cdr (assq :eps params))) (pdf (cdr (assq :pdf params))) (num-out-types-set (seq-count 'identity (list png svg eps pdf)))) (when (> num-out-types-set 1) (error "more than one output type specified for ditaa code block")) (when (= num-out-types-set 0) ;; deduce outfile type from suffix or set to default (let ((out-file-suffix (file-name-extension out-file))) (setq svg (string= out-file-suffix "svg")) (setq eps (string= out-file-suffix "eps")) (setq pdf (string= out-file-suffix "pdf")) (setq png (or (string= out-file-suffix "png") (not svg eps pdf))))) (let* ((ditaa-options (cdr (assq :cmdline params))) (ditaa-encoding (cdr (assq :encoding params))) (java-options (cdr (assq :java params))) (use-eps-jar (or eps pdf)) (exec-form (if (or (equal org-ditaa-default-exec-mode 'jar) use-eps-jar) (concat org-ditaa-java-exec (when java-options (concat " " java-options)) " " "-jar" " " (shell-quote-argument (org-ditaa-ensure-jar-file (if use-eps-jar org-ditaa-eps-jar-path org-ditaa-jar-path)))) org-ditaa-exec)) (in-file (org-babel-temp-file "ditaa-")) (ditaa-out-file (org-babel-process-file-name (if pdf (concat in-file ".eps") out-file))) (cmd (concat exec-form (when ditaa-options (concat " " ditaa-options)) (when svg (concat " " "--svg")) (when ditaa-encoding (concat " " "-e " ditaa-encoding)) " " in-file " " ditaa-out-file))) (with-temp-file in-file (insert body)) (message cmd) (shell-command cmd) (when pdf (let ((pdf-cmd (concat "epstopdf" " " ditaa-out-file " " "-o=" (org-babel-process-file-name out-file)))) (message pdf-cmd) (shell-command pdf-cmd))) nil))) ;; signal that output has already been written to file (defun org-babel-prep-session:ditaa (_session _params) "Return an error because ditaa does not support sessions." (error "Ditaa does not support sessions")) (provide 'ob-ditaa) ;;; ob-ditaa.el ends here