Subject: bug#18886: 24.4; M-v no longer works in CUA-mode.

From: Kim Storm <[email-masked]>
Date: Thu, 30 Oct 2014 17:46:15 +0100

On 2014-10-30 01:47, Stefan Monnier wrote:
> Hi Kim,
>
> Nice to hear from you again.
Yes, I wish I had more time to dedicate to emacs ...
but there is just too much to do running my own business.

 From my first impressions with 24.4, I can see that
emacs developments are still going strong! Good work!

I have taken a shot at adding the missing cua features to 24.4

I don't have time to try to get up to date with the repository stuff,
so I have just included some patches for you to look at -- please
commit them if you think they are acceptable (they are only lightly
tested so far).

Note that the new defcustom is unconditionally set to ?0
by cua-mode if cua-mode-copy-to-register-0 is enabled (default),

Also, the new replace command only works if save-to-register
is non-nil, as it uses the old-text copy in that register (instead
of saving another copy as the original code in cua did).

Finally, using a C-u arg should replace until eob according to the
doc string -- it actually replaces max 1000000 instances; this
is just laziness on my part.

Kim

--- orig.delsel.el    2014-10-30 14:58:32.000000000 +0100
+++ delsel.el    2014-10-30 17:28:41.000000000 +0100
@@ -54,6 +54,15 @@

  ;;; Code:

+(defcustom delete-selection-save-to-register
+  nil
+  "If non-nil, deleted region text is stored in this register.
+Value must be the register (key) to use."
+  :type '(choice
+      (const :tag "None" nil)
+      (character :tag "Register (Key)"))
+  :group 'editing-basics)
+
  ;;;###autoload
  (defalias 'pending-delete-mode 'delete-selection-mode)

@@ -72,16 +81,73 @@
        (remove-hook 'pre-command-hook 'delete-selection-pre-hook)
      (add-hook 'pre-command-hook 'delete-selection-pre-hook)))

+(defvar delsel--replace-text-or-position nil)
+
  (defun delete-active-region (&optional killp)
    "Delete the active region.
  If KILLP in not-nil, the active region is killed instead of deleted."
-  (if killp
-      ;; Don't allow `kill-region' to change the value of `this-command'.
-      (let (this-command)
-    (kill-region (point) (mark) t))
-    (funcall region-extract-function 'delete-only))
+  (message "delete")
+  (cond (killp
+     ;; Don't allow `kill-region' to change the value of `this-command'.
+     (let (this-command)
+       (kill-region (point) (mark) t)))
+    (delete-selection-save-to-register
+     (set-register delete-selection-save-to-register
+               (funcall region-extract-function t))
+     (setq delsel--replace-text-or-position
+           (cons (current-buffer)
+             (and (consp buffer-undo-list) (car buffer-undo-list))))
+     )
+    (t
+     (funcall region-extract-function 'delete-only)))
    t)

+(defun delete-selection-repeat-replace-region (arg)
+  "Repeat replacing text of highlighted region with typed text.
+Search for the next stretch of text identical to the region last replaced
+by typing text over it and replaces it with the same stretch of text.
+With arg, repeat that many times. C-u means until end of buffer."
+  (interactive "P")
+  (let ((old-text (and delete-selection-save-to-register
+               (get-register delete-selection-save-to-register)))
+    (count (if (consp arg) 1000000 (or (prefix-numeric-value 
current-prefix-arg) 1))))
+    (message "old %s" old-text)
+    (when (and old-text (> (length old-text) 0))
+      ;; If this is the first use after overwriting regions,
+      ;; find the replacement text by looking at the undo list
+      (when (consp delsel--replace-text-or-position)
+    (let ((buffer (car delsel--replace-text-or-position))
+          (elt (cdr delsel--replace-text-or-position)))
+    (setq delsel--replace-text-or-position nil)
+    (with-current-buffer buffer
+      (save-restriction
+        (widen)
+        ;; Find the text that replaced the region via the undo list.
+        (let ((ul buffer-undo-list) u s e)
+          (when elt
+        (while (consp ul)
+          (setq u (car ul) ul (cdr ul))
+          (cond
+           ((eq u elt) ;; got it
+            (setq ul nil))
+           ((and (consp u) (integerp (car u)) (integerp (cdr u)))
+            (if (and s (= (cdr u) s))
+            (setq s (car u))
+              (setq s (car u) e (cdr u)))))))
+          (cond ((and s e (<= s e) (= s (mark t)))
+             (setq delsel--replace-text-or-position 
(filter-buffer-substring s e))
+             (set-text-properties 0 (length 
delsel--replace-text-or-position)
+                      nil delsel--replace-text-or-position))
+            ((and (null s) (eq u elt)) ;; nothing inserted
+             (setq delsel--replace-text-or-position ""))
+            (t
+             (message "Cannot locate replacement text"))))))))
+      (while (and (> count 0)
+          delsel--replace-text-or-position
+         (search-forward old-text nil t nil))
+    (replace-match delsel--replace-text-or-position nil t)
+    (setq count (1- count))))))
+
  (defun delete-selection-helper (type)
    "Delete selection according to TYPE:
   `yank'

--- orig.cua-base.el    2014-10-30 15:40:12.000000000 +0100
+++ cua-base.el    2014-10-30 16:16:08.000000000 +0100
@@ -277,7 +277,7 @@

  (defcustom cua-remap-control-v t
    "If non-nil, C-v binding is used for paste (yank).
-Also, M-v is mapped to `cua-repeat-replace-region'."
+Also, M-v is mapped to `delete-selection-repeat-replace-region'."
    :type 'boolean
    :group 'cua)

@@ -961,46 +961,6 @@
         (if cua--rectangle
             (cua--rectangle-corner 0))))))

-;; Typed text that replaced the highlighted region.
-(defvar cua--repeat-replace-text nil)
-
-(defun cua-repeat-replace-region (arg)
-  "Repeat replacing text of highlighted region with typed text.
-Searches for the next stretch of text identical to the region last
-replaced by typing text over it and replaces it with the same stretch
-of text."
-  (interactive "P")
-  (when cua--last-deleted-region-pos
-    (with-current-buffer (car cua--last-deleted-region-pos)
-      (save-restriction
-    (widen)
-    ;; Find the text that replaced the region via the undo list.
-    (let ((ul buffer-undo-list)
-          (elt (cdr cua--last-deleted-region-pos))
-          u s e)
-      (when elt
-        (while (consp ul)
-          (setq u (car ul) ul (cdr ul))
-          (cond
-           ((eq u elt) ;; got it
-        (setq ul nil))
-           ((and (consp u) (integerp (car u)) (integerp (cdr u)))
-        (if (and s (= (cdr u) s))
-            (setq s (car u))
-          (setq s (car u) e (cdr u)))))))
-      (cond ((and s e (<= s e) (= s (mark t)))
-         (setq cua--repeat-replace-text (cua--filter-buffer-noprops s e)))
-        ((and (null s) (eq u elt)) ;; nothing inserted
-         (setq cua--repeat-replace-text
-               ""))
-        (t
-         (message "Cannot locate replacement text"))))))
-    (setq cua--last-deleted-region-pos nil))
-  (if (and cua--last-deleted-region-text
-       cua--repeat-replace-text
-       (search-forward cua--last-deleted-region-text nil t nil))
-      (replace-match cua--repeat-replace-text arg t)))
-
  (defun cua-help-for-region (&optional help)
    "Show region specific help in echo area."
    (interactive)
@@ -1333,7 +1293,7 @@
      (define-key cua--cua-keys-keymap [(control z)] 'undo))
    (when cua-remap-control-v
      (define-key cua--cua-keys-keymap [(control v)] 'yank)
-    (define-key cua--cua-keys-keymap [(meta v)] 
'cua-repeat-replace-region))
+    (define-key cua--cua-keys-keymap [(meta v)] 
'delete-selection-repeat-replace-region))

    (define-key cua--prefix-override-keymap [(control x)] 
'cua--prefix-override-handler)
    (define-key cua--prefix-override-keymap [(control c)] 
'cua--prefix-override-handler)
@@ -1469,6 +1429,7 @@
        (if (and (boundp 'delete-selection-mode) delete-selection-mode)
            (delete-selection-mode -1)))
      (if cua-highlight-region-shift-only (transient-mark-mode -1))
+    (if cua-delete-copy-to-register-0 (setq 
delete-selection-save-to-register ?0))
      (cua--deactivate))
     (cua--saved-state
      (if (nth 0 cua--saved-state)