Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
;; esvg-show.el. -*- lexical-binding: nil; -*-
;; This file:
;;    https://anggtwu.net/elisp/esvg-show.el.html
;;    https://anggtwu.net/elisp/esvg-show.el
;;            (find-angg "elisp/esvg-show.el")
;;     See: https://anggtwu.net/2026-eepitch-svg.html
;;  Author: Eduardo Ochs <eduardoochs@gmail.com>
;; Version: 2026aug14
;;
;; This is the lowest-level file of esvg - edrx's (REPL for) SVG.
;;
;; Note that svg.el comes with an executable example in its comments,
;; but it is a bit tricky to run because it inserts an SVG image at the
;; end of svg.el itself... see (and maybe try):
;;
;;   (find-efile "svg.el" "Here are some usage examples:")
;;   (find-efile "svg.el" "(goto-char (point-max))")
;;
;; Now try this test:
;;
;;   (load (buffer-file-name))
;;   (setq svg (svg-create 400 400 :stroke "orange" :stroke-width 5))
;;   (show-svg-pp-xml)
;;   (svg-rectangle svg 100 100 200 100 :fill "red"   :id "rect1")
;;   (svg-rectangle svg 120 120 200 100 :fill "green" :id "rect2")
;;   (svg-rectangle svg 110 100 200 100 :fill "red"   :id "rect1")
;;   (svg-rectangle svg 100 100 200 100 :fill "red"   :id "rect1")
;;   (show-svg-pp-xml)
;;
;; It creates a 4-window setting like this,
;;
;;      ____________________________
;;     |            |               |
;;     |            |  SVG (image)  |
;;     |            |_______________|
;;     |    This    |               |
;;     |    file    |  SVG as Lisp  |
;;     |            |_______________|
;;     |            |               |
;;     |            |  SVG as XML   |
;;     |____________|_______________|
;;
;; and the calls to `svg-rectangle' update the SVG image, but not the
;; windows with in which the SVG object is shown as Lisp and as XML.
;;
;; Index:
;; «.esvg-xml-to-string»	(to "esvg-xml-to-string")
;; «.find-xml-indent»		(to "find-xml-indent")
;; «.find-4a»			(to "find-4a")
;; «.show-svg-1»		(to "show-svg-1")
;; «.show-svg»			(to "show-svg")


;; Esvg is built on top of eev, and it implements
;; alternatives for some functions in svg.el.
(require 'eev-load)		; See: (find-eev-install-intro "0.2. Loading")
(require 'svg)			; See: (find-efile "svg.el")
(defvar   svg)			; The `show-*' functions use this variable


;; «esvg-xml-to-string»  (to ".esvg-xml-to-string")
;; Tests: (esvg-xml-to-string  (svg-create 1 2))
;;        (esvg-xml-to-string '(svg))
;;        (esvg-xml-to-string '(svg nil))
;;        (esvg-xml-to-string '(svg nil (rect)))
;;        (esvg-xml-to-string '(svg ((w . 1) (h . 2)) (rect)))
;;        (esvg-xml-to-string '(svg ((w . 1) (h . 2)) (rect) (rect)))
;;        (esvg-xml-to-string '(svg ((w . 1) (h . 2)) (rect nil)))
;;        (esvg-xml-to-string '(svg ((w . 1) (h . 2)) (rect nil (subrect))))
;;        (esvg-xml-to-string '(svg ((w . 1) (h . 2)) (foo ((a . 3) (b . 4)) (bar))))
;;        (esvg-xml-to-string "<svg></svg>\n\n")
;;
(defun esvg-xml-to-string (o)
  "Convert O to a multi-line string.
If O is string, treat it as XML, split it into lines, and indent it.
If O is a list convert it to XML first by using `esvg--svg-print',
that is a wrapper around `svg-print'.
This function is used by `show-xml-1'."
  (if (not (stringp o))
      (setq o (esvg--svg-print o)))
  (setq o (replace-regexp-in-string  "[ \t\n]+"  " " o))
  (setq o (replace-regexp-in-string ">[ \t\n]*<" ">\n<" o))
  (setq o (esvg--xml-indent o))
  (setq o (replace-regexp-in-string "[ \t\n]*\\'" "" o)))

;; Tests: (esvg--svg-print (svg-create 1 2))
;;        (esvg--svg-print '(svg nil))
;;        (esvg--svg-print '(svg ((w . 1) (h . 2))))
;;        (esvg--svg-print '(svg ((w . 1) (h . 2)) (rect)))
;;   See: (find-efunction 'svg-print)
(defun esvg--svg-print (o)
  "An internal function used by `esvg-xml-to-string'."
  (with-temp-buffer
    (svg-print o)
    (buffer-string)))

;; Test: (esvg--xml-indent "<a>\n<b>\n</b>\n</a>")
(defun esvg--xml-indent (xmlstr)
  "An internal function used by `esvg-xml-to-string'."
  (with-temp-buffer
    (insert xmlstr)
    (xml-mode)
    (indent-region (point-min) (point-max))
    (buffer-string)))


;; «find-xml-indent»  (to ".find-xml-indent")
(defun esvg-xml-at-point ()
  "If the point is on an SVG image then return its XML."
  (plist-get (cdr (get-text-property (point) 'display)) :data))

(defun esvg-xml-at-point-or-region ()
  (or (esvg-xml-at-point)
      (buffer-substring (point) (mark))))

(defun find-xml-indent (&optional s)
  "Display the XML of an SVG image in a temporary buffer, in indented form.
This function is meant to be used interactively. If we call it with the
point on an SVG image, it extracts the XML from the `display' text
property of the image at point; if there is no SVG image at point it
uses the region."
  (interactive)
  (find-estring
   (esvg-xml-to-string
    (or s (esvg-xml-at-point-or-region)))))


;; «find-4a»  (to ".find-4a")
;; Based on: (find-efunction 'find-3a)
;;      See: (find-multiwindow-intro "3. High-level words")
;;     Test: (find-4a nil nil nil nil)
(defun find-4a (a b c d) (find-wset "13_o22+_o_o_o" a b c d))


;; «show-svg-1»  (to ".show-svg-1")
;; Tests: (show-svg)
;;        (show-svg-pp)
;;        (show-svg-pp-xml)
;;
(defun show-svg-1 ()
  (find-ebuffer "*svg*")
  (delete-region (point-min) (point-max))
  (if svg (svg-insert-image svg))
  (goto-char (point-min))
  (setq cursor-type nil))

(defun show-pp-1 ()
  (let ((ee-buffer-name (or ee-buffer-name "*svg-pp*")))
    (find-epp svg)))

(defun show-xml-1 ()
  (let ((ee-buffer-name (or ee-buffer-name "*svg-xml*")))
    (find-estring (esvg-xml-to-string svg))))


;; «show-svg»  (to ".show-svg")
;; The top-level functions.
;; See the test at the top of this file.
;;
(defun show-svg ()
  (interactive)
  (find-2a nil '(show-svg-1)))

(defun show-svg-pp ()
  (interactive)
  (find-3a nil '(show-svg-1) '(show-pp-1)))

(defun show-svg-pp-xml ()
  (interactive)
  (find-4a nil '(show-svg-1) '(show-pp-1) '(show-xml-1)))

(defun show-pp-xml ()
  (interactive)
  (find-3a nil '(show-pp-1) '(show-xml-1)))

(defun show-pp ()
  (interactive)
  (find-2a nil '(show-pp-1)))



(provide 'esvg-show)






;; Local Variables:
;; coding:  utf-8-unix
;; End: