1

Suppose I have a function like my-make-invisible, where my-re is some regexp:

(defun my-make-invisible ()
  (save-excursion
    (goto-char (point-min))
    (while (re-search-forward my-re nil t)
      (add-text-properties (match-beginning 0)
                           (match-end 0)
                           '(invisible t)))))

This function just makes each portion of buffer content that matches my-re invisible: it works in all major modes I've tried, but not in org-mode.

Is there an easy way to achieve the same in org-mode?

(Note: adding other properties, like faces or displays, with a function like the one above does work in org-mode. It seems that the problem is only adding invisibility)

I have the same problem if I try to make things invisible by adding them to buffer-invisibility-spec. Except for when the buffer is in org-mode, the following makes the first three characters in the buffer invisible:

(progn (add-text-properties 1 3 '(invisible hide-this-stuff))
       (add-to-invisibility-spec '(hide-this-stuff)))

If I do it in org-mode, hide-this-stuff will show up in the value of buffer-invisibility-spec but this has no effect whatsoever as far as the visibility of those first three characters.

3
  • 1
    AFAIK, the text property conflicts with what font-lock-mode does and since the latter runs in the background, it wins. You can see that that is the case by toggling it off: M-x font-lock-mode. I would guess that you need to do search-based fontification in this case, instead of search based text-property setting. See the Font lock section in the Emacs manual and references therein, particularly the reference to Search-based fontification in the Elisp manual. You can start with C-h i g(emacs)Font lock and go from there.
    – NickD
    Jan 8, 2022 at 11:23
  • Perhaps this question will help, although in my limited experiments I couldn't make it work.
    – NickD
    Jan 8, 2022 at 11:31
  • Thanks @NickD ! This put me on the right track.
    – efl
    Jan 10, 2022 at 0:02

2 Answers 2

2

You might try using overlay properties instead of text properties to avoid conflicts. You can specify a priority to override any exiting overlays.

Modifying your example to this will make make invisible all instances of my-re regexp:

(defun my-make-invisible (my-re)
  (interactive "sRE Search Term: ")
  (save-excursion
    (goto-char (point-min))
    (while (re-search-forward my-re nil t)
      (setq invisible-overlay (make-overlay (match-beginning 0) (match-end 0)))
      (overlay-put invisible-overlay 'invisible t))))

There are a few differences when using overlay properties vs text properties, which may or may not work for your use case. Overlays will not transfer when copy/pasting, for example.

1

You can achieve the same in Org mode even using text properties by adding your own folding specification (see the docstring of variable org-fold-core--specs for details) and then call org-fold-core-region:

(defvar my-re "my regex pattern")

(org-fold-core-add-folding-spec 'my-invisible nil)

(defun my-make-invisible (&optional unfold)
  "Make all matches in buffer for regex `my-re' invisible.
When UNFOLD is non-nil make them visible instead."
  (save-excursion
    (goto-char (point-min))
    (while (re-search-forward my-re nil t)
      (org-fold-core-region (match-beginning 0)
                            (match-end 0)
                            (if unfold nil t)
                            'my-invisible))))

(my-make-invisible)

The commentary section of the built-in Emacs package org-fold-core.el provides a good explanation of how this works. Note that org-fold-core--specs is buffer-local, so you need to call org-fold-core-add-folding-spec in each buffer where you want to use it, for example by adding the call to org-mode-hook.

Also note that it is indeed font-lock-mode that prevents this from working by just adding text properties, as can be confirmed by turning off font-lock-mode.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.