组织模式内联图像显示为“insert-sliced-image”

问题描述 投票:0回答:1

在组织模式下显示内联图像时,它的行为有点像单行。像这样滚动浏览大图像是不可能的。 Emacs 将跳到图像的顶部,然后跳到图像的顶部。

真的很想在组织模式下获得切片图像显示,这样我就可以查看更大的内联图像,而不必在新窗口中打开它们并进行缩放。

我的目标是这个 gif 后半部分所示的内容:

注意:这个 gif 没有显示组织模式,我知道这一点。但这种类型的图像显示在组织模式下会非常非常好。 gif 来源:emacs-hnreader

此切片图像是 Emacs 的一项功能:https://www.gnu.org/software/emacs/manual/html_node/elisp/Showing-Images.html

emacs 上也有一个关于此的问题,但从未引起任何关注:https://emacs.stackexchange.com/questions/40550/org-mode-and-insert-sliced-image

emacs org-mode
1个回答
0
投票

可以通过将

insert-sliced-image
循环复制到
org-display-inline-images
并跟踪生成的叠加列表来实现此效果,而不是像当前那样使用单个叠加。将以下内容放入您的
init.el
中应该可以解决问题。 (灵感来自https://github.com/thanhvg/emacs-hnreader

;; Image display

(defvar-local org-inline-image-overlay-families nil
  "A list of elements corresponding to displayed inline images in the
current buffer. Each element is a list of overlays making up the
displayed image.
The first element in each list is a cons of the start and end of dummy
characters inserted for the slices. The last element in the list is the
top-rightmost overlay.")
(put 'org-inline-image-overlay-families 'permanent-local t)

(defun org--delete-inline-image-overlay-family (ovfam)
  "Delete the overlay family OVFAM from its buffer."
  (dolist (ov (cdr ovfam))
    (delete-overlay ov))
  (delete-region (caar ovfam) (1+ (cdar ovfam))))

(defun org--inline-image-overlay-families (&optional beg end)
  "Return image overlay families which start between BEG and END."
  (let* ((beg (or beg (point-min)))
         (end (or end (point-max)))
         (overlays (overlays-in beg end))
         result)
    (dolist (ovfam org-inline-image-overlay-families result)
      (when (memq (car (last ovfam)) overlays)
        (push ovfam result)))))

(defun org-toggle-inline-images (&optional include-linked beg end)
  "Toggle the display of inline images.
INCLUDE-LINKED is passed to `org-display-inline-images'."
  (interactive "P")
  (if (org--inline-image-overlay-families beg end)
      (progn
        (org-remove-inline-images beg end)
        (when (called-interactively-p 'interactive)
          (message "Inline image display turned off")))
    (org-display-inline-images include-linked nil beg end)
    (when (called-interactively-p 'interactive)
      (let ((new (org--inline-image-overlay-families beg end)))
        (message (if new
                     (format "%d images displayed inline"
                             (length new))
                   "No images to display inline"))))))

(defun org--make-inline-image-overlay (start end spec)
  "Make overlay from START to END with display value SPEC.
The overlay is returned."
  (let ((ov (make-overlay start end)))
    (image-flush image)
    (overlay-put ov 'display spec)
    (overlay-put ov 'face 'default)
    (overlay-put ov 'org-image-overlay t)
    (overlay-put ov 'modification-hooks
                 (list 'org-display-inline-remove-overlay-family))
    (when (boundp 'image-map)
      (overlay-put ov 'keymap image-map))
    ov))

(defun org-display-inline-images (&optional include-linked refresh beg end)
  "Display inline images.

An inline image is a link which follows either of these
conventions:

  1. Its path is a file with an extension matching return value
     from `image-file-name-regexp' and it has no contents.

  2. Its description consists in a single link of the previous
     type.  In this case, that link must be a well-formed plain
     or angle link, i.e., it must have an explicit \"file\" or
     \"attachment\" type.

Equip each image with the key-map `image-map'.

When optional argument INCLUDE-LINKED is non-nil, also links with
a text description part will be inlined.  This can be nice for
a quick look at those images, but it does not reflect what
exported files will look like.

When optional argument REFRESH is non-nil, refresh existing
images between BEG and END.  This will create new image displays
only if necessary.

BEG and END define the considered part.  They default to the
buffer boundaries with possible narrowing."
  (interactive "P")
  (when (display-graphic-p)
    (when refresh
      (org-remove-inline-images beg end)
      (when (fboundp 'clear-image-cache) (clear-image-cache)))
    (let ((end (or end (point-max))))
      (org-with-point-at (or beg (point-min))
        (let* ((case-fold-search t)
               (file-extension-re (image-file-name-regexp))
               (link-abbrevs (mapcar #'car
                                     (append org-link-abbrev-alist-local
                                             org-link-abbrev-alist)))
               ;; Check absolute, relative file names and explicit
               ;; "file:" links.  Also check link abbreviations since
               ;; some might expand to "file" links.
               (file-types-re
                (format "\\[\\[\\(?:file%s:\\|attachment:\\|[./~]\\)\\|\\]\\[\\(<?\\(?:file\\|attachment\\):\\)"
                        (if (not link-abbrevs) ""
                          (concat "\\|" (regexp-opt link-abbrevs))))))
          (while (re-search-forward file-types-re end t)
            (let* ((link (org-element-lineage
                          (save-match-data (org-element-context))
                          '(link) t))
                   (linktype (org-element-property :type link))
                   (inner-start (match-beginning 1))
                   (path
                    (cond
                     ;; No link at point; no inline image.
                     ((not link) nil)
                     ;; File link without a description.  Also handle
                     ;; INCLUDE-LINKED here since it should have
                     ;; precedence over the next case.  I.e., if link
                     ;; contains filenames in both the path and the
                     ;; description, prioritize the path only when
                     ;; INCLUDE-LINKED is non-nil.
                     ((or (not (org-element-property :contents-begin link))
                          include-linked)
                      (and (or (equal "file" linktype)
                               (equal "attachment" linktype))
                           (org-element-property :path link)))
                     ;; Link with a description.  Check if description
                     ;; is a filename.  Even if Org doesn't have syntax
                     ;; for those -- clickable image -- constructs, fake
                     ;; them, as in `org-export-insert-image-links'.
                     ((not inner-start) nil)
                     (t
                      (org-with-point-at inner-start
                        (and (looking-at
                              (if (char-equal ?< (char-after inner-start))
                                  org-link-angle-re
                                org-link-plain-re))
                             ;; File name must fill the whole
                             ;; description.
                             (= (org-element-property :contents-end link)
                                (match-end 0))
                             (progn
                               (setq linktype (match-string 1))
                               (match-string 2))))))))
              (when (and path (string-match-p file-extension-re path))
                (let ((file (if (equal "attachment" linktype)
                                (progn
                                  (require 'org-attach)
                                  (ignore-errors (org-attach-expand path)))
                              (expand-file-name path))))
                  (when (and file (file-exists-p file))
                    (let ((width (org-display-inline-image--width link))
                          (old (get-char-property-and-overlay
                                (org-element-property :begin link)
                                'org-image-overlay)))
                      (if (and (car-safe old) refresh)
                          (image-flush (overlay-get (cdr old) 'display))
                        (let ((image (org--create-inline-image file width)))
                          (when image
                            (let* ((image-pixel-cons (image-size image t))
                                   (image-pixel-h (cdr image-pixel-cons))
                                   (y 0.0) (dy (/ (default-font-height) image-pixel-h 1.0))
                                   (dummy-zone-start nil)
                                   (dummy-zone-end nil)
                                   (ovfam nil))
                              (org-with-point-at (org-element-property :begin link)

                                (while (< y 1.0)
                                  (if (= y 0.0)
                                      ;; Overlay link
                                      (push (org--make-inline-image-overlay
                                             (point)
                                             (org-element-property :end link)
                                             (list (list 'slice 0 0.0 1.0 dy) image))
                                            ovfam)

                                    ;; Overlay dummy lines
                                    (let ((start (point)))
                                      (insert " ")
                                      (if (not dummy-zone-start)
                                          (setq dummy-zone-start (pos-bol)))
                                      (push (org--make-inline-image-overlay
                                             start
                                             (point)
                                             (list (list 'slice 0 y 1.0 dy) image))
                                            ovfam)))
                                  (move-end-of-line 1)
                                  (insert (propertize "\n" 'line-height t))
                                  (setq y (+ y dy)))
                                (setq dummy-zone-end (point)))
                              (push (cons dummy-zone-start dummy-zone-end) ovfam)
                              (push ovfam org-inline-image-overlay-families))))))))))))))))

(defun org-display-inline-remove-overlay-family (ov after _beg _end &optional _len)
  "Remove inline-display overlay family if a corresponding region is modified."
  (when (and ov after)
    (when (overlay-get ov 'org-image-overlay)
      (image-flush (overlay-get ov 'display))) ;; cdr here?
    (catch 'break
      (dolist (ovfam org-inline-image-overlay-families)
        (when (memq ov ovfam)
          (setq org-inline-image-overlay-families
                (delq ovfam org-inline-image-overlay-families))
          (org--delete-inline-image-overlay-family ovfam)
          (throw 'break))))))

(defun org-remove-inline-images (&optional beg end)
  "Remove inline display of images which start between BEG and END."
  (interactive)
  (let* ((beg (or beg (point-min)))
         (end (or end (point-max)))
         (overlays (overlays-in beg end)))
    (dolist (ovfam org-inline-image-overlay-families)
      (when (memq (car (last ovfam)) overlays)
        (setq org-inline-image-overlay-families
              (delq ovfam org-inline-image-overlay-families))
        (org--delete-inline-image-overlay-family ovfam)))))
© www.soinside.com 2019 - 2024. All rights reserved.