Subject: bug#25482: 26.0.50; Allow setting `query-replace-from-to-separator` to nil

From: Thierry Volpiatto <[email-masked]>
Date: Sat, 28 Jan 2017 07:50:19 +0100

Just to not leave this unfinished, here the last patch I did which
simplify code.

- defcustom is simple (string or nil).
- No need to reevaluate defcustom at every time.
- setq is usable.
- splitting is now simple with all the text property dance removed.
- plain string is added to history instead of a crap string.

1 file changed, 29 insertions(+), 37 deletions(-)
lisp/replace.el | 66 +++++++++++++++++++++++++--------------------------------

modified   lisp/replace.el
@@ -79,15 +79,12 @@ That becomes the \"string to replace\".")
 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")
 
-(defcustom query-replace-from-to-separator
-  (propertize (if (char-displayable-p ?→) " → " " -> ")
-              'face 'minibuffer-prompt)
-  "String that separates FROM and TO in the history of replacement pairs."
-  ;; Avoids error when attempt to autoload char-displayable-p fails
-  ;; while preparing to dump, also stops customize-rogue listing this.
-  :initialize 'custom-initialize-delay
+(defcustom query-replace-from-to-separator " → "
+  "String that separates FROM and TO in the history of replacement pairs.
+When nil or the string provided not displayable the default separator \" -> \"
+will be used instead."
   :group 'matching
-  :type '(choice string (sexp :tag "Display specification"))
+  :type '(choice string)
   :version "25.1")
 
 (defcustom query-replace-from-history-variable 'query-replace-history
@@ -149,15 +146,12 @@ See `replace-regexp' and `query-replace-regexp-eval'.")
 (defun query-replace-descr (string)
   (mapconcat 'isearch-text-char-description string ""))
 
-(defun query-replace--split-string (string)
-  "Split string STRING at a character with property `separator'"
-  (let* ((length (length string))
-         (split-pos (text-property-any 0 length 'separator t string)))
-    (if (not split-pos)
-        (substring-no-properties string)
-      (cl-assert (not (text-property-any (1+ split-pos) length 'separator t string)))
-      (cons (substring-no-properties string 0 split-pos)
-            (substring-no-properties string (1+ split-pos) length)))))
+(defun query-replace--split-string (string separator)
+  "Split string STRING at `query-replace-from-to-separator'."
+  (cond ((string-match separator string)
+         (cons (substring-no-properties string 0 (match-beginning 0))
+               (substring-no-properties string (match-end 0))))
+        (t (substring-no-properties string))))
 
 (defun query-replace-read-from (prompt regexp-flag)
   "Query and return the `from' argument of a query-replace operation.
@@ -165,49 +159,47 @@ The return value can also be a pair (FROM . TO) indicating that the user
 wants to replace FROM with TO."
   (if query-replace-interactive
       (car (if regexp-flag regexp-search-ring search-ring))
-    ;; Reevaluating will check char-displayable-p that is
-    ;; unavailable while preparing to dump.
-    (custom-reevaluate-setting 'query-replace-from-to-separator)
     (let* ((history-add-new-input nil)
-	   (separator
-	    (when query-replace-from-to-separator
-	      (propertize "\0"
-			  'display query-replace-from-to-separator
-			  'separator t)))
+           (sep-char (and (stringp query-replace-from-to-separator)
+                          (replace-regexp-in-string
+                           " " "" query-replace-from-to-separator)))
+           (separator (propertize
+                       (if (and sep-char
+                                (char-displayable-p (string-to-char sep-char)))
+                           query-replace-from-to-separator
+                         " -> ")
+                       'face 'minibuffer-prompt))
            (minibuffer-history
             (append
-	     (when separator
              (mapcar (lambda (from-to)
                        (concat (query-replace-descr (car from-to))
                                separator
                                (query-replace-descr (cdr from-to))))
-		       query-replace-defaults))
+                     query-replace-defaults)
              (symbol-value query-replace-from-history-variable)))
-	   (minibuffer-allow-text-properties t) ; separator uses text-properties
            (prompt
-	    (if (and query-replace-defaults separator)
-		(format "%s (default %s): " prompt (car minibuffer-history))
+            (if query-replace-defaults
+                (format "%s (default %s %s %s): "
+                        prompt
+                        (query-replace-descr (caar query-replace-defaults))
+                        separator
+                        (query-replace-descr (cdar query-replace-defaults)))
               (format "%s: " prompt)))
            (from
             ;; The save-excursion here is in case the user marks and copies
             ;; a region in order to specify the minibuffer input.
             ;; That should not clobber the region for the query-replace itself.
             (save-excursion
-              (minibuffer-with-setup-hook
-                  (lambda ()
-                    (setq-local text-property-default-nonsticky
-                                (cons '(separator . t) text-property-default-nonsticky)))
               (if regexp-flag
                   (read-regexp prompt nil 'minibuffer-history)
                 (read-from-minibuffer
-                   prompt nil nil nil nil
-                   (car (if regexp-flag regexp-search-ring search-ring)) t)))))
+                 prompt nil nil nil nil (car search-ring) t))))
            (to))
       (if (and (zerop (length from)) query-replace-defaults)
           (cons (caar query-replace-defaults)
                 (query-replace-compile-replacement
                  (cdar query-replace-defaults) regexp-flag))
-        (setq from (query-replace--split-string from))
+        (setq from (query-replace--split-string from separator))
         (when (consp from) (setq to (cdr from) from (car 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.

-- 
Thierry