4

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?

matj1
  • 41
  • 3
  • 2
    Try making an indirect buffer with `M-x make-indirect-buffer` and adjusting modes accordingly. –  May 16 '18 at 08: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

1 Answers1

1

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)])
Tobias
  • 32,569
  • 1
  • 34
  • 75