2
votes

I have created a regular expression with re-builder in Emacs. I use C-c C-w to copy it to the kill-ring.

The kill-ring shows:

"\\(defun\\)"

First, I modified the copy function to get rid of the "".

\\(defun\\)

My other problem is, the regex in the kill-ring contains double backslashes, rendering it unusable for functions like query-replace-regexp, which I want to yank it back into from the kill-ring.

These functions expect single backslashes, like

\(defun\)

So I thought I could replace the '\\' with the '\' before copying it to the kill-ring by doing this:

(replace-regexp-in-string "\\\\" "\\" "\\(defun\\)" nil t)

When executing the function the minibuffer shows "\\(defun\\)" instead of "\(defun\)" as a result.

What am I doing wrong?

5

5 Answers

2
votes

Passing your string through 'insert or 'princ does the substitution for you.

(princ "\\(defun\\)")
->
\(defun\)

I don't see the obvious way to do this directly, here's a really convoluted way that seems to work with the test strings for me:

(defun my-insert-kill ()
  "convoluted way to replace \\ in strings"
  (interactive)
  (princ (with-temp-buffer
           (insert "(progn (princ ")
           (insert (current-kill 0))
           (insert ") (insert \"\n\") nil)")
           (eval-print-last-sexp)
           (backward-sexp) (backward-char)
           (let ((p (point)))
             (goto-char (point-min))
             (forward-sexp) (forward-char)
             (buffer-substring (point) p)))
         (current-buffer)))
2
votes

This works for me:

(defun my-reb-copy ()
  "Copy current RE into the kill ring without quotes and single
backslashes for later insertion."
  (interactive)
  (reb-update-regexp)
  (let* ((re (with-output-to-string
               (print (reb-target-binding reb-regexp))))
         (str (substring re 2 (- (length re) 2))))
    (with-temp-buffer
      (insert str)
      (goto-char (point-min))
      (while (search-forward "\\\\" nil t)
        (replace-match "\\" nil t))
      (kill-new (buffer-substring (point-min) (point-max))))
    (message "Regexp copied to kill-ring")))

(define-key reb-mode-map "\C-c\C-t" 'my-reb-copy)
1
votes

re-builder+.el has some extensions to re-builder that provides functions for using re-builder with query-replace-regexp and replace-regexp.

http://www.emacswiki.org/emacs/re-builder+.el

0
votes

Something like this?

(defun my-yank-unstring ()
  (interactive)
  (insert (car (read-from-string (current-kill 0)))))

(Thanks to Trey for the (current-kill 0) bit.)

0
votes

Taking a step back, you could set the variable reb-re-syntax to string instead of the default read. This will change the behavior of re-builder to use single backslashes instead of double.

To do this using customize:

M-x customize-variable RET rev-re-syntax RET

Or add to your .emacs file:

(set reb-re-syntax 'string)

Then, to jump directly into replacement, you could use this defun:

(defun reb-query-replace (to-string)
  "Replace current RE from point with `query-replace-regexp'."
  (interactive
   (progn (barf-if-buffer-read-only)
          (list (query-replace-read-to (reb-target-binding reb-regexp)
                                       "Query replace"  t))))
  (with-current-buffer reb-target-buffer
    (query-replace-regexp (reb-target-binding reb-regexp) to-string)))