mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-11-24 07:20:29 +00:00
org-fold: Make sure that changes do not leave partially folded headings
* lisp/org-fold-core.el (org-fold-core--fix-folded-region): Check fragility in all the indirect buffers. * lisp/org-fold.el (org-fold--reveal-headline-at-point): New function revealing heading line or full heading when the heading only contains blank lines. (org-fold--reveal-outline-maybe): Check headline at the end of folded region as well. Use `org-fold-core--fix-folded-region'. * lisp/org.el (org-insert-heading): Make sure that the newline in front of heading is revealed.
This commit is contained in:
parent
f29ccf3161
commit
8e2fed82ed
@ -1269,41 +1269,42 @@ property, unfold the region if the :fragile function returns non-nil."
|
||||
(let ((new-region (funcall func from to)))
|
||||
(setq from (car new-region))
|
||||
(setq to (cdr new-region))))
|
||||
(dolist (spec (org-fold-core-folding-spec-list))
|
||||
;; No action is needed when :fragile is nil for the spec.
|
||||
(when (org-fold-core-get-folding-spec-property spec :fragile)
|
||||
(org-with-wide-buffer
|
||||
;; Expand the considered region to include partially present fold.
|
||||
;; Note: It is important to do this inside loop over all
|
||||
;; specs. Otherwise, the region may be expanded to huge
|
||||
;; outline fold, potentially involving majority of the
|
||||
;; buffer. That would cause the below code to loop over
|
||||
;; almost all the folds in buffer, which would be too slow.
|
||||
(let ((local-from from)
|
||||
(local-to to)
|
||||
(region-from (org-fold-core-get-region-at-point spec (max (point-min) (1- from))))
|
||||
(region-to (org-fold-core-get-region-at-point spec (min to (1- (point-max))))))
|
||||
(when region-from (setq local-from (car region-from)))
|
||||
(when region-to (setq local-to (cdr region-to)))
|
||||
(let ((pos local-from))
|
||||
;; Move to the first hidden region.
|
||||
(unless (org-fold-core-get-folding-spec spec pos)
|
||||
(setq pos (org-fold-core-next-folding-state-change spec pos local-to)))
|
||||
;; Cycle over all the folds.
|
||||
(while (< pos local-to)
|
||||
(save-match-data ; we should not clobber match-data in after-change-functions
|
||||
(let ((fold-begin (and (org-fold-core-get-folding-spec spec pos)
|
||||
pos))
|
||||
(fold-end (org-fold-core-next-folding-state-change spec pos local-to)))
|
||||
(when (and fold-begin fold-end)
|
||||
(when (save-excursion
|
||||
(funcall (org-fold-core-get-folding-spec-property spec :fragile)
|
||||
(cons fold-begin fold-end)
|
||||
spec))
|
||||
;; Reveal completely, not just from the SPEC.
|
||||
(org-fold-core-region fold-begin fold-end nil)))))
|
||||
;; Move to next fold.
|
||||
(setq pos (org-fold-core-next-folding-state-change spec pos local-to))))))))))))
|
||||
(org-fold-core-cycle-over-indirect-buffers
|
||||
(dolist (spec (org-fold-core-folding-spec-list))
|
||||
;; No action is needed when :fragile is nil for the spec.
|
||||
(when (org-fold-core-get-folding-spec-property spec :fragile)
|
||||
(org-with-wide-buffer
|
||||
;; Expand the considered region to include partially present fold.
|
||||
;; Note: It is important to do this inside loop over all
|
||||
;; specs. Otherwise, the region may be expanded to huge
|
||||
;; outline fold, potentially involving majority of the
|
||||
;; buffer. That would cause the below code to loop over
|
||||
;; almost all the folds in buffer, which would be too slow.
|
||||
(let ((local-from from)
|
||||
(local-to to)
|
||||
(region-from (org-fold-core-get-region-at-point spec (max (point-min) (1- from))))
|
||||
(region-to (org-fold-core-get-region-at-point spec (min to (1- (point-max))))))
|
||||
(when region-from (setq local-from (car region-from)))
|
||||
(when region-to (setq local-to (cdr region-to)))
|
||||
(let ((pos local-from))
|
||||
;; Move to the first hidden region.
|
||||
(unless (org-fold-core-get-folding-spec spec pos)
|
||||
(setq pos (org-fold-core-next-folding-state-change spec pos local-to)))
|
||||
;; Cycle over all the folds.
|
||||
(while (< pos local-to)
|
||||
(save-match-data ; we should not clobber match-data in after-change-functions
|
||||
(let ((fold-begin (and (org-fold-core-get-folding-spec spec pos)
|
||||
pos))
|
||||
(fold-end (org-fold-core-next-folding-state-change spec pos local-to)))
|
||||
(when (and fold-begin fold-end)
|
||||
(when (save-excursion
|
||||
(funcall (org-fold-core-get-folding-spec-property spec :fragile)
|
||||
(cons fold-begin fold-end)
|
||||
spec))
|
||||
;; Reveal completely, not just from the SPEC.
|
||||
(org-fold-core-region fold-begin fold-end nil)))))
|
||||
;; Move to next fold.
|
||||
(setq pos (org-fold-core-next-folding-state-change spec pos local-to)))))))))))))
|
||||
|
||||
;;; Handling killing/yanking of folded text
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
(defvar org-outline-regexp-bol)
|
||||
(defvar org-archive-tag)
|
||||
(defvar org-custom-properties-overlays)
|
||||
(defvar org-element-headline-re)
|
||||
|
||||
(declare-function isearch-filter-visible "isearch" (beg end))
|
||||
(declare-function org-element-type "org-element" (element))
|
||||
@ -930,6 +931,30 @@ This function is intended to be used as a member of
|
||||
(setq from (save-excursion (goto-char from) (line-beginning-position 0)))
|
||||
(cons from to))
|
||||
|
||||
(defun org-fold--reveal-headline-at-point ()
|
||||
"Reveal header line and empty contents inside.
|
||||
Reveal the header line and, if present, also reveal its contents, when
|
||||
the contents consists of blank lines.
|
||||
|
||||
Assume that point is located at the header line."
|
||||
(org-with-wide-buffer
|
||||
(beginning-of-line)
|
||||
(org-fold-region
|
||||
(max (point-min) (1- (point)))
|
||||
(let ((endl (line-end-position)))
|
||||
(save-excursion
|
||||
(goto-char endl)
|
||||
(skip-chars-forward "\n\t\r ")
|
||||
;; Unfold blank lines after newly inserted headline.
|
||||
(if (equal (point)
|
||||
(save-excursion
|
||||
(goto-char endl)
|
||||
(org-end-of-subtree)
|
||||
(skip-chars-forward "\n\t\r ")))
|
||||
(point)
|
||||
endl)))
|
||||
nil 'headline)))
|
||||
|
||||
(defun org-fold--reveal-outline-maybe (region _)
|
||||
"Reveal folded outline in REGION when needed.
|
||||
|
||||
@ -942,28 +967,25 @@ This function is intended to be used as :fragile property of
|
||||
;; headline or a list item.
|
||||
(backward-char)
|
||||
(beginning-of-line)
|
||||
;; Make sure that headline is not partially hidden
|
||||
;; Make sure that headline is not partially hidden.
|
||||
(unless (org-fold-folded-p nil 'headline)
|
||||
(org-fold-region
|
||||
(max (point-min) (1- (point)))
|
||||
(let ((endl (line-end-position)))
|
||||
(save-excursion
|
||||
(goto-char endl)
|
||||
(skip-chars-forward "\n\t\r ")
|
||||
;; Unfold blank lines.
|
||||
(if (or (and (looking-at-p "\\*")
|
||||
(> (point) (1+ endl)))
|
||||
(eq (point) (point-max)))
|
||||
(point)
|
||||
endl)))
|
||||
nil 'headline))
|
||||
(org-fold--reveal-headline-at-point))
|
||||
;; Never hide level 1 headlines
|
||||
(save-excursion
|
||||
(goto-char (line-end-position))
|
||||
(unless (>= (point) (cdr region))
|
||||
(when (re-search-forward (rx bol "* ") (cdr region) t)
|
||||
(org-fold-region (match-beginning 0) (line-end-position) nil 'headline))))
|
||||
(org-fold--reveal-headline-at-point))))
|
||||
;; Make sure that headline after is not partially hidden.
|
||||
(goto-char (cdr region))
|
||||
(beginning-of-line)
|
||||
(unless (org-fold-folded-p nil 'headline)
|
||||
(when (looking-at-p org-element-headline-re)
|
||||
(org-fold--reveal-headline-at-point)))
|
||||
;; Check the validity of headline
|
||||
(goto-char (car region))
|
||||
(backward-char)
|
||||
(beginning-of-line)
|
||||
(unless (let ((case-fold-search t))
|
||||
(looking-at (rx-to-string
|
||||
`(or (regex ,(org-item-re))
|
||||
|
@ -6141,7 +6141,10 @@ unconditionally."
|
||||
(unless invisible-ok
|
||||
(if (eq org-fold-core-style 'text-properties)
|
||||
(cond
|
||||
((org-fold-folded-p (line-beginning-position) 'headline)
|
||||
((org-fold-folded-p
|
||||
(max (point-min)
|
||||
(1- (line-beginning-position)))
|
||||
'headline)
|
||||
(org-fold-region (line-end-position 0) (line-end-position) nil 'headline))
|
||||
(t nil))
|
||||
(pcase (get-char-property-and-overlay (point) 'invisible)
|
||||
|
Loading…
Reference in New Issue
Block a user