Skip to main content
1 of 6
Gabriele
  • 1.7k
  • 11
  • 22

Make region(s) invisible (not evaluated) to "string-match", "occur" and similar commands

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))))))
Gabriele
  • 1.7k
  • 11
  • 22