emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: History for query replace pairs


From: Juri Linkov
Subject: Re: History for query replace pairs
Date: Tue, 04 Nov 2014 01:46:47 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (x86_64-pc-linux-gnu)

> This feature seems stalled, is this issue the only thing blocking it?

The only blocking thing is to decide whether to move through the history
of replacements using M-p or M-n.  This patch implements a sequence of M-n
to insert replacement pairs, but it's easy to change just one line from

(read-from-minibuffer
 prompt nil nil nil query-replace-from-history-variable defaults t)))))

to

(read-from-minibuffer
 prompt nil nil nil 'defaults nil t)

then M-p will move through replacement pairs instead of previous
single history strings `from' or `to'.

Maybe this choice should be customizable?

=== modified file 'lisp/replace.el'
--- lisp/replace.el     2014-08-25 02:36:45 +0000
+++ lisp/replace.el     2014-11-03 23:27:28 +0000
@@ -56,8 +56,8 @@ (defvar query-replace-history nil
 
 (defvar query-replace-defaults nil
   "Default values of FROM-STRING and TO-STRING for `query-replace'.
-This is a cons cell (FROM-STRING . TO-STRING), or nil if there is
-no default value.")
+This is a list of cons cells (FROM-STRING . TO-STRING),
+or nil if there is no default values.")
 
 (defvar query-replace-interactive nil
   "Non-nil means `query-replace' uses the last search string.
@@ -67,6 +67,13 @@ (make-obsolete-variable 'query-replace-i
 to the minibuffer that reads the string to replace, or invoke replacements
 from Isearch by using a key sequence like `C-s C-s M-%'." "24.3")
 
+(defvar query-replace-from-to-separator
+  (propertize
+   "\0" 'display (propertize
+                 (if (char-displayable-p ?\u2192) " \u2192 " " -> ")
+                 'face 'minibuffer-prompt))
+  "String that separates FROM and TO in the default replacements.")
+
 (defcustom query-replace-from-history-variable 'query-replace-history
   "History list to use for the FROM argument of `query-replace' commands.
 The value of this variable should be a symbol; that symbol
@@ -132,11 +139,15 @@ (defun query-replace-read-from (prompt r
   (if query-replace-interactive
       (car (if regexp-flag regexp-search-ring search-ring))
     (let* ((history-add-new-input nil)
+          (defaults (mapcar (lambda (from-to)
+                              (concat (query-replace-descr (car from-to))
+                                      query-replace-from-to-separator
+                                      (query-replace-descr (cdr from-to))))
+                            query-replace-defaults))
           (prompt
-           (if query-replace-defaults
-               (format "%s (default %s -> %s): " prompt
-                       (query-replace-descr (car query-replace-defaults))
-                       (query-replace-descr (cdr query-replace-defaults)))
+           (if defaults
+               (format "%s (default %s): " prompt
+                       (car defaults))
              (format "%s: " prompt)))
           (from
            ;; The save-excursion here is in case the user marks and copies
@@ -144,14 +155,18 @@ (defun query-replace-read-from (prompt r
            ;; That should not clobber the region for the query-replace itself.
            (save-excursion
              (if regexp-flag
-                 (read-regexp prompt nil query-replace-from-history-variable)
+                 (read-regexp prompt defaults 
query-replace-from-history-variable)
                (read-from-minibuffer
-                prompt nil nil nil query-replace-from-history-variable
-                (car (if regexp-flag regexp-search-ring search-ring)) t)))))
+                prompt nil nil nil query-replace-from-history-variable
+                defaults t)))))
       (if (and (zerop (length from)) query-replace-defaults)
-         (cons (car query-replace-defaults)
+         (cons (caar query-replace-defaults)
+               (query-replace-compile-replacement
+                (cdar query-replace-defaults) regexp-flag))
+       (let* ((to (if (string-match query-replace-from-to-separator from)
                (query-replace-compile-replacement
-                (cdr query-replace-defaults) regexp-flag))
+                       (substring from (match-end 0)) regexp-flag)))
+              (from (if to (substring from 0 (match-beginning 0)) from)))
        (add-to-history query-replace-from-history-variable from nil t)
        ;; Warn if user types \n or \t, but don't reject the input.
        (and regexp-flag
@@ -163,7 +178,11 @@ (defun query-replace-read-from (prompt r
                ((string= match "\\t")
                 (message "Note: `\\t' here doesn't match a tab; to do that, 
just type TAB")))
               (sit-for 2)))
-       from))))
+         (if (not to)
+             from
+           (add-to-history query-replace-to-history-variable to nil t)
+           (push (cons from to) query-replace-defaults)
+           (cons from to)))))))
 
 (defun query-replace-compile-replacement (to regexp-flag)
   "Maybe convert a regexp replacement TO to Lisp.
@@ -216,7 +235,7 @@ (defun query-replace-read-to (from promp
                 nil nil nil
                 query-replace-to-history-variable from t)))
        (add-to-history query-replace-to-history-variable to nil t)
-       (setq query-replace-defaults (cons from to))
+       (push (cons from to) query-replace-defaults)
        to))
    regexp-flag))
 


> You could use a Unicode character (RIGHT ARROW → for instance), it's
> unlikely to occur in a normal search and replace, and could be specially
> encoded to "→→" in those cases. So you'd store "X→→Y→A→→→→B" to record
> FROM="X→Y" and TO="A→→B".  It's an unambiguous encoding.  If that's too
> hacky, let's find another way, and let me know how I can help.

The patch uses "\0" as a separator that is highly unlikely to occur in
the replacement strings.

Also for better displaying of special characters in the minibuffer,
the following patch modifies isearch-text-char-description used by
query-replace-descr to put a formatted display property on special characters
instead of changing them.  This patch also works better for isearch,
because it keep the faces on the special characters in the failed string.

=== modified file 'lisp/isearch.el'
--- lisp/isearch.el     2014-09-04 16:14:26 +0000
+++ lisp/isearch.el     2014-11-03 23:22:06 +0000
@@ -2873,8 +2873,12 @@ (defun isearch-no-upper-case-p (string r
 
 (defun isearch-text-char-description (c)
   (cond
-   ((< c ?\s) (propertize (format "^%c" (+ c 64)) 'face 'escape-glyph))
-   ((= c ?\^?) (propertize "^?" 'face 'escape-glyph))
+   ((< c ?\s) (propertize
+              (char-to-string c)
+              'display (propertize (format "^%c" (+ c 64)) 'face 
'escape-glyph)))
+   ((= c ?\^?) (propertize
+               (char-to-string c)
+               'display (propertize "^?" 'face 'escape-glyph)))
    (t (char-to-string c))))
 
 ;; General function to unread characters or events.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]