From 95a98c571bf365f8a83d04f61f265ca04ad851d1 Mon Sep 17 00:00:00 2001
From: Steven vanZyl <rushsteve1@rushsteve1.us>
Date: Sun, 26 Sep 2021 10:35:24 -0400
Subject: [PATCH] ob-svgbob: New babel backend for SVGBob

* lisp/ob-svgbob.el: A new babel backend for the SVGBob tool,
which can convert ASCII art approximations into much nicer
SVG drawings.

Co-authored-by: Author: TEC <tec@tecosaur.com>
---
 lisp/ob-svgbob.el | 110 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 110 insertions(+)
 create mode 100644 lisp/ob-svgbob.el

diff --git a/lisp/ob-svgbob.el b/lisp/ob-svgbob.el
new file mode 100644
index 000000000..75284156a
--- /dev/null
+++ b/lisp/ob-svgbob.el
@@ -0,0 +1,110 @@
+;;; ob-svgbob.el --- Babel Functions for SVGBob -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Steven vanZyl <rushsteve1@rushsteve1.us>
+;;         TEC <tec@tecosaur.com>
+;; Maintainer: Timothy <tec@tecosaur.com>
+;; Keywords: literate programming, reproducible research
+;; Homepage: 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating and SVGBob diagrams.
+;; https://github.com/ivanceras/svgbob
+
+;; This is very similar to ob-dot.el with a similar list of caveats:
+
+;; * There are no sessions
+;; * We are generally only going to return results of type "file graphics"
+;; * The "file" header argument is required
+;; * SVGBob has no definite syntax
+
+;; This file also includes some additional utility functions and a simple
+;; derived major-mode for SVGBob
+
+;;; Code:
+(require 'ob)
+
+(defcustom svgbob-executable "svgbob"
+  "The path to the SVGBob binary.
+This can be installed from source using `cargo install svgbob_cli'"
+  :group 'svgbob
+  :type 'file)
+
+(defcustom svgbob-buffer-name "*svgbob-output*"
+  "The name of the buffer that SVGBob will output to"
+  :group 'svgbob
+  :type 'string)
+
+(defcustom org-babel-svgbob-options
+  '((background . "transparent"))
+  "Options passed to the SVGBob executable"
+  :group 'svgbob
+  :type '(alist :value-type (symbol string)))
+
+;; 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"))
+
+(defun ob-svgbob-string-to-svg (str)
+  "Converts a string to SVG text and returns 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-region-to-svg (start end)
+  "Converts a region to SVG text in a new buffer"
+  (interactive "r")
+  (let ((str (ob-svgbob-string-to-svg (buffer-substring-no-properties start end))))
+    (with-current-buffer (get-buffer-create svgbob-buffer-name)
+      (read-only-mode 0) ; Disable read-only
+      (fundamental-mode) ; Required to erase the buffer
+      (erase-buffer)
+      (insert str)
+      (image-mode)
+      (read-only-mode)
+      (display-buffer-in-side-window (current-buffer) '((side . right))))))
+
+(defun ob-svgbob-buffer-to-svg ()
+  "Converts a buffer to SVG text in a new buffer.
+See `svgbob-region-to-svg' for more"
+  (interactive)
+  (ob-svgbob-region-to-svg (point-min) (point-max)))
+
+(defvar org-babel-default-header-args:svgbob
+  '((:results . "file graphics") (:exports . "results"))
+  "Default arguments to use when evaluating a dot source block.")
+
+(defun org-babel-execute:svgbob (body params)
+  (if (alist-get :file params)
+      (ob-svgbob-string-to-svg body)
+    (user-error "You need to specify a :file parameter")))
+
+(defun org-babel-prep-session:svgbob (_session _params)
+  "Return an error because SVGBob does not support sessions."
+  (user-error "SVGBob does not support sessions"))
+
+(provide 'ob-svgbob)
+
+;;; ob-svgbob.el ends here
-- 
2.33.0

