emacs: search and replace on a region

Viewed 238

So, I have this excellent function (that someone made for me) for doing multiple search and replaces on an entire buffer.

(defun accent-replace-whole-buffer ()
  "Corrects macrons from badly scanned latin"
  (interactive "*")
  (dolist (ele (list ?â ?ä ?ê ?ë ?î ?ô ?ü ?ï))
    (setq elt (char-to-string ele))
    (goto-char (point-min))
    (while (search-forward elt nil t 1)
      (replace-match
       (char-to-string
        (pcase ele
          (`?â ?ā)
          (`?ä ?ā)
          (`?ê ?ē)
          (`?ë ?ē)
          (`?î ?ī)
          (`?ô ?ō)     
          (`?ü ?ū)
          (`?ï ?ī)))))))

and I would like to make another function, which does this, only on the selected region.

How would I go about this? Is there a nice tutorial anywhere?

2 Answers

Use narrow-to-region, inside save-restriction:

(defun accent-replace-in-region (begin end)
  "Corrects macrons in active region from badly scanned latin"
  (interactive "*r")
  (save-restriction
    (narrow-to-region begin end)
    (dolist (ele (list ?ā ?ā ?ē ?ē ?ī ?ō ?ū ?ī))
      (setq elt (char-to-string ele))
      (goto-char (point-min))
      (while (search-forward elt nil t 1)
        (replace-match
         (char-to-string
          (pcase ele
            (`?â ?ā)
            (`?ä ?ā)
            (`?ê ?ē)
            (`?ë ?ē)
            (`?î ?ī)
            (`?ô ?ō)     
            (`?ü ?ū)
            (`?ï ?ī))))))))

Instead of the builtin interactive code "r", using that form:

(defun MYFUNTION (&optional beg end)
  (interactive "*") 
  (let ((beg (cond (beg)
           ((use-region-p)
            (region-beginning))
           (t (point-min))))
    (end (cond (end (point-marker end))
           ((use-region-p)
            (point-marker (region-end)))
           (t (point-marker (point-max))))))
    (and beg end (narrow-to-region beg end))
    (goto-char beg)
    ;; here some replace example revealing the problem mentioned
    (while (re-search-forward "." end t 1)
      (replace-match "+++++++++"))))

Basically two reasons for this: Make sure, the region is visible when acting upon. "r" doesn't care for transient-mark-mode. Unfortunately use-region-p also has some quirks. Second reason: end needs to be updated when a replacing will change the length of the region.

Related