3

In my LaTeX code I want to replace these strings:

\left.\left.\left.
\left.\left.
\left.

with:

\left.\left.\left. \mycommand{3}
\left.\left. \mycommand{2}
\left. \mycommand{1}

where the argument of the command \mycommand is the number of the occurrences of the regexp `"\\left\." in each string.

My question is: can I obtain it by a query-replace? I figured out something like:

(query-replace-regexp "\\(\\(:?\\\\left\\.\\)+\\)"
                      `(,(lambda (x y)
                           (let* ((MATCH (match-string 0))
                                  (OCCURRENCES 
                                   (my-count-regexp "\\\\left\\."
                                                    MATCH))
                                  (OCCURRENCES (number-to-string OCCURRENCES)))
                             (concat MATCH "\\myfunction{" OCCURRENCES "}")))))

But I didn't find a function (my-count-regexp in my code) that returns the occurrences of a regexp in a string.

Also I'm not shure of the lambda function syntax.

Edit. I found that the following code works, but I'm still searching for something simplier:

(query-replace-regexp "\\(\\(:?\\\\left\\.\\)+\\)"
                      `(,(lambda (x y)
                           (let* ((MATCH (match-string 0))
                                  (OCCURRENCES
                                   (with-temp-buffer
                                     (insert MATCH)
                                     (goto-char (point-min))
                                     (count-matches "\\\\left\\.")))
                                  (MATCH (replace-regexp-in-string "\\\\"
                                                                   "\\\\\\\\" MATCH))

                                  (OCCURRENCES (number-to-string OCCURRENCES)))
                             (concat MATCH "\\\\myfunction{" OCCURRENCES "}")))))

3 Answers 3

1

Why not derive the number of occurrences from the length of the match?

(let* ((match (match-string 0))
       (occurrences (/ (length match) 6))
       ...)
   ...)
1
  • Because the matched string may be more complex (e.g. with some tab/space between the \left.s). I really need to count the matched regexp in a string.
    – Gabriele
    Commented Dec 11, 2019 at 19:08
1

I would approach it like this:

(goto-char (point-min))
(while (re-search-forward "\\(\\(\\\\left\\.\\)+\\)" nil t)
  (let ((s (match-beginning 0))
    (e (match-end 0))
    (m (match-string 0)))
  (cl--set-buffer-substring  s e
   (format "%s \\mycommand{%s}"
           m
           (count-matches "\\\\left" s e)))
  (goto-char e)))
0

I know the question is old, and that it asks if it's possible using query replace (although it does not look like anything has to get replaced), but I would still like to add a simple (straightforward) solution here

(goto-char (point-min))
(while (re-search-forward "^\\\\left\\." nil t)
  (let ((count 1)
    (end (line-end-position)))
    (while (re-search-forward "\\\\left\\." end t)
      (cl-incf count))
    (insert (format " \\mycommand{%d}" count))))

Because re-search-forward does not move point if no match is found, the \mycommand{n} is always inserted at the correct position.

The first regexp assumes that the patterns start at the beginning of a line (it includes ^), but this is not required, in that case, just remove the ^.

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.