* A question about overlays and performance. @ 2020-07-25 16:40 Jeff Norden 2020-07-25 16:53 ` Eli Zaretskii 0 siblings, 1 reply; 17+ messages in thread From: Jeff Norden @ 2020-07-25 16:40 UTC (permalink / raw) To: emacs-devel I've been working on an improved emacs mode for CWEB files. The elisp manual says this about overlays: However,... overlays generally don’t scale well... If you need to affect the visual appearance of many portions in the buffer, we recommend using text properties. I've been using text properties, but am realizing that overlays would make things a bit simpler. Is there a way to predict how many overlays will be "too many" and start to slow thing down? Does the configuration of the overlays play a role? A file with 200 sections would wind up with 400 overlays, but the layout would be simple. There would be "section" overlays that are disjoint from each other, and "subsection" overlays each of which is contained in a unique section. Each section would contain at most one subsection, so a position would never be in more than two of the overlays. It would also be easy to call (overlay-recenter) each time the cursor moves to a new section. Thanks in advance! -Jeff ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-25 16:40 A question about overlays and performance Jeff Norden @ 2020-07-25 16:53 ` Eli Zaretskii 2020-07-25 17:24 ` Jeff Norden 2020-07-26 1:33 ` Ihor Radchenko 0 siblings, 2 replies; 17+ messages in thread From: Eli Zaretskii @ 2020-07-25 16:53 UTC (permalink / raw) To: Jeff Norden; +Cc: emacs-devel > From: Jeff Norden <jnorden@math.tntech.edu> > Date: Sat, 25 Jul 2020 11:40:26 -0500 > > Is there a way to predict how many overlays will be "too many" and > start to slow thing down? Thousands. > Does the configuration of the overlays play a role? What do you mean by "configuration" in this context? ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-25 16:53 ` Eli Zaretskii @ 2020-07-25 17:24 ` Jeff Norden 2020-07-25 17:29 ` Eli Zaretskii 2020-07-26 1:33 ` Ihor Radchenko 1 sibling, 1 reply; 17+ messages in thread From: Jeff Norden @ 2020-07-25 17:24 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel Thanks for the fast (nearly instantaneous!) response. >> Is there a way to predict how many overlays will be "too many" and >> start to slow thing down? > > Thousands. That's great. The number of overlays I'd create would certainly be less than 1000. >> Does the configuration of the overlays play a role? > > What do you mean by "configuration" in this context? I wondered if the simple overlay layout that I described would have less of an effect than if they were scattered about and intersected in many different ways. But if it takes thousands to affect performance, then that doesn't really matter for my case. Thanks again! -Jeff ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-25 17:24 ` Jeff Norden @ 2020-07-25 17:29 ` Eli Zaretskii 0 siblings, 0 replies; 17+ messages in thread From: Eli Zaretskii @ 2020-07-25 17:29 UTC (permalink / raw) To: Jeff Norden; +Cc: emacs-devel > From: Jeff Norden <jnorden@math.tntech.edu> > Cc: emacs-devel@gnu.org > Date: Sat, 25 Jul 2020 12:24:49 -0500 > > >> Does the configuration of the overlays play a role? > > > > What do you mean by "configuration" in this context? > > I wondered if the simple overlay layout that I described would have less > of an effect than if they were scattered about and intersected in many > different ways. No, not really. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-25 16:53 ` Eli Zaretskii 2020-07-25 17:24 ` Jeff Norden @ 2020-07-26 1:33 ` Ihor Radchenko 2020-07-26 13:56 ` Eli Zaretskii 2020-07-26 14:44 ` Stefan Monnier 1 sibling, 2 replies; 17+ messages in thread From: Ihor Radchenko @ 2020-07-26 1:33 UTC (permalink / raw) To: Eli Zaretskii, Jeff Norden; +Cc: emacs-devel > The elisp manual says this about overlays: > However,... overlays generally don’t scale well... > If you need to affect the visual appearance of many portions > in the buffer, we recommend using text properties. Not directly related to the initial question here, but may I ask if there are any practical guidelines to convert overlays to text properties? I am specifically concerned about two issues when we want to use text properties instead of overlays to hide text in buffer (pointing at org-mode): - text hidden via text properties is not well-handled by isearch. For overlays, isearch can temporary reveal the hidden text, which is not the case for text hidden using 'invisible text property. - text properties are not buffer-local in indirect buffers. With overlays, it is possible to have define hidden text in basic and indirect buffer independently. However, text properties will always be shared and the text hidden in indirect buffer will automatically be hidden in the base buffer as well. Best, Ihor Eli Zaretskii <eliz@gnu.org> writes: >> From: Jeff Norden <jnorden@math.tntech.edu> >> Date: Sat, 25 Jul 2020 11:40:26 -0500 >> >> Is there a way to predict how many overlays will be "too many" and >> start to slow thing down? > > Thousands. > >> Does the configuration of the overlays play a role? > > What do you mean by "configuration" in this context? > -- Ihor Radchenko, PhD, Center for Advancing Materials Performance from the Nanoscale (CAMP-nano) State Key Laboratory for Mechanical Behavior of Materials, Xi'an Jiaotong University, Xi'an, China Email: yantar92@gmail.com, ihor_radchenko@alumni.sutd.edu.sg ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-26 1:33 ` Ihor Radchenko @ 2020-07-26 13:56 ` Eli Zaretskii 2020-07-26 14:19 ` Ihor Radchenko 2020-07-26 14:44 ` Stefan Monnier 1 sibling, 1 reply; 17+ messages in thread From: Eli Zaretskii @ 2020-07-26 13:56 UTC (permalink / raw) To: Ihor Radchenko; +Cc: jnorden, emacs-devel > From: Ihor Radchenko <yantar92@gmail.com> > Cc: emacs-devel@gnu.org > Date: Sun, 26 Jul 2020 09:33:21 +0800 > > Not directly related to the initial question here, but may I ask if > there are any practical guidelines to convert overlays to text > properties? I am specifically concerned about two issues when we want to > use text properties instead of overlays to hide text in buffer (pointing > at org-mode): > - text hidden via text properties is not well-handled by isearch. For > overlays, isearch can temporary reveal the hidden text, which is not > the case for text hidden using 'invisible text property. > - text properties are not buffer-local in indirect buffers. With > overlays, it is possible to have define hidden text in basic and > indirect buffer independently. However, text properties will always be > shared and the text hidden in indirect buffer will automatically be > hidden in the base buffer as well. So what kind of guidelines did you want to hear regarding these issues? ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-26 13:56 ` Eli Zaretskii @ 2020-07-26 14:19 ` Ihor Radchenko 0 siblings, 0 replies; 17+ messages in thread From: Ihor Radchenko @ 2020-07-26 14:19 UTC (permalink / raw) To: Eli Zaretskii; +Cc: jnorden, emacs-devel > So what kind of guidelines did you want to hear regarding these > issues? Mostly wanted to know if there is a known way to solve these issues. If there is, it may be a good idea to describe it briefly in the manual. If not, I was thinking about writing a patch/feature request to solve these issues. Eli Zaretskii <eliz@gnu.org> writes: >> From: Ihor Radchenko <yantar92@gmail.com> >> Cc: emacs-devel@gnu.org >> Date: Sun, 26 Jul 2020 09:33:21 +0800 >> >> Not directly related to the initial question here, but may I ask if >> there are any practical guidelines to convert overlays to text >> properties? I am specifically concerned about two issues when we want to >> use text properties instead of overlays to hide text in buffer (pointing >> at org-mode): >> - text hidden via text properties is not well-handled by isearch. For >> overlays, isearch can temporary reveal the hidden text, which is not >> the case for text hidden using 'invisible text property. >> - text properties are not buffer-local in indirect buffers. With >> overlays, it is possible to have define hidden text in basic and >> indirect buffer independently. However, text properties will always be >> shared and the text hidden in indirect buffer will automatically be >> hidden in the base buffer as well. > > So what kind of guidelines did you want to hear regarding these > issues? -- Ihor Radchenko, PhD, Center for Advancing Materials Performance from the Nanoscale (CAMP-nano) State Key Laboratory for Mechanical Behavior of Materials, Xi'an Jiaotong University, Xi'an, China Email: yantar92@gmail.com, ihor_radchenko@alumni.sutd.edu.sg ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-26 1:33 ` Ihor Radchenko 2020-07-26 13:56 ` Eli Zaretskii @ 2020-07-26 14:44 ` Stefan Monnier 2020-07-27 11:20 ` Ihor Radchenko 1 sibling, 1 reply; 17+ messages in thread From: Stefan Monnier @ 2020-07-26 14:44 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Eli Zaretskii, Jeff Norden, emacs-devel > - text hidden via text properties is not well-handled by isearch. For > overlays, isearch can temporary reveal the hidden text, which is not > the case for text hidden using 'invisible text property. The recommending way to avoid this problem is to provide a patch which extends Isearch's handling of invisible text to text-properties. There's no reason to presume it would be hard to do. > - text properties are not buffer-local in indirect buffers. With > overlays, it is possible to have define hidden text in basic and > indirect buffer independently. However, text properties will always be > shared and the text hidden in indirect buffer will automatically be > hidden in the base buffer as well. And the way I recommend to avoid this problem is to stay clear of indirect buffers (which I consider as an attractive nuisance). Stefan ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-26 14:44 ` Stefan Monnier @ 2020-07-27 11:20 ` Ihor Radchenko 2020-07-28 16:43 ` Jeff Norden 2020-07-28 23:53 ` Juri Linkov 0 siblings, 2 replies; 17+ messages in thread From: Ihor Radchenko @ 2020-07-27 11:20 UTC (permalink / raw) To: Stefan Monnier; +Cc: Eli Zaretskii, Jeff Norden, emacs-devel [-- Attachment #1: Type: text/plain, Size: 755 bytes --] > The recommending way to avoid this problem is to provide a patch which > extends Isearch's handling of invisible text to text-properties. > There's no reason to presume it would be hard to do. See the attached. > And the way I recommend to avoid this problem is to stay clear of > indirect buffers (which I consider as an attractive nuisance). It is not always possible. I am currently working on re-implementing org-mode folding from using overlays to text-properties. However, it is not possible to stay clear of indirect buffers in org-mode. Many user packages and core code depend on indirect buffer functionality (including different folding state). I will have to go ahead using my "hacky" solution with char-property-alias-alist. Best, Ihor [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: iseach-text-properties.patch --] [-- Type: text/x-diff, Size: 12399 bytes --] diff --git a/lisp/isearch.el b/lisp/isearch.el index 81e83d7950..e87f7f6756 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -145,6 +145,9 @@ search-invisible has a non-nil property `isearch-open-invisible', then incremental search will show the hidden text. (This applies when using `outline.el' and `hideshow.el'.) +When the value is `open-all', consider text made invisible by text +property as well. Text property `isearch-open-invisible' will be +considered in the same way as for overlays. To temporarily change the value for an active incremental search, use \\<isearch-mode-map>\\[isearch-toggle-invisible]. @@ -942,6 +945,7 @@ isearch-new-forward ;; Accumulate here the overlays opened during searching. (defvar isearch-opened-overlays nil) +(defvar isearch-opened-regions nil) ;; Non-nil if the string exists but is invisible. (defvar isearch-hidden nil) @@ -1218,6 +1222,7 @@ isearch-mode isearch-opoint (point) search-ring-yank-pointer nil isearch-opened-overlays nil + isearch-opened-regions nil isearch-input-method-function input-method-function isearch-input-method-local-p (local-variable-p 'input-method-function) regexp-search-ring-yank-pointer nil @@ -1551,6 +1556,7 @@ isearch-exit (let ((isearch-nonincremental t)) (isearch-edit-string)) ;; this calls isearch-done as well (isearch-done)) + (isearch-clean-regions) (isearch-clean-overlays)) (defun isearch-fail-pos (&optional msg) @@ -1807,6 +1813,7 @@ isearch-cancel (isearch--set-state (car isearch-cmds))) (goto-char isearch-opoint)) (isearch-done t) ; Exit isearch.. + (isearch-clean-regions) (isearch-clean-overlays) (signal 'quit nil)) ; ..and pass on quit signal. @@ -2271,6 +2278,7 @@ isearch-query-replace (isearch-string-propertized (isearch-string-propertize isearch-string))) (isearch-done nil t) + (isearch-clean-regions) (isearch-clean-overlays) (if (and isearch-other-end (if backward @@ -2376,6 +2384,7 @@ isearch--highlight-regexp-or-lines ;; We call `exit-recursive-edit' explicitly at the end below. (isearch-recursive-edit nil)) (isearch-done nil t) + (isearch-clean-regions) (isearch-clean-overlays)) (require 'hi-lock nil t) (let ((regexp (cond ((functionp isearch-regexp-function) @@ -2958,6 +2967,7 @@ isearch-pre-command-hook ;; Other characters terminate the search and are then executed normally. (search-exit-option (isearch-done) + (isearch-clean-regions) (isearch-clean-overlays))))) (defun isearch-post-command-hook () @@ -3312,6 +3322,22 @@ isearch-search-fun-function This returned function will be used by `isearch-search-string' to search for the first occurrence of STRING.") +(defun isearch--find-text-property-region (pos prop) + "Find a region around POS containing PROP text property. +Return nil when PROP is not set at POS." + (let* ((beg (and (get-text-property pos prop) pos)) + (end beg)) + (when beg + (unless (or (equal beg (point-min)) + (not (eq (get-text-property beg prop) + (get-text-property (1- beg) prop)))) + (setq beg (previous-single-property-change pos prop nil (point-min)))) + (unless (or (equal end (point-max)) + (not (eq (get-text-property end prop) + (get-text-property (1+ end) prop)))) + (setq end (next-single-property-change pos prop nil (point-max)))) + (cons beg end)))) + (defun isearch-search-fun () "Return the function to use for the search. Can be changed via `isearch-search-fun-function' for special needs." @@ -3421,8 +3447,9 @@ isearch-search (if (or (not isearch-success) (bobp) (eobp) (= (match-beginning 0) (match-end 0)) - (funcall isearch-filter-predicate - (match-beginning 0) (match-end 0))) + (save-match-data + (funcall isearch-filter-predicate + (match-beginning 0) (match-end 0)))) (setq retry nil))) (setq isearch-just-started nil) (if isearch-success @@ -3481,6 +3508,20 @@ isearch-open-overlay-temporary (overlay-put ov 'isearch-invisible (overlay-get ov 'invisible)) (overlay-put ov 'invisible nil))) +;; Same as `isearch-open-overlay-temporary', but for text hidden via text +;; properties. +(defun isearch-open-region-temporary (hidden-region) + (if (not (null (get-text-property (car hidden-region) 'isearch-open-invisible-temporary))) + (funcall (get-text-property (car hidden-region) 'isearch-open-invisible-temporary) hidden-region nil) + (with-silent-modifications + (put-text-property (car hidden-region) + (cdr hidden-region) + 'isearch-invisible + (get-text-property (point) 'invisible)) + (put-text-property (car hidden-region) + (cdr hidden-region) + 'invisible + nil)))) ;; This is called at the end of isearch. It will open the overlays ;; that contain the latest match. Obviously in case of a C-g the @@ -3501,6 +3542,23 @@ isearch-open-necessary-overlays (if fct-temp (funcall fct-temp ov t))))) +;; Equivalent of `isearch-open-necessary-overlays' for text hidden via text +;; properties. +(defun isearch-open-necessary-region (region) + (let ((inside-region (and (> (point) (car region)) + (<= (point) (cdr region)))) + (fct-temp (get-text-property (car region) 'isearch-open-invisible-temporary))) + (when (or inside-region (not fct-temp)) + (with-silent-modifications + (put-text-property (car region) + (cdr region) + 'invisible + (get-text-property (car region) 'isearch-invisible)) + (remove-text-properties (car region) (cdr region) '('isearch-invisible nil)))) + (if inside-region + (funcall (get-text-property (car region) 'isearch-open-invisible) region) + (when fct-temp (funcall fct-temp region t))))) + ;; This is called when exiting isearch. It closes the temporary ;; opened overlays, except the ones that contain the latest match. (defun isearch-clean-overlays () @@ -3508,6 +3566,10 @@ isearch-clean-overlays (mapc 'isearch-open-necessary-overlays isearch-opened-overlays) (setq isearch-opened-overlays nil))) +(defun isearch-clean-regions () + (when isearch-opened-regions + (mapc 'isearch-open-necessary-region isearch-opened-regions) + (setq isearch-opened-regions nil))) (defun isearch-intersects-p (start0 end0 start1 end1) "Return t if regions START0..END0 and START1..END1 intersect." @@ -3535,6 +3597,21 @@ isearch-close-unnecessary-overlays (overlay-put ov 'invisible (overlay-get ov 'isearch-invisible)) (overlay-put ov 'isearch-invisible nil))))))) +(defun isearch-close-unnecessary-regions (begin end) + (let ((regions isearch-opened-regions)) + (setq isearch-opened-regions nil) + (dolist (region regions) + (if (isearch-intersects-p begin end (car region) (cdr region)) + (push region isearch-opened-regions) + (let ((fct-temp (get-text-property (car region) 'isearch-open-invisible-temporary))) + (if fct-temp + (funcall fct-temp region t) + (with-silent-modifications + (put-text-property (car region) + (cdr region) + 'invisible + (get-text-property (car region) 'isearch-invisible)) + (remove-text-properties (car region) (cdr region) '('isearch-invisible nil))))))))) (defun isearch-range-invisible (beg end) "Return t if all the text from BEG to END is invisible." @@ -3542,52 +3619,70 @@ isearch-range-invisible ;; Check that invisibility runs up to END. (save-excursion (goto-char beg) - (let (;; can-be-opened keeps track if we can open some overlays. - (can-be-opened (eq search-invisible 'open)) + (let (;; can-be-opened keeps track if we can open some hidden text. + (can-be-opened (memq search-invisible '(open open-all))) + (region-can-be-opened (eq search-invisible 'open-all)) ;; the list of overlays that could be opened - (crt-overlays nil)) + (crt-overlays nil) + (crt-regions nil)) (when (and can-be-opened isearch-hide-immediately) - (isearch-close-unnecessary-overlays beg end)) + (isearch-close-unnecessary-overlays beg end) + (when region-can-be-opened (isearch-close-unnecessary-regions beg end))) ;; If the following character is currently invisible, ;; skip all characters with that same `invisible' property value. ;; Do that over and over. (while (and (< (point) end) (invisible-p (point))) - (if (invisible-p (get-text-property (point) 'invisible)) - (progn - (goto-char (next-single-property-change (point) 'invisible - nil end)) - ;; if text is hidden by an `invisible' text property - ;; we cannot open it at all. - (setq can-be-opened nil)) - (when can-be-opened - (let ((overlays (overlays-at (point))) - ov-list - o - invis-prop) - (while overlays - (setq o (car overlays) - invis-prop (overlay-get o 'invisible)) - (if (invisible-p invis-prop) - (if (overlay-get o 'isearch-open-invisible) - (setq ov-list (cons o ov-list)) - ;; We found one overlay that cannot be - ;; opened, that means the whole chunk - ;; cannot be opened. - (setq can-be-opened nil))) - (setq overlays (cdr overlays))) - (if can-be-opened - ;; It makes sense to append to the open - ;; overlays list only if we know that this is - ;; t. - (setq crt-overlays (append ov-list crt-overlays))))) - (goto-char (next-overlay-change (point))))) - ;; See if invisibility reaches up thru END. - (if (>= (point) end) - (if (and can-be-opened (consp crt-overlays)) - (progn + (when (invisible-p (get-text-property (point) 'invisible)) + (if (and can-be-opened region-can-be-opened) + (let ((region (isearch--find-text-property-region (point) 'invisible))) + ;; If the region info is passed to user-defined + ;; function, tell that function what we actually + ;; want to reveal. + (when (< (car region) beg) (setcar region beg)) + (when (> (cdr region) end) (setcdr region end)) + (if (get-text-property (point) 'isearch-open-invisible) + (push region crt-regions) + (goto-char (next-single-property-change (point) 'invisible + nil end)) + (setq can-be-opened nil))) + (goto-char (next-single-property-change (point) 'invisible + nil end)) + ;; if text is hidden by an `invisible' text property + ;; we cannot open it at all. + (setq can-be-opened nil))) + (when can-be-opened + (let ((overlays (overlays-at (point))) + ov-list + o + invis-prop) + (while overlays + (setq o (car overlays) + invis-prop (overlay-get o 'invisible)) + (if (invisible-p invis-prop) + (if (overlay-get o 'isearch-open-invisible) + (setq ov-list (cons o ov-list)) + ;; We found one overlay that cannot be + ;; opened, that means the whole chunk + ;; cannot be opened. + (setq can-be-opened nil))) + (setq overlays (cdr overlays))) + (if can-be-opened + ;; It makes sense to append to the open + ;; overlays list only if we know that this is + ;; t. + (setq crt-overlays (append ov-list crt-overlays))))) + (goto-char (next-single-char-property-change (point) 'invisible))) + ;; See if invisibility reaches up thru END. + (if (>= (point) end) + (if (and can-be-opened (or (consp crt-overlays) + (consp crt-regions))) + (progn (setq isearch-opened-overlays - (append isearch-opened-overlays crt-overlays)) + (append isearch-opened-overlays crt-overlays)) (mapc 'isearch-open-overlay-temporary crt-overlays) + (setq isearch-opened-regions + (append isearch-opened-regions crt-regions)) + (mapc 'isearch-open-region-temporary crt-regions) nil) (setq isearch-hidden t))))))) [-- Attachment #3: Type: text/plain, Size: 1206 bytes --] Stefan Monnier <monnier@iro.umontreal.ca> writes: >> - text hidden via text properties is not well-handled by isearch. For >> overlays, isearch can temporary reveal the hidden text, which is not >> the case for text hidden using 'invisible text property. > > The recommending way to avoid this problem is to provide a patch which > extends Isearch's handling of invisible text to text-properties. > There's no reason to presume it would be hard to do. > >> - text properties are not buffer-local in indirect buffers. With >> overlays, it is possible to have define hidden text in basic and >> indirect buffer independently. However, text properties will always be >> shared and the text hidden in indirect buffer will automatically be >> hidden in the base buffer as well. > > And the way I recommend to avoid this problem is to stay clear of > indirect buffers (which I consider as an attractive nuisance). > > > Stefan > -- Ihor Radchenko, PhD, Center for Advancing Materials Performance from the Nanoscale (CAMP-nano) State Key Laboratory for Mechanical Behavior of Materials, Xi'an Jiaotong University, Xi'an, China Email: yantar92@gmail.com, ihor_radchenko@alumni.sutd.edu.sg ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-27 11:20 ` Ihor Radchenko @ 2020-07-28 16:43 ` Jeff Norden 2020-07-28 16:58 ` Yuan Fu 2020-07-29 1:52 ` Ihor Radchenko 2020-07-28 23:53 ` Juri Linkov 1 sibling, 2 replies; 17+ messages in thread From: Jeff Norden @ 2020-07-28 16:43 UTC (permalink / raw) To: Ihor Radchenko; +Cc: eliz, monnier, emacs-devel > I am currently working on re-implementing org-mode folding from using > overlays to text-properties. It's interesting that you are working to change org's overlays back to text properties, while I'm considering doing exactly the opposite for the project that I've been playing with. Do org buffers routinely wind up with thousands of overlays? > Stefan Monnier <monnier@iro.umontreal.ca> writes: >> ... >> And the way I recommend to avoid this problem is to stay clear of >> indirect buffers (which I consider as an attractive nuisance). From what little I've seen of them, I'm quite inclined to agree with Stefan's opinion about indirect buffers. Is their main use in org to provide multiple views of a buffer with different foldings? I wonder if it might be possible to implement a "window-invisibility-spec", that would override the buffer-spec when set. It would have to be done in C, not lisp. You might even want to add a new field in the window structure. I have no real clue as to whether this is possible, feasible, or a good idea. But it might provide a nice way to display a single buffer in two different windows with different levels of hidden text. It seems like it would be a lot simpler than using indirect buffers, but I'm certainly no expert on this. Regards, -Jeff ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-28 16:43 ` Jeff Norden @ 2020-07-28 16:58 ` Yuan Fu 2020-07-28 17:05 ` Eric Abrahamsen 2020-07-29 1:52 ` Ihor Radchenko 1 sibling, 1 reply; 17+ messages in thread From: Yuan Fu @ 2020-07-28 16:58 UTC (permalink / raw) To: Jeff Norden; +Cc: eliz, emacs-devel, Ihor Radchenko, monnier [-- Attachment #1: Type: text/plain, Size: 384 bytes --] > On Jul 28, 2020, at 12:43 PM, Jeff Norden <jnorden@tntech.edu> wrote: > > From what little I've seen of them, I'm quite inclined to agree with > Stefan's opinion about indirect buffers. Is their main use in org to > provide multiple views of a buffer with different foldings? AFAIK org-sidebar relies on that: the sidebar showing headings is an indirect buffer. Yuan [-- Attachment #2: Type: text/html, Size: 3105 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-28 16:58 ` Yuan Fu @ 2020-07-28 17:05 ` Eric Abrahamsen 0 siblings, 0 replies; 17+ messages in thread From: Eric Abrahamsen @ 2020-07-28 17:05 UTC (permalink / raw) To: Yuan Fu; +Cc: eliz, monnier, Ihor Radchenko, Jeff Norden, emacs-devel Yuan Fu <casouri@gmail.com> writes: >> On Jul 28, 2020, at 12:43 PM, Jeff Norden <jnorden@tntech.edu> wrote: >> >> From what little I've seen of them, I'm quite inclined to agree with >> Stefan's opinion about indirect buffers. Is their main use in org to >> provide multiple views of a buffer with different foldings? > > AFAIK org-sidebar relies on that: the sidebar showing headings is an indirect buffer. An important use is the capture system: when capturing text to be inserted in an Org buffer, the text is entered in an indirect buffer, so that it's already in place as the user is typing. The old system used a temporary buffer, then inserted the text on finalization. I don't remember the whole history, but I do remember that switching to indirect buffers solved several issues, and ended up being a pretty clean solution to the problem. I think they still have their uses. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-28 16:43 ` Jeff Norden 2020-07-28 16:58 ` Yuan Fu @ 2020-07-29 1:52 ` Ihor Radchenko 2020-07-30 18:21 ` Jeff Norden 1 sibling, 1 reply; 17+ messages in thread From: Ihor Radchenko @ 2020-07-29 1:52 UTC (permalink / raw) To: Jeff Norden; +Cc: eliz, monnier, emacs-devel > It's interesting that you are working to change org's overlays back to > text properties, while I'm considering doing exactly the opposite for > the project that I've been playing with. Org is using overlays to fold anything right now, same as outline-mode. What do you mean by "exactly the opposite"? If you need some specific feature that is lacking in text properties, but present in overlays, let me know here or jump into the patch discussion: https://www.mail-archive.com/emacs-orgmode@gnu.org/msg127740.html > Do org buffers routinely wind up with thousands of overlays? It is very common when you have an org file with thousands of headlines each containing a [folded] property drawer. I provided an example org file in the patch discussion: https://www.mail-archive.com/emacs-orgmode@gnu.org/msg127740.html > From what little I've seen of them, I'm quite inclined to agree with > Stefan's opinion about indirect buffers. Is their main use in org to > provide multiple views of a buffer with different foldings? Another common use is narrowing to subtrees, so that you have two buffers with different narrowing for the same org file. It is not possible within a single buffer, as far I as know. > I wonder if it might be possible to implement a "window-invisibility-spec", > that would override the buffer-spec when set. It would have to be done > in C, not lisp. You might even want to add a new field in the window > structure. I have no real clue as to whether this is possible, feasible, > or a good idea. But it might provide a nice way to display a single buffer > in two different windows with different levels of hidden text. It seems > like it would be a lot simpler than using indirect buffers, but I'm > certainly no expert on this. I do not think that it is a good idea for this spefic case. If I understand correctly, the only advantage of such approach would the fact that you do not need to create an indirect buffer. However, there is a problem with "window-local" approach. Anything that is "window-local" implies that it can affect **any** buffer shown in that window. So, we will need to handle buffer changes without adding any extra benefit in comparison with indirect buffer approach. Not to mention, that the ability to have independent narrow states will be lost. Best, Ihor Jeff Norden <jnorden@tntech.edu> writes: >> I am currently working on re-implementing org-mode folding from using >> overlays to text-properties. > > It's interesting that you are working to change org's overlays back to > text properties, while I'm considering doing exactly the opposite for > the project that I've been playing with. Do org buffers routinely wind > up with thousands of overlays? > >> Stefan Monnier <monnier@iro.umontreal.ca> writes: >>> ... >>> And the way I recommend to avoid this problem is to stay clear of >>> indirect buffers (which I consider as an attractive nuisance). > > From what little I've seen of them, I'm quite inclined to agree with > Stefan's opinion about indirect buffers. Is their main use in org to > provide multiple views of a buffer with different foldings? > > I wonder if it might be possible to implement a "window-invisibility-spec", > that would override the buffer-spec when set. It would have to be done > in C, not lisp. You might even want to add a new field in the window > structure. I have no real clue as to whether this is possible, feasible, > or a good idea. But it might provide a nice way to display a single buffer > in two different windows with different levels of hidden text. It seems > like it would be a lot simpler than using indirect buffers, but I'm > certainly no expert on this. > > Regards, > -Jeff -- Ihor Radchenko, PhD, Center for Advancing Materials Performance from the Nanoscale (CAMP-nano) State Key Laboratory for Mechanical Behavior of Materials, Xi'an Jiaotong University, Xi'an, China Email: yantar92@gmail.com, ihor_radchenko@alumni.sutd.edu.sg ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-29 1:52 ` Ihor Radchenko @ 2020-07-30 18:21 ` Jeff Norden 0 siblings, 0 replies; 17+ messages in thread From: Jeff Norden @ 2020-07-30 18:21 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-devel >> ... inclined to agree with Stefan's opinion about indirect buffers. > Another common use is narrowing to subtrees, so that you have two > buffers with different narrowing for the same org file. It is not > possible within a single buffer, as far I as know. So the org case for indirect buffers is messier than I had imagined, which shouldn't surprise me. I'm a very casual user of org - just as an alternative to outline-mode for the cycling and the intuitive use of the tab key. > What do you mean by "exactly the opposite"? I was working on changing some text-property based code to use overlays instead, but I'm having second thoughts. Overlays simplified some things, but not as much as I thought they would. I also ran into a couple of snags: 1) There don't seem to be 'char-property' versions of text-property-any or text-property-not-all. I guess you could do this in lisp with a loop using next-char-property-change, but that works against my original goal of simplifying things. 2) A simple option that you have for protecting hidden text when using text-properties is to temporarily mark it as read-only, e.g.: (add-text-properties beg end '(invisible t read-only t)) Of course, you need to make sure you remove both properties when you un-hide (and take into account that you are now changing read-only text). It also means that you can't kill or delete a region that contains hidden text without un-hiding it first. That may or may not be a good thing, depending on your perspective. There might also be other side-effects that I'm not thinking of right now. --- I just looked at org a bit more and discovered org-catch-invisible-edits. It works, in part, because org re-binds the keys that usually call delete-char and delete-backward-char. I tried it, and found that even with catch-invisible-edits set to 'error, if you put the cursor right before an ellipsis and type M-d, the first word in the hidden text is silently deleted. I wouldn't say this is a bug or problem, since it is hard to imagine someone doing that accidentally. I just thought it was interesting. Best regards, -Jeff ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-27 11:20 ` Ihor Radchenko 2020-07-28 16:43 ` Jeff Norden @ 2020-07-28 23:53 ` Juri Linkov 2020-07-29 1:36 ` Ihor Radchenko 1 sibling, 1 reply; 17+ messages in thread From: Juri Linkov @ 2020-07-28 23:53 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Eli Zaretskii, Jeff Norden, Stefan Monnier, emacs-devel > I am currently working on re-implementing org-mode folding from using > overlays to text-properties. Any chance to fix also bug#40808? It's still open because there is no solution for isearching invisible text in org-mode. Here's a short test case that demonstrates the problem in org-mode: 0. emacs -Q 1. visit emacs/etc/ORG-NEWS 2. isearch for "http": C-s http C-s C-s C-s ... it eventually stops at org links where "http" is invisible, such as [[https://orgmode.org/worg/library-of-babel.html][here]] The problem is that org-mode puts the text property 'invisible' only when the link is scrolled into view, I guess it puts the property using font-lock. So it seems org-mode needs to use font-lock-ensure on the line with the next search hit before calling isearch-filter-predicate on the found occurence. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-28 23:53 ` Juri Linkov @ 2020-07-29 1:36 ` Ihor Radchenko 2020-07-30 23:04 ` Juri Linkov 0 siblings, 1 reply; 17+ messages in thread From: Ihor Radchenko @ 2020-07-29 1:36 UTC (permalink / raw) To: Juri Linkov; +Cc: Eli Zaretskii, Jeff Norden, Stefan Monnier, emacs-devel > Any chance to fix also bug#40808? It's still open because there is > no solution for isearching invisible text in org-mode. Thanks for pointing out this bug. Searching actually works fine on my feature branch + patched isearch (though it is actually an unintended side-effect). However, (setq isearch-lazy-count t) leaves the last headline open. I will need to investigate this. > The problem is that org-mode puts the text property 'invisible' > only when the link is scrolled into view, I guess it puts the property > using font-lock. > > So it seems org-mode needs to use font-lock-ensure on the line > with the next search hit before calling isearch-filter-predicate > on the found occurence. I am currently undecided about searchability of hidden text in links. Do I understand correctly that you prefer the hidden parts of links to be searchable? Either way is possible. If hidden parts are searchable, it will be even possible to show them temporarily. Best, Ihor Juri Linkov <juri@linkov.net> writes: >> I am currently working on re-implementing org-mode folding from using >> overlays to text-properties. > > Any chance to fix also bug#40808? It's still open because there is > no solution for isearching invisible text in org-mode. > > Here's a short test case that demonstrates the problem in org-mode: > > 0. emacs -Q > 1. visit emacs/etc/ORG-NEWS > 2. isearch for "http": C-s http C-s C-s C-s ... > > it eventually stops at org links where "http" is invisible, such as > > [[https://orgmode.org/worg/library-of-babel.html][here]] > > The problem is that org-mode puts the text property 'invisible' > only when the link is scrolled into view, I guess it puts the property > using font-lock. > > So it seems org-mode needs to use font-lock-ensure on the line > with the next search hit before calling isearch-filter-predicate > on the found occurence. -- Ihor Radchenko, PhD, Center for Advancing Materials Performance from the Nanoscale (CAMP-nano) State Key Laboratory for Mechanical Behavior of Materials, Xi'an Jiaotong University, Xi'an, China Email: yantar92@gmail.com, ihor_radchenko@alumni.sutd.edu.sg ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: A question about overlays and performance. 2020-07-29 1:36 ` Ihor Radchenko @ 2020-07-30 23:04 ` Juri Linkov 0 siblings, 0 replies; 17+ messages in thread From: Juri Linkov @ 2020-07-30 23:04 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Eli Zaretskii, Jeff Norden, Stefan Monnier, emacs-devel >> Any chance to fix also bug#40808? It's still open because there is >> no solution for isearching invisible text in org-mode. > > Thanks for pointing out this bug. Searching actually works fine on my > feature branch + patched isearch (though it is actually an unintended > side-effect). However, (setq isearch-lazy-count t) leaves the last > headline open. I will need to investigate this. Leaving the last headline open is a known bug fixed in https://debbugs.gnu.org/40808#8 Here it's explaned: "And also it fixes an old bug existed in previous Emacs versions where lazy-highlight didn't update lazy-highlighting when a hidden outline was automatically opened at the end of the file (I noticed this bug only now). So the condition ‘(eq search-invisible 'open)’ fixes an old bug..." >> The problem is that org-mode puts the text property 'invisible' >> only when the link is scrolled into view, I guess it puts the property >> using font-lock. >> >> So it seems org-mode needs to use font-lock-ensure on the line >> with the next search hit before calling isearch-filter-predicate >> on the found occurence. > > I am currently undecided about searchability of hidden text in links. Do > I understand correctly that you prefer the hidden parts of links to be > searchable? Either way is possible. If hidden parts are searchable, it > will be even possible to show them temporarily. The hidden parts of links should be searchable when the value of 'search-invisible' is 't' ("Match hidden text"). ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2020-07-30 23:04 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-07-25 16:40 A question about overlays and performance Jeff Norden 2020-07-25 16:53 ` Eli Zaretskii 2020-07-25 17:24 ` Jeff Norden 2020-07-25 17:29 ` Eli Zaretskii 2020-07-26 1:33 ` Ihor Radchenko 2020-07-26 13:56 ` Eli Zaretskii 2020-07-26 14:19 ` Ihor Radchenko 2020-07-26 14:44 ` Stefan Monnier 2020-07-27 11:20 ` Ihor Radchenko 2020-07-28 16:43 ` Jeff Norden 2020-07-28 16:58 ` Yuan Fu 2020-07-28 17:05 ` Eric Abrahamsen 2020-07-29 1:52 ` Ihor Radchenko 2020-07-30 18:21 ` Jeff Norden 2020-07-28 23:53 ` Juri Linkov 2020-07-29 1:36 ` Ihor Radchenko 2020-07-30 23:04 ` Juri Linkov
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).