ob-asymptote.el (4822B)
1 ;;; ob-asymptote.el --- Babel Functions for Asymptote -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc. 4 5 ;; Author: Eric Schulte 6 ;; Maintainer: Jarmo Hurri <jarmo.hurri@iki.fi> 7 ;; Keywords: literate programming, reproducible research 8 ;; Homepage: https://git.sr.ht/~bzg/org-contrib 9 10 ;; This file is not part of GNU Emacs. 11 12 ;; GNU Emacs is free software: you can redistribute it and/or modify 13 ;; it under the terms of the GNU General Public License as published by 14 ;; the Free Software Foundation, either version 3 of the License, or 15 ;; (at your option) any later version. 16 17 ;; GNU Emacs is distributed in the hope that it will be useful, 18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 ;; GNU General Public License for more details. 21 22 ;; You should have received a copy of the GNU General Public License 23 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 24 25 ;;; Commentary: 26 27 ;; Org-Babel support for evaluating asymptote source code. 28 ;; 29 ;; This differs from most standard languages in that 30 ;; 31 ;; 1) there is no such thing as a "session" in asymptote 32 ;; 33 ;; 2) we are generally only going to return results of type "file" 34 ;; 35 ;; 3) we are adding the "file" and "cmdline" header arguments, if file 36 ;; is omitted then the -V option is passed to the asy command for 37 ;; interactive viewing 38 39 ;;; Requirements: 40 41 ;; - The asymptote program :: http://asymptote.sourceforge.net/ 42 ;; 43 ;; - asy-mode :: Major mode for editing asymptote files 44 45 ;;; Code: 46 (require 'ob) 47 48 (defvar org-babel-tangle-lang-exts) 49 (add-to-list 'org-babel-tangle-lang-exts '("asymptote" . "asy")) 50 51 (defvar org-babel-default-header-args:asymptote 52 '((:results . "file") (:exports . "results")) 53 "Default arguments when evaluating an Asymptote source block.") 54 55 (defun org-babel-execute:asymptote (body params) 56 "Execute a block of Asymptote code. 57 This function is called by `org-babel-execute-src-block'." 58 (let* ((out-file (cdr (assq :file params))) 59 (format (or (file-name-extension out-file) 60 "pdf")) 61 (cmdline (cdr (assq :cmdline params))) 62 (in-file (org-babel-temp-file "asymptote-")) 63 (cmd 64 (concat "asy " 65 (if out-file 66 (concat 67 "-globalwrite -f " format 68 " -o " (org-babel-process-file-name out-file)) 69 "-V") 70 " " cmdline 71 " " (org-babel-process-file-name in-file)))) 72 (with-temp-file in-file 73 (insert (org-babel-expand-body:generic 74 body params 75 (org-babel-variable-assignments:asymptote params)))) 76 (message cmd) (shell-command cmd) 77 nil)) ;; signal that output has already been written to file 78 79 (defun org-babel-prep-session:asymptote (_session _params) 80 "Return an error if the :session header argument is set. 81 Asymptote does not support sessions." 82 (error "Asymptote does not support sessions")) 83 84 (defun org-babel-variable-assignments:asymptote (params) 85 "Return list of asymptote statements assigning the block's variables." 86 (mapcar #'org-babel-asymptote-var-to-asymptote 87 (org-babel--get-vars params))) 88 89 (defun org-babel-asymptote-var-to-asymptote (pair) 90 "Convert an elisp value into an Asymptote variable. 91 The elisp value PAIR is converted into Asymptote code specifying 92 a variable of the same value." 93 (let ((var (car pair)) 94 (val (let ((v (cdr pair))) 95 (if (symbolp v) (symbol-name v) v)))) 96 (cond 97 ((integerp val) 98 (format "int %S=%S;" var val)) 99 ((floatp val) 100 (format "real %S=%S;" var val)) 101 ((stringp val) 102 (format "string %S=\"%s\";" var val)) 103 ((and (listp val) (not (listp (car val)))) 104 (let* ((type (org-babel-asymptote-define-type val)) 105 (fmt (if (eq 'string type) "\"%s\"" "%s")) 106 (vect (mapconcat (lambda (e) (format fmt e)) val ", "))) 107 (format "%s[] %S={%s};" type var vect))) 108 ((listp val) 109 (let* ((type (org-babel-asymptote-define-type val)) 110 (fmt (if (eq 'string type) "\"%s\"" "%s")) 111 (array (mapconcat (lambda (row) 112 (concat "{" 113 (mapconcat (lambda (e) (format fmt e)) 114 row ", ") 115 "}")) 116 val ","))) 117 (format "%S[][] %S={%s};" type var array)))))) 118 119 (defun org-babel-asymptote-define-type (data) 120 "Determine type of DATA. 121 122 DATA is a list. Return type as a symbol. 123 124 The type is `string' if any element in DATA is a string. 125 Otherwise, it is either `real', if some elements are floats, or 126 `int'." 127 (letrec ((type 'int) 128 (find-type 129 (lambda (row) 130 (dolist (e row type) 131 (cond ((listp e) (setq type (funcall find-type e))) 132 ((stringp e) (throw 'exit 'string)) 133 ((floatp e) (setq type 'real))))))) 134 (catch 'exit (funcall find-type data)) type)) 135 136 (provide 'ob-asymptote) 137 138 ;;; ob-asymptote.el ends here