Recompute header ranges when folding.

Previously header ranges could be broken to extend over previous lines.
The easiest way to reproduce is to put the caret at ^ in this line:

    fn ^foo() { … }

And insert a newline; the header will cover both the “fn “ and “foo() {
… }” lines.

This hacky patch recomputes the header range whenever a modification
happens inside it.
This commit is contained in:
Nicholas Seckar 2015-10-20 13:17:33 -07:00
parent d372bd1af1
commit eafd97fc70

View File

@ -69,6 +69,34 @@
;;; 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)))
@ -80,25 +108,13 @@
;; We create a header overlay even when disabled; this could be avoided, ;; We create a header overlay even when disabled; this could be avoided,
;; especially if we called origami-reset for each buffer if customizations ;; especially if we called origami-reset for each buffer if customizations
;; changed. ;; changed.
(with-current-buffer buffer (let* ((range (origami-header-overlay-range ov))
(let* ((line-begin (header-ov (make-overlay (car range) (cdr range) buffer
(save-excursion nil))) ;; no front advance
(goto-char (+ beg offset))
(line-beginning-position)))
(fold-end
;; Find the end of the folded region -- try to include the
;; newline if possible. The header will span the entire fold.
(save-excursion
(goto-char end)
(when (looking-at ".")
(forward-char 1)
(when (looking-at "\n")
(forward-char 1)))
(point)))
(header-ov (make-overlay line-begin fold-end buffer)))
(overlay-put header-ov 'creator 'origami) (overlay-put header-ov 'creator 'origami)
(overlay-put header-ov 'fold-overlay ov) (overlay-put header-ov 'fold-overlay ov)
(overlay-put ov 'header-ov header-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)
@ -124,6 +140,10 @@
(origami-show-overlay ov))) (origami-show-overlay ov)))
(defun origami-activate-header (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 'origami-header-active t)
(overlay-put ov 'face 'origami-fold-header-face) (overlay-put ov 'face 'origami-fold-header-face)
(overlay-put ov 'before-string (overlay-put ov 'before-string