diff --git a/lisp/org.el b/lisp/org.el index 30a4e7aef..1efd2f31b 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -15673,6 +15673,26 @@ cache Display remote images, and open them in separate buffers (const :tag "Display and silently update remote images" cache)) :safe #'symbolp) +(defcustom org-image-align nil + "How to align images previewed using `org-display-inline-images'. + +Only stand-alone image links are affected by this setting. These +are links without surrounding text. + +Possible values of this option are: + +nil Insert image at specified position. +left Insert image at specified position (same as nil). +center Center image previews. +right Right-align image previews." + :group 'org-appearance + :package-version '(Org . "9.7") + :type '(choice + (const :tag "Left align (or don\\='t align) image previews" nil) + (const :tag "Center image previews" center) + (const :tag "Right align image previews" right)) + :safe #'symbolp) + (defun org--create-inline-image (file width) "Create image located at FILE, or return nil. WIDTH is the width of the image. The image may not be created @@ -15807,7 +15827,8 @@ buffer boundaries with possible narrowing." (when file (setq file (substitute-in-file-name file))) (when (and file (file-exists-p file)) (let ((width (org-display-inline-image--width link)) - (old (get-char-property-and-overlay + (align (org-image--align link)) + (old (get-char-property-and-overlay (org-element-begin link) 'org-image-overlay))) (if (and (car-safe old) refresh) @@ -15819,7 +15840,7 @@ buffer boundaries with possible narrowing." (progn (goto-char (org-element-end link)) - (skip-chars-backward " \t") + (unless (eolp) (skip-chars-backward " \t")) (point))))) ;; FIXME: See bug#59902. We cannot rely ;; on Emacs to update image if the file @@ -15833,6 +15854,15 @@ buffer boundaries with possible narrowing." (list 'org-display-inline-remove-overlay)) (when (boundp 'image-map) (overlay-put ov 'keymap image-map)) + (when align + (overlay-put + ov 'before-string + (propertize + " " 'face 'default + 'display + (pcase align + ('center `(space :align-to (- center (0.5 . ,image)))) + ('right `(space :align-to (- right ,image))))))) (push ov org-inline-image-overlays)))))))))))))))) (defvar visual-fill-column-width) ; Silence compiler warning @@ -15894,6 +15924,43 @@ buffer boundaries with possible narrowing." org-image-actual-width) (t nil)))) +(defun org-image--align (link) + "Determine the alignment of the image link. + +This is controlled globally by the option `org-image-align', and +per image by the value of `:align' in the affiliated keyword +`#+attr_org'. + +The result is either nil or one of the symbols left, center or +right. + +center will cause the image preview to be centered, right will +cause it to be right-aligned. A value of left or nil +implies no special alignment." + (let ((par (org-element-lineage link 'paragraph))) + ;; Only apply when image is not surrounded by paragraph text: + (when (and (= (org-element-begin link) + (save-excursion + (goto-char (org-element-contents-begin par)) + (skip-chars-forward "\t ") + (point))) ;account for leading space + ;before link + (<= (- (org-element-contents-end par) + (org-element-end link)) + 1)) ;account for trailing newline + ;at end of paragraph + (save-match-data + ;; Look for a valid :align keyword (left, center or right) + (if-let* ((attr-org (car-safe (org-element-property :attr_org par))) + ((string-match ":align[[:space:]]+\\(\\w+\\)" attr-org)) + (attr-align (car-safe + (memq (intern (match-string 1 attr-org)) + '(left center right))))) + (unless (eq attr-align 'left) attr-align) + ;; No image-specific keyword, check global alignment property + (when (memq org-image-align '(center right)) + org-image-align)))))) + (defun org-display-inline-remove-overlay (ov after _beg _end &optional _len) "Remove inline-display overlay if a corresponding region is modified." (when (and ov after)