Add display customization

This commit is contained in:
Greg Sexton 2016-03-13 21:13:54 +00:00
commit 4e98f118c3

View File

@ -37,27 +37,99 @@
(require 'cl) (require 'cl)
(require 'origami-parsers) (require 'origami-parsers)
;;; fold display mode and faces
(defcustom origami-fold-replacement "..."
;; TODO: this should also be specifiable as a function: folded text -> string
"Show this string instead of the folded text."
:type 'string
:group 'origami)
(defcustom origami-show-fold-header nil
"Highlight the line the fold start on."
:type 'boolean
:group 'origami)
(defface origami-fold-header-face
`((t (:box (:line-width 1 :color ,(face-attribute 'highlight :background))
:background ,(face-attribute 'highlight :background))))
"Face used to display fold headers.")
(defface origami-fold-fringe-face
'((t ()))
"Face used to display fringe contents.")
(defface origami-fold-replacement-face
'((t :inherit 'font-lock-comment-face))
"Face used to display the fold replacement text.")
(defgroup origami '((origami-fold-header-face custom-face)
(origami-fold-fringe-face custom-face)
(origami-fold-replacement-face custom-face))
"Origami: A text folding minor mode for Emacs.")
;;; overlay manipulation ;;; overlay manipulation
(defun origami-header-overlay-range (fold-overlay)
"Given a `fold-overlay', return the range that the corresponding
header overlay should cover. Result is a cons cell of (begin . end)."
(with-current-buffer (overlay-buffer fold-overlay)
(let ((fold-begin
(save-excursion
(goto-char (overlay-start fold-overlay))
(line-beginning-position)))
(fold-end
;; Find the end of the folded region -- include the following
;; newline if possible. The header will span the entire fold.
(save-excursion
(goto-char (overlay-end fold-overlay))
(when (looking-at ".")
(forward-char 1)
(when (looking-at "\n")
(forward-char 1)))
(point))))
(cons fold-begin fold-end))))
(defun origami-header-overlay-reset-position (header-overlay)
(-when-let (fold-ov (overlay-get header-overlay 'fold-overlay))
(let ((range (origami-header-overlay-range fold-ov)))
(move-overlay header-overlay (car range) (cdr range)))))
(defun origami-header-modify-hook (header-overlay after-p b e &optional l)
(if after-p (origami-header-overlay-reset-position header-overlay)))
(defun origami-create-overlay (beg end offset buffer) (defun origami-create-overlay (beg end offset buffer)
(when (> (- end beg) 0) (when (> (- end beg) 0)
(let ((ov (make-overlay (+ beg offset) end buffer))) (let ((ov (make-overlay (+ beg offset) end buffer)))
(overlay-put ov 'creator 'origami)
(overlay-put ov 'isearch-open-invisible 'origami-isearch-show) (overlay-put ov 'isearch-open-invisible 'origami-isearch-show)
(overlay-put ov 'isearch-open-invisible-temporary (overlay-put ov 'isearch-open-invisible-temporary
(lambda (ov hide-p) (if hide-p (origami-hide-overlay ov) (lambda (ov hide-p) (if hide-p (origami-hide-overlay ov)
(origami-show-overlay ov)))) (origami-show-overlay ov))))
;; We create a header overlay even when disabled; this could be avoided,
;; especially if we called origami-reset for each buffer if customizations
;; changed.
(let* ((range (origami-header-overlay-range ov))
(header-ov (make-overlay (car range) (cdr range) buffer
nil))) ;; no front advance
(overlay-put header-ov 'creator 'origami)
(overlay-put header-ov 'fold-overlay ov)
(overlay-put header-ov 'modification-hooks '(origami-header-modify-hook))
(overlay-put ov 'header-ov header-ov))
ov))) ov)))
(defun origami-hide-overlay (ov) (defun origami-hide-overlay (ov)
;; TODO: make all of this customizable
(overlay-put ov 'invisible 'origami) (overlay-put ov 'invisible 'origami)
(overlay-put ov 'display "...") (overlay-put ov 'display origami-fold-replacement)
(overlay-put ov 'face 'font-lock-comment-delimiter-face)) (overlay-put ov 'face 'origami-fold-replacement-face)
(if origami-show-fold-header
(origami-activate-header (overlay-get ov 'header-ov))))
(defun origami-show-overlay (ov) (defun origami-show-overlay (ov)
(overlay-put ov 'invisible nil) (overlay-put ov 'invisible nil)
(overlay-put ov 'display nil) (overlay-put ov 'display nil)
(overlay-put ov 'face nil)) (overlay-put ov 'face nil)
(origami-deactivate-header (overlay-get ov 'header-ov)))
(defun origami-hide-node-overlay (node) (defun origami-hide-node-overlay (node)
(-when-let (ov (origami-fold-data node)) (-when-let (ov (origami-fold-data node))
@ -67,6 +139,24 @@
(-when-let (ov (origami-fold-data node)) (-when-let (ov (origami-fold-data node))
(origami-show-overlay ov))) (origami-show-overlay ov)))
(defun origami-activate-header (ov)
;; Reposition the header overlay. Since it extends before the folded area, it
;; may no longer cover the appropriate locations.
(origami-header-overlay-reset-position ov)
(overlay-put ov 'origami-header-active t)
(overlay-put ov 'face 'origami-fold-header-face)
(overlay-put ov 'before-string
(propertize
""
'display
'(left-fringe empty-line origami-fold-fringe-face))))
(defun origami-deactivate-header (ov)
(overlay-put ov 'origami-header-active nil)
(overlay-put ov 'face nil)
(overlay-put ov 'before-string nil)
(overlay-put ov 'after-string nil))
(defun origami-isearch-show (ov) (defun origami-isearch-show (ov)
(origami-show-node (current-buffer) (point))) (origami-show-node (current-buffer) (point)))
@ -83,7 +173,7 @@
(defun origami-remove-all-overlays (buffer) (defun origami-remove-all-overlays (buffer)
(with-current-buffer buffer (with-current-buffer buffer
(remove-overlays (point-min) (point-max) 'invisible 'origami))) (remove-overlays (point-min) (point-max) 'creator 'origami)))
;;; fold structure ;;; fold structure