dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

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