In a previous question, Make region(s) invisible (not evaluated) to query-replacy and similar commands, I learned about isearch-filter-predicate
. Now I wonder if is there a similar method to make regions invisible to functions as string-match
, occur etc.
As an example I have this LaTeX
code:
\begin{eqnarray}
\begin{matrix}
\newline
\end{matrix}
\end{eqnarray}
I use string-match-p
to test if the \newline
(\\
) string occurs in the LaTeX
eqnarray
environment. If nil
I replace "eqnarray" --> "equation". I also need to "ignore" newlines that occur in sub-enviroments like matrix
, so I thought I could make the regions of these sub-enviroments "invisible" to the string-match-p
function.
Is there a way to do it? Alternatively I thought I could write the isearch-filter-predicate
combined with the search-forward-regexp
function to test for the occurrence of my target string in the region.
This is the code I wrote:
(defun skip-if-my-ignore (beg end)
"Return nil if some text BEG to END has non-`nil' property `my-ignore'."
(catch 'skip-if-my-ignore
(let ((pos beg))
(while (< pos end)
(when (get-text-property pos 'my-ignore) (throw 'skip-if-my-ignore nil))
(setq pos (1+ pos))))
t))
(defun test-invisibility ()
(interactive)
(save-excursion
(let* ((a (copy-marker (point-min)))
(SUB_ENVIRONMENTS (regexp-opt '(
"array"
"cases"
"pmatrix"
"matrix"
))))
(unwind-protect
(progn
(goto-char a)
(while (search-forward-regexp (concat
"\\\\begin{"
"\\(" SUB_ENVIRONMENTS "\\)"
"}")
nil t)
(save-excursion
(let* ((b (copy-marker (match-beginning 0)))
(SUB_ENV (match-string 1))
(e (copy-marker (search-forward-regexp
(concat "\\\\end{" SUB_ENV "}") nil t))))
(put-text-property b e 'my-ignore t)
(save-restriction
(narrow-to-region b e)
(let ((isearch-filter-predicate 'skip-if-my-ignore))
;; should not ask for replacements (in sub-environments)
(perform-replace "\\\\newline" "MATCHED" t t nil 1 nil b e)
(if (string-match-p "\\\\newline" (buffer-substring b e))
(read-string "string-match-p matched the string. I don't want this!")
(read-string "string-match-p didn't match the string. I WANT THIS!"))
(if (search-forward-regexp "\\\\newline" e t)
(read-string "search-forward-regexp matched the string. I don't want this!")
(read-string "search-forward-regexp didn't match the string. I WANT THIS!"))
;; should not find occurrences in the sub-environments:
(occur "\\\\newline" 1))))))))
;; *UNWINDFORMS
(remove-list-of-text-properties (point-min) (point-max) '(my-ignore))))))