diff --git a/ob-svgbob.el b/ob-svgbob.el index f88a433..e183827 100644 --- a/ob-svgbob.el +++ b/ob-svgbob.el @@ -42,6 +42,9 @@ (require 'ob) +(eval-when-compile + (require 'cl-lib)) + (defcustom org-svgbob-executable "svgbob" "The path to the SVGBob binary. This can be installed from source using `cargo install svgbob_cli'" @@ -53,26 +56,41 @@ This can be installed from source using `cargo install svgbob_cli'" :group 'org-babel :type 'string) -(defcustom org-babel-svgbob-options - '((background . "transparent")) - "Options passed to the SVGBob executable." - :group 'org-babel - :type '(alist :value-type (symbol string))) +(defconst org-babel-svgbob--parameters + '(:background :fill-color :font-family :font-size :scale :stroke-width) + "Recognised SVGBob parameter keys.") ;; So `org-edit-special' works. -;; Since SVGBob is based on simple ASCII diagrams without a definite, this mode -;; is derived from `artist-mode'. (unless (fboundp 'svgbob-mode) - (define-derived-mode svgbob-mode artist-mode "svgbob")) + (add-to-list 'org-src-lang-modes (cons "svgbob" 'fundamental))) -(defun ob-svgbob-string-to-svg (str) - "Convert STR to SVG text and return a string of that." - (org-babel-eval - (concat svgbob-executable " " - (mapconcat (lambda (opt) (format "--%s %s " (symbol-name (car opt)) (cdr opt))) - org-babel-svgbob-options - " ")) - str)) +(defun ob-svgbob-string-to-svg (str &optional parameters) + "Convert STR to SVG text and return a string of that. +PARAMETERS should be a plist of svgbob parameters, and only keys +that are members of `org-babel-svgbob--parameters' will be used." + (with-temp-buffer + (insert + (org-babel-eval + (concat org-svgbob-executable + (cl-loop for (key . val) + in parameters + when (memq key org-babel-svgbob--parameters) + concat (format " --%s %S" + (substring (symbol-name key) 1) + val))) + str)) + (when-let ((stroke-color (alist-get :stroke-color parameters))) + (goto-char (point-min)) + (re-search-forward "^[ \t]*stroke: \\(black\\);\n") + (replace-match stroke-color t t nil 1)) + (when-let ((text-color (alist-get :text-color parameters))) + (goto-char (point-min)) + (search-forward "text {") + (re-search-forward "^[ \t]*fill: \\(black\\);\n") + (replace-match text-color t t nil 1)) + (when-let ((file (alist-get :file parameters))) + (write-region nil nil file)) + (buffer-string))) (defun ob-svgbob-region-to-svg (start end) "Convert a region to SVG text in a new buffer. @@ -95,14 +113,16 @@ See `svgbob-region-to-svg' for more" (ob-svgbob-region-to-svg (point-min) (point-max))) (defvar org-babel-default-header-args:svgbob - '((:results . "file graphics") (:exports . "results")) + '((:results . "file graphics") + (:exports . "results") + (:background . "transparent")) "Default arguments to use when evaluating a dot source block.") (defun org-babel-execute:svgbob (body params) "Execute a block of svgbob with org-babel. Specifically, svgbob is called on BODY with PARAMS." (if (alist-get :file params) - (ob-svgbob-string-to-svg body) + (ob-svgbob-string-to-svg body params) (user-error "You need to specify a :file parameter"))) (defun org-babel-prep-session:svgbob (_session _params)