3

I want to replace all hard column widths in several LaTeX-documents, e.g. replace {90mm} by {0.75\textwidth}. I already found out that you can use \, and #1 to so arithmetics on captured groups, like e.g. here. But I can't get it to work in a lisp function. I tried several things to no avail, and now would like if this is possible at all, and if yes, how.

Here's something that I came up with that doesn't work:

(defun colum-width-relative ()
  ""
  (interactive)
  (beginning-of-buffer)
  (save-excursion 
    (query-replace-regexp 
     "{\\([0-9]+\\)mm}"
     (concat "{0." \,(/ (* #1 100) 120) "\\\\textwidth}"))))
  • query-replace-regexp is intended for interactive use, the way to do this is to use re-search-forward in a loop, based on (match-string 1) make a decision about the new value of text width, and then use replace-match to substitute it with the new value. – wvxvw Jun 22 '17 at 8:25
  • @wvxvw: Would you care to formulate this as an answer? – Shylock Jun 22 '17 at 8:47
6

Here's an example. See if I understood the problem correctly.

(defun colum-width-relative ()
  ""
  (interactive)
  (beginning-of-buffer)
  (save-excursion
    (while (re-search-forward "{\\([0-9]+\\)mm}" nil t)
      (replace-match
       (format "{%0.2f\\\\textwidth}"
               (/ (string-to-number (match-string 1)) 120.0))))))

Here's an extended version:

(defun colum-width-relative (arg)
  (interactive "P")
  (beginning-of-buffer)
  (cl-labels ((replacer
               (&rest _)
               (format "{%0.2f\\\\textwidth}"
                       (/ (string-to-number (match-string 1)) 120.0))))
    (let ((re "{\\([0-9]+\\)mm}"))
      (save-excursion
        (if arg
            (perform-replace re (list #'replacer) t t nil)
          (while (re-search-forward re nil t)
            (replace-match (replacer))))))))

If you call the extended version with prefix argument, i.e. C-u M-xcolumn-width-relative it will query you before replacing every instance matching regular expression.

  • Works great, but as a paranoid person I don't like to just replace stuff without double checking it. Is there a kind of query-replace-match that lets me decide for each case individually (pressing y or n)? – Shylock Jun 22 '17 at 10:02
  • @Shylock I've added a version which will query before replacing. – wvxvw Jun 22 '17 at 11:00
  • Wow, thanks! This saves me quite a bit of time. Once I reach 15 points you'll also feel the gratitude in form of a counted upvote :D – Shylock Jun 22 '17 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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