:safe #'booleanp
:version "29.1")
+(defvar-local outline--use-buttons nil
+ "Non-nil when buffer displays clickable buttons on the headings.")
+
+(defvar-local outline--use-rtl nil
+ "Non-nil when direction of clickable buttons is right-to-left.")
+
+(defcustom outline-minor-mode-use-margins '(derived-mode . special-mode)
+ "Whether to display clickable buttons in the margins.
+The value should be a `buffer-match-p' condition.
+
+These buttons can be used to hide and show the body under the heading.
+Note that this feature is meant to be used in editing buffers."
+ :type 'buffer-predicate
+ :safe #'booleanp
+ :version "29.1")
+
+(defvar-local outline--use-margins nil
+ "Non-nil when buffer displays clickable buttons in the margins.")
+
(define-icon outline-open nil
- '((image "outline-open.svg" "outline-open.pbm"
- :height 15 :ascent center)
+ '((image "outline-open.svg" "outline-open.pbm" :height 15)
(emoji "🔽")
(symbol " ▼ ")
- (text " open "))
- "Icon used for buttons for opening a section in outline buffers."
+ (text " v "))
+ "Icon used for buttons for opened sections in outline buffers."
:version "29.1"
- :help-echo "Open this section")
+ :help-echo "Close this section")
(define-icon outline-close nil
- '((image "outline-close.svg" "outline-close.pbm"
- :height 15 :ascent center)
+ '((image "outline-close.svg" "outline-close.pbm" :height 15)
(emoji "▶️")
(symbol " ▶ ")
- (text " close "))
- "Icon used for buttons for closing a section in outline buffers."
+ (text " > "))
+ "Icon used for buttons for closed sections in outline buffers."
:version "29.1"
- :help-echo "Close this section")
+ :help-echo "Open this section")
+
+(define-icon outline-close-rtl outline-close
+ '((image "outline-close.svg" "outline-close.pbm" :height 15 :rotation 180)
+ (emoji "◀️")
+ (symbol " ◀ ")
+ (text " < "))
+ "Right-to-left icon used for buttons in closed outline sections."
+ :version "29.1")
+
+(define-icon outline-open-in-margins outline-open
+ '((image "outline-open.svg" "outline-open.pbm" :height 10))
+ "Icon used for buttons for opened sections in margins."
+ :version "29.1")
+
+(define-icon outline-close-in-margins outline-close
+ '((image "outline-open.svg" "outline-open.pbm" :height 10 :rotation -90))
+ "Icon used for buttons for closed sections in margins."
+ :version "29.1")
+
+(define-icon outline-close-rtl-in-margins outline-close-rtl
+ '((image "outline-open.svg" "outline-open.pbm" :height 10 :rotation 90))
+ "Right-to-left icon used for closed sections in margins."
+ :version "29.1")
\f
(defvar outline-level #'outline-level
(when (or (memq outline-minor-mode-highlight '(append override))
(and (eq outline-minor-mode-highlight t)
(not (get-text-property (match-beginning 0) 'face))))
- (overlay-put overlay 'face (outline-font-lock-face)))
- (when (outline--use-buttons-p)
- (outline--insert-open-button)))
+ (overlay-put overlay 'face (outline-font-lock-face))))
(goto-char (match-end 0))))))
;;;###autoload
(key-description outline-minor-mode-prefix) outline-mode-prefix-map)
(if outline-minor-mode
(progn
+ (cond
+ ((buffer-match-p outline-minor-mode-use-margins (current-buffer))
+ (setq-local outline--use-margins t))
+ ((buffer-match-p outline-minor-mode-use-buttons (current-buffer))
+ (setq-local outline--use-buttons t)))
+ (when (and (or outline--use-buttons outline--use-margins)
+ (eq (current-bidi-paragraph-direction) 'right-to-left))
+ (setq-local outline--use-rtl t))
+ (when outline--use-margins
+ (if outline--use-rtl
+ (setq-local right-margin-width (1+ right-margin-width))
+ (setq-local left-margin-width (1+ left-margin-width)))
+ (setq-local fringes-outside-margins t)
+ ;; Force display of margins
+ (set-window-buffer nil (window-buffer)))
+ (when (or outline--use-buttons outline--use-margins)
+ (add-hook 'after-change-functions
+ (lambda (beg end _len)
+ (when outline--use-buttons
+ (remove-overlays beg end 'outline-button t))
+ (when outline--use-margins
+ (remove-overlays beg end 'outline-margin t))
+ (outline--fix-up-all-buttons beg end))
+ nil t))
(when outline-minor-mode-highlight
(if (and global-font-lock-mode (font-lock-specified-p major-mode))
(progn
(font-lock-add-keywords nil outline-font-lock-keywords t)
- (font-lock-flush)
- (outline--fix-up-all-buttons))
+ (font-lock-flush))
(outline-minor-mode-highlight-buffer)))
+ (outline--fix-up-all-buttons)
;; Turn off this mode if we change major modes.
(add-hook 'change-major-mode-hook
(lambda () (outline-minor-mode -1))
(font-lock-remove-keywords nil outline-font-lock-keywords))
(remove-overlays nil nil 'outline-overlay t)
(font-lock-flush))
+ (when outline--use-margins
+ (if outline--use-rtl
+ (setq-local right-margin-width (1- right-margin-width))
+ (setq-local left-margin-width (1- left-margin-width)))
+ (setq-local fringes-outside-margins nil)
+ ;; Force removal of margins
+ (set-window-buffer nil (window-buffer)))
(setq line-move-ignore-invisible nil)
;; Cause use of ellipses for invisible text.
(remove-from-invisibility-spec '(outline . t))
;; When turning off outline mode, get rid of any outline hiding.
(outline-show-all)))
-(defun outline--use-buttons-p ()
- (and outline-minor-mode
- (buffer-match-p outline-minor-mode-use-buttons (current-buffer))))
-
(defvar-local outline-heading-alist ()
"Alist associating a heading for every possible level.
Each entry is of the form (HEADING . LEVEL).
(overlay-put o 'follow-link 'mouse-face)
(overlay-put o 'mouse-face 'highlight)
(overlay-put o 'outline-button t))
- (let ((icon
- (icon-elements (if (eq type 'close) 'outline-close 'outline-open)))
+ (let ((icon (icon-elements (if (eq type 'close)
+ (if outline--use-rtl
+ 'outline-close-rtl
+ 'outline-close)
+ 'outline-open)))
(inhibit-read-only t))
;; In editing buffers we use overlays only, but in other buffers
;; we use a mix of text properties, text and overlays to make
(overlay-put o 'face (plist-get icon 'face))))
o))
-(defun outline--insert-open-button ()
+(defun outline--make-margin-overlay (type)
+ (let ((o (seq-find (lambda (o)
+ (overlay-get o 'outline-margin))
+ (overlays-at (point)))))
+ (unless o
+ (setq o (make-overlay (point) (1+ (point))))
+ (overlay-put o 'follow-link 'mouse-face)
+ (overlay-put o 'mouse-face 'highlight)
+ (overlay-put o 'outline-margin t))
+ (let ((icon (icon-elements (if (eq type 'close)
+ (if outline--use-rtl
+ 'outline-close-rtl-in-margins
+ 'outline-close-in-margins)
+ 'outline-open-in-margins)))
+ (inhibit-read-only t))
+ (overlay-put
+ o 'before-string
+ (propertize " " 'display
+ `((margin ,(if outline--use-rtl
+ 'right-margin 'left-margin))
+ ,(or (plist-get icon 'image)
+ (plist-get icon 'string))))))
+ o))
+
+(defun outline--insert-open-button (&optional use-margins)
(with-silent-modifications
(save-excursion
- (beginning-of-line)
+ (beginning-of-line)
+ (if use-margins
+ (let ((o (outline--make-margin-overlay 'open)))
+ (overlay-put o 'help-echo "Click to hide")
+ (overlay-put o 'keymap
+ (define-keymap
+ "<mouse-2>" #'outline-hide-subtree)))
(when (derived-mode-p 'special-mode)
(let ((inhibit-read-only t))
(insert " ")
(overlay-put o 'keymap
(define-keymap
"RET" #'outline-hide-subtree
- "<mouse-2>" #'outline-hide-subtree))))))
+ "<mouse-2>" #'outline-hide-subtree
+ "<left-margin> <mouse-1>" #'outline-hide-subtree)))))))
-(defun outline--insert-close-button ()
+(defun outline--insert-close-button (&optional use-margins)
(with-silent-modifications
(save-excursion
- (beginning-of-line)
+ (beginning-of-line)
+ (if use-margins
+ (let ((o (outline--make-margin-overlay 'close)))
+ (overlay-put o 'help-echo "Click to show")
+ (overlay-put o 'keymap
+ (define-keymap
+ "<mouse-2>" #'outline-show-subtree)))
(when (derived-mode-p 'special-mode)
(let ((inhibit-read-only t))
(insert " ")
(overlay-put o 'keymap
(define-keymap
"RET" #'outline-show-subtree
- "<mouse-2>" #'outline-show-subtree))))))
+ "<mouse-2>" #'outline-show-subtree
+ "<left-margin> <mouse-1>" #'outline-show-subtree)))))))
(defun outline--fix-up-all-buttons (&optional from to)
- (when (outline--use-buttons-p)
+ (when (or outline--use-buttons outline--use-margins)
(when from
(save-excursion
(goto-char from)
(outline-end-of-heading)
(seq-some (lambda (o) (eq (overlay-get o 'invisible) 'outline))
(overlays-at (point))))
- (outline--insert-close-button)
- (outline--insert-open-button)))
+ (outline--insert-close-button outline--use-margins)
+ (outline--insert-open-button outline--use-margins)))
(or from (point-min)) (or to (point-max)))))
(define-obsolete-function-alias 'hide-subtree #'outline-hide-subtree "25.1")
(t
(outline-show-all)
(setq outline--cycle-buffer-state 'show-all)
- (message "Show all")))
- (outline--fix-up-all-buttons)))
+ (message "Show all")))))
\f
(defvar-keymap outline-navigation-repeat-map