The following code adds a menu item Edit SVG Image in the Image menu for buffers with an svg image as contents and image-mode
as major-mode
. If you click this menu item an svg edit buffer is opened for editing the image in another window. The edit buffer is just updated, displayed, and selected if it already exists.
Every time when you save the image in the edit buffer the displayed image is updated.
(require 'subr-x)
(require 'easymenu)
(require 'cl-lib)
(defvar-local svg+-edit-buffer nil
"Buffer name for svg editing.")
(defvar-local svg+-image-buffer nil
"Buffer for displaying the svg image.")
(defun svg+-image-buffer-p (&optional buffer)
"Return non-nil if BUFFER displays an svg image.
BUFFER defaults to `current-buffer'."
(with-current-buffer (or buffer (current-buffer))
(when-let (((and (derived-mode-p 'image-mode)
(> (buffer-size) 0)))
(img (get-text-property 1 'display))
((eq (car img) 'image))
(props (cdr img))
(type (plist-get props :type)))
(or (eq type 'svg)
(and (eq type 'imagemagick)
(let ((file (plist-get props :file))
(data (plist-get props :data)))
(member (image-type (or file data)
nil
data)
'(svg svgz))))))))
(defun svg+-edit ()
"Edit svg of current `image-mode' buffer."
(interactive)
(unless (svg+-image-buffer-p)
(user-error "svg+-edit only available in `image-mode'"))
(unless (buffer-live-p svg+-edit-buffer)
(setq svg+-edit-buffer (generate-new-buffer (buffer-name))))
(let ((buffer (current-buffer))
(file-name (buffer-file-name)))
(with-current-buffer svg+-edit-buffer
(when (or
(eq (buffer-size) 0)
(y-or-n-p "Edit buffer not empty. Reset content to image? "))
(erase-buffer)
(insert (with-current-buffer buffer
(buffer-substring-no-properties (point-min) (point-max)))))
(setq svg+-image-buffer buffer
buffer-file-name file-name)
(let ((auto-mode-alist (cl-remove 'image-mode auto-mode-alist :key 'cdr )))
(after-find-file))
(switch-to-buffer-other-window (current-buffer))))
(auto-revert-mode))
(easy-menu-add-item image-mode-menu nil
["Edit SVG Image" svg+-edit :enable (svg+-image-buffer-p)])