[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/org 7dee2c07f4 2/3: org-fold-core: Fix folding for `ise
From: |
ELPA Syncer |
Subject: |
[elpa] externals/org 7dee2c07f4 2/3: org-fold-core: Fix folding for `isearch-filter-prediacate' outside isearch |
Date: |
Thu, 1 Jun 2023 09:59:32 -0400 (EDT) |
branch: externals/org
commit 7dee2c07f459680eacbc3afdccff2f1a0d930086
Author: Ihor Radchenko <yantar92@posteo.net>
Commit: Ihor Radchenko <yantar92@posteo.net>
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/
---
lisp/org-fold-core.el | 109 +++++++++++++++++++++++++++++---------------------
1 file changed, 63 insertions(+), 46 deletions(-)
diff --git a/lisp/org-fold-core.el b/lisp/org-fold-core.el
index 1d48bd3896..d58cbc6490 100644
--- a/lisp/org-fold-core.el
+++ b/lisp/org-fold-core.el
@@ -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)