I'm editing a svg file and want to see how it looks like. I tried opening a window with the same buffer and change to image-mode but it change the mode in both windows. I tried opening the same file in a different buffer, but it didn't allow me.

So is there a way to have two windows with the same svg file, one with source and one with preview?

  • 2
    Try making an indirect buffer with M-x make-indirect-buffer and adjusting modes accordingly.
    – user12563
    May 16 '18 at 8:49
  • @DoMiNeLa10 image-mode uses text properties to display images. Text properties are stored along with the text and not buffer-local. So the indirect buffer does not help with displaying the svg as image (with image-mode) and as source text simultaneously. A better alternative would be an overlay with display-property in the indirect buffer.
    – Tobias
    May 16 '18 at 16:46

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)
             '(svg svgz))))))))

(defun svg+-edit ()
  "Edit svg of current `image-mode' buffer."
  (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? "))
    (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 )))
      (switch-to-buffer-other-window (current-buffer))))

(easy-menu-add-item image-mode-menu nil
            ["Edit SVG Image" svg+-edit :enable (svg+-image-buffer-p)])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.