forked from mirrors/org-mode
org-fold-core: Fix folding for `isearch-filter-prediacate' outside isearch
* lisp/org-fold-core.el (org-fold-core--keep-overlays): New internal macro, signaling `org-fold-core-region' to keep overlays in place and store new overlays for later use in isearch. (org-fold-core-region): Never remove overlays and store newly created ones in `org-fold-core--isearch-overlays' when `org-fold-core--keep-overlays' is non-nil. Remove resolved FIXME. (org-fold-core--isearch-setup): Advice `isearch-clean-overlays' as more reliable way to clear all the temporary overlays created for isearch. `query-replace' and EVIL packages use `isearch-filter-predicate' separately as thus `isearch-mode-end-hook' is not sufficient to ensure that isearch overlays are converted back to text properties. (org-fold-core--isearch-show-temporary): Do not alter match data, as isearch expects the match data to stay unchanged. Arrange the overlays to be kept for isearch consumption (otherwise, isearch will signal an error; see https://list.orgmode.org/orgmode/87pmc4smdg.fsf@fastmail.fm/). (org-fold-core--create-isearch-overlays): Call `org-fold-core-region' with let-bound `org-fold-core-style' instead of repeating the code from `org-fold-core-region'. Reported-by: Michael Dauer <mick.dauer@gmail.com> Link: https://list.orgmode.org/orgmode/CAP7OBx+L11ck3Ni6rv94HGU3otdj6C4rG-rMDzkwR1LTj=BWiw@mail.gmail.com/ Link+: https://list.orgmode.org/orgmode/87pmc4smdg.fsf@fastmail.fm/ Link+: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=60399 Link+: https://yhetil.org/emacs-devel/87fs7c10cq.fsf@web.de/
This commit is contained in:
parent
873b0d22fd
commit
7dee2c07f4
|
@ -984,6 +984,16 @@ WITH-MARKERS must be nil when RELATIVE is non-nil."
|
|||
|
||||
;;;;; Region visibility
|
||||
|
||||
(defvar org-fold-core--keep-overlays nil
|
||||
"When non-nil, `org-fold-core-region' will not remove existing overlays.
|
||||
Also, new overlays will be added to `org-fold-core--isearch-overlays'.")
|
||||
(defvar org-fold-core--isearch-overlays) ; defined below
|
||||
(defmacro org-fold-core--keep-overlays (&rest body)
|
||||
"Run BODY with `org-fold-core--keep-overlays' set to t."
|
||||
(declare (debug (body)))
|
||||
`(let ((org-fold-core--keep-overlays t))
|
||||
,@body))
|
||||
|
||||
;; This is the core function performing actual folding/unfolding. The
|
||||
;; folding state is stored in text property (folding property)
|
||||
;; returned by `org-fold-core--property-symbol-get-create'. The value of the
|
||||
|
@ -996,7 +1006,16 @@ If SPEC-OR-ALIAS is omitted and FLAG is nil, unfold everything in the region."
|
|||
(when spec (org-fold-core--check-spec spec))
|
||||
(with-silent-modifications
|
||||
(org-with-wide-buffer
|
||||
(when (eq org-fold-core-style 'overlays) (remove-overlays from to 'invisible spec))
|
||||
(when (eq org-fold-core-style 'overlays)
|
||||
(if org-fold-core--keep-overlays
|
||||
(mapc
|
||||
(lambda (ov)
|
||||
(when (eq spec (overlay-get ov 'invisible))
|
||||
(overlay-put ov 'org-invisible spec)
|
||||
(overlay-put ov 'invisible nil)))
|
||||
(overlays-in from to))
|
||||
(remove-overlays from to 'org-invisible spec)
|
||||
(remove-overlays from to 'invisible spec)))
|
||||
(if flag
|
||||
(if (not spec)
|
||||
(error "Calling `org-fold-core-region' with missing SPEC")
|
||||
|
@ -1006,17 +1025,12 @@ If SPEC-OR-ALIAS is omitted and FLAG is nil, unfold everything in the region."
|
|||
(let ((o (make-overlay from to nil
|
||||
(org-fold-core-get-folding-spec-property spec :front-sticky)
|
||||
(org-fold-core-get-folding-spec-property spec :rear-sticky))))
|
||||
(when org-fold-core--keep-overlays (push o org-fold-core--isearch-overlays))
|
||||
(overlay-put o 'evaporate t)
|
||||
(overlay-put o (org-fold-core--property-symbol-get-create spec) spec)
|
||||
(overlay-put o 'invisible spec)
|
||||
(overlay-put o 'isearch-open-invisible #'org-fold-core--isearch-show)
|
||||
;; FIXME: Disabling to work around Emacs bug#60399
|
||||
;; and https://orgmode.org/list/87zgb6tk6h.fsf@localhost.
|
||||
;; The proper fix will require making sure that
|
||||
;; `org-fold-core-isearch-open-function' does not
|
||||
;; delete the overlays used by isearch.
|
||||
;; (overlay-put o 'isearch-open-invisible-temporary #'org-fold-core--isearch-show-temporary)
|
||||
)
|
||||
(overlay-put o 'isearch-open-invisible-temporary #'org-fold-core--isearch-show-temporary))
|
||||
(put-text-property from to (org-fold-core--property-symbol-get-create spec) spec)
|
||||
(put-text-property from to 'isearch-open-invisible #'org-fold-core--isearch-show)
|
||||
(put-text-property from to 'isearch-open-invisible-temporary #'org-fold-core--isearch-show-temporary)
|
||||
|
@ -1104,6 +1118,13 @@ TYPE can be either `text-properties' or `overlays'."
|
|||
(`overlays
|
||||
(when (eq org-fold-core-style 'text-properties)
|
||||
(setq-local isearch-filter-predicate #'org-fold-core--isearch-filter-predicate-overlays)
|
||||
;; When `isearch-filter-predicate' is called outside isearch,
|
||||
;; it is common that `isearch-mode-end-hook' does not get
|
||||
;; executed, but `isearch-clean-overlays' usually does.
|
||||
(advice-add
|
||||
'isearch-clean-overlays :after
|
||||
#'org-fold-core--clear-isearch-overlays
|
||||
'((name . isearch-clean-overlays@org-fold-core)))
|
||||
(add-hook 'isearch-mode-end-hook #'org-fold-core--clear-isearch-overlays nil 'local)))
|
||||
(_ (error "%s: Unknown type of setup for `org-fold-core--isearch-setup'" type))))
|
||||
|
||||
|
@ -1152,26 +1173,34 @@ This function is intended to be used as `isearch-filter-predicate'."
|
|||
"Temporarily reveal text in REGION.
|
||||
Hide text instead if HIDE-P is non-nil.
|
||||
REGION can also be an overlay in current buffer."
|
||||
(when (overlayp region)
|
||||
(setq region (cons (overlay-start region)
|
||||
(overlay-end region))))
|
||||
(if (not hide-p)
|
||||
(let ((pos (car region)))
|
||||
(while (< pos (cdr region))
|
||||
(let ((spec-no-open
|
||||
(catch :found
|
||||
(dolist (spec (org-fold-core-get-folding-spec 'all pos))
|
||||
(unless (org-fold-core-get-folding-spec-property spec :isearch-open)
|
||||
(throw :found spec))))))
|
||||
(if spec-no-open
|
||||
;; Skip regions folded with folding specs that cannot be opened.
|
||||
(setq pos (org-fold-core-next-folding-state-change spec-no-open pos (cdr region)))
|
||||
(dolist (spec (org-fold-core-get-folding-spec 'all pos))
|
||||
(push (cons spec (org-fold-core-get-region-at-point spec pos)) (gethash region org-fold-core--isearch-local-regions)))
|
||||
(org-fold-core--isearch-show region)
|
||||
(setq pos (org-fold-core-next-folding-state-change nil pos (cdr region)))))))
|
||||
(mapc (lambda (val) (org-fold-core-region (cadr val) (cddr val) t (car val))) (gethash region org-fold-core--isearch-local-regions))
|
||||
(remhash region org-fold-core--isearch-local-regions)))
|
||||
(save-match-data ; match data must not be modified.
|
||||
(let ((org-fold-core-style (if (overlayp region) 'overlays 'text-properties)))
|
||||
(when (overlayp region)
|
||||
(setq region (cons (overlay-start region)
|
||||
(overlay-end region))))
|
||||
(if (not hide-p)
|
||||
(let ((pos (car region)))
|
||||
(while (< pos (cdr region))
|
||||
(let ((spec-no-open
|
||||
(catch :found
|
||||
(dolist (spec (org-fold-core-get-folding-spec 'all pos))
|
||||
(unless (org-fold-core-get-folding-spec-property spec :isearch-open)
|
||||
(throw :found spec))))))
|
||||
(if spec-no-open
|
||||
;; Skip regions folded with folding specs that cannot be opened.
|
||||
(setq pos (org-fold-core-next-folding-state-change spec-no-open pos (cdr region)))
|
||||
(dolist (spec (org-fold-core-get-folding-spec 'all pos))
|
||||
(push (cons spec (org-fold-core-get-region-at-point spec pos)) (gethash region org-fold-core--isearch-local-regions)))
|
||||
;; isearch expects all the temporarily opened overlays to exist.
|
||||
;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=60399
|
||||
(org-fold-core--keep-overlays
|
||||
(org-fold-core--isearch-show region))
|
||||
(setq pos (org-fold-core-next-folding-state-change nil pos (cdr region)))))))
|
||||
(mapc (lambda (val)
|
||||
(org-fold-core--keep-overlays
|
||||
(org-fold-core-region (cadr val) (cddr val) t (car val))))
|
||||
(gethash region org-fold-core--isearch-local-regions))
|
||||
(remhash region org-fold-core--isearch-local-regions)))))
|
||||
|
||||
(defvar-local org-fold-core--isearch-special-specs nil
|
||||
"List of specs that can break visibility state when converted to overlays.
|
||||
|
@ -1196,24 +1225,12 @@ instead of text properties. The created overlays will be stored in
|
|||
;; We do not want it here.
|
||||
(with-silent-modifications
|
||||
(org-fold-core-region (car region) (cdr region) nil spec)
|
||||
;; The overlay is modeled after `outline-flag-region'
|
||||
;; [2020-05-09 Sat] overlay for 'outline blocks.
|
||||
(let ((o (make-overlay (car region) (cdr region) nil 'front-advance)))
|
||||
(overlay-put o 'evaporate t)
|
||||
(overlay-put o 'invisible spec)
|
||||
(overlay-put o 'org-invisible spec)
|
||||
;; Make sure that overlays are applied in the same order
|
||||
;; with the folding specs.
|
||||
;; Note: `memq` returns cdr with car equal to the first
|
||||
;; found matching element.
|
||||
(overlay-put o 'priority (length (memq spec (org-fold-core-folding-spec-list))))
|
||||
;; `delete-overlay' here means that spec information will be lost
|
||||
;; for the region. The region will remain visible.
|
||||
(if (org-fold-core-get-folding-spec-property spec :isearch-open)
|
||||
(overlay-put o 'isearch-open-invisible #'delete-overlay)
|
||||
(overlay-put o 'isearch-open-invisible #'ignore)
|
||||
(overlay-put o 'isearch-open-invisible-temporary #'ignore))
|
||||
(push o org-fold-core--isearch-overlays))))))
|
||||
(let ((org-fold-core-style 'overlays))
|
||||
(org-fold-core-region (car region) (cdr region) t spec)
|
||||
(let ((o (cdr (get-char-property-and-overlay
|
||||
(car region)
|
||||
(org-fold-core--property-symbol-get-create spec nil t)))))
|
||||
(push o org-fold-core--isearch-overlays)))))))
|
||||
(setq pos (org-fold-core-next-folding-state-change nil pos end)))))
|
||||
|
||||
(defun org-fold-core--isearch-filter-predicate-overlays (beg end)
|
||||
|
|
Loading…
Reference in New Issue