开发者

Emacs: how do I replace-regexp with a lisp function in a defun?

For example I want to make all text in parenthesis, (), UPCASE. It's trivial to do the following interactively:

M-x query-replace-regexp
replace: "(\(.+?\))"
with   : "(\,(upcase \1))"

Instead I want to write a defun which will do that:

(defun upcs ()
  (interactive)
  (goto-char 1)
  (while (search-forward "(\\(.+?\\))" nil t) (repla开发者_如何转开发ce-match "(\\,(upcase \\1))" t nil)))

but it doesn't work! While the following works (it appends foo and bar to the parenthesized texts):

(defun HOOK ()
  (interactive)
  (goto-char 1)
  (while (search-forward-regexp "(\\(.+?\\))" nil t) (replace-match "(foo \\1 bar)" t nil)))


Luke's answer almost does the job but not quite. The original poster wanted all the text that was enclosed in parenthesis converted to upper case while Luke's code converts the code to upper case AND ALSO removes the parenthesis. A slight modification to the regex provides the correct solution:

(defun upcs ()
(interactive)
(goto-char 1)
    (while (search-forward-regexp "\\([^\\)]+\\)" nil t) 
        (replace-match (upcase (match-string 1)) t nil)))


First of all, you're using search-forward in your first function. This takes a string literal rather than a regular expression. You should be using search-forward-regexp, as you do in your second function.

Secondly, while this code is valid as a replace value for query-replace-regexp, I don't think you can pass it to replace-match:

(\\,(upcase \\1))

You can get the value of the match found by search-forward-regexp using the match-string function.

Finally, I'm not sure your search regular expression is correct.

I think you need something along these lines:

(defun upcs ()
    (interactive)
    (goto-char 1)
        (while (search-forward-regexp "(\\([^\\)]+\\))" nil t) 
            (replace-match (upcase (match-string 1)) t nil)))


So this solves the problem.

(defun put-in-par (str)
  (concat "(" str ")"))

(defun upcs-luke ()
    (interactive)
    (goto-char 1)
        (while (search-forward-regexp "(\\([^\\)]+\\))" nil t) 
            (replace-match (put-in-par (upcase (match-string 1))) t nil)))

Thanks to BillC and Luke Girvin for help.


This was very useful, thanks all.

In the interest of putting more examples on the web, I went from this:

(replace-regexp "\([\%\)\”\"]\..?\)[0-9]+" "\1")

(which didn't work, but which used the regexps that did work in interactive mode)

to this:

(while (re-search-forward "\\([\\%\\\"\\”]\\)\\.?[0-9]+" nil t)
    (replace-match (match-string 1) t nil))

I needed three backslashes before the internal quotation mark.


The interactive regex-based replacement functions cannot change the case but otherwise work fine by default: the case-replace variable needs to be set to nil (default: t). Then interactive replacements then will properly work with ,(upcase \1) and friends.

Reference: See discussion on the emacs-berlin mailing list: https://mailb.org/pipermail/emacs-berlin/2021/000840.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜