emacs-elpa-diffs
[Top][All Lists]
Advanced

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

[nongnu] elpa/recomplete 5aa74e66e6 5/7: Use replace in region function


From: ELPA Syncer
Subject: [nongnu] elpa/recomplete 5aa74e66e6 5/7: Use replace in region function that avoids redundant work
Date: Sat, 7 Jan 2023 19:59:39 -0500 (EST)

branch: elpa/recomplete
commit 5aa74e66e6d876fa19272a1b1f407cc8dbb2feb7
Author: Campbell Barton <ideasman42@gmail.com>
Commit: Campbell Barton <ideasman42@gmail.com>

    Use replace in region function that avoids redundant work
---
 Makefile                 |   4 ++
 recomplete.el            |  65 ++++++++++++++++++++----
 tests/recomplete-test.el | 127 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000..c4f26c62f7
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+test:
+       @emacs -batch -l tests/recomplete-test.el -f 
ert-run-tests-batch-and-exit
diff --git a/recomplete.el b/recomplete.el
index 1a5763808e..773d49a5ba 100644
--- a/recomplete.el
+++ b/recomplete.el
@@ -67,8 +67,6 @@
 ;;   after `recomplete-with-callback', so we know not to break the chain in 
that case.
 (defvar-local recomplete--alist nil "Internal properties for repeated 
`recomplete' calls.")
 
-;; ---------------------------------------------------------------------------
-;; Generic Functions/Macros
 
 (defmacro recomplete--with-advice (fn-orig where fn-advice &rest body)
   "Execute BODY with advice added.
@@ -222,9 +220,7 @@ Argument FN-CACHE stores the result for reuse."
 
     (when result-choices
       (let ((word-at-index (nth (mod cycle-index (length result-choices)) 
result-choices)))
-        (goto-char word-beg)
-        (delete-region word-beg word-end)
-        (insert word-at-index)))
+        (recomplete-replace-in-region word-at-index word-beg word-end)))
 
     (list result-choices fn-cache)))
 
@@ -275,9 +271,7 @@ Argument FN-CACHE stores the result for reuse."
         (setq fn-cache (list result-choices word-beg word-end))))
 
     (let ((word-at-index (nth (mod cycle-index (length result-choices)) 
result-choices)))
-      (goto-char word-beg)
-      (delete-region word-beg word-end)
-      (insert word-at-index))
+      (recomplete-replace-in-region word-at-index word-beg word-end))
 
     (list result-choices fn-cache)))
 
@@ -321,9 +315,7 @@ Argument FN-CACHE stores the result for reuse."
           (setq fn-cache (list result-choices word-beg word-end)))))
 
     (let ((word-at-index (nth (mod cycle-index (length result-choices)) 
result-choices)))
-      (goto-char word-beg)
-      (delete-region word-beg word-end)
-      (insert word-at-index))
+      (recomplete-replace-in-region word-at-index word-beg word-end))
 
     (list result-choices fn-cache)))
 
@@ -331,6 +323,57 @@ Argument FN-CACHE stores the result for reuse."
 ;; ---------------------------------------------------------------------------
 ;; Public Functions
 
+;;;###autoload
+(defun recomplete-replace-in-region (str beg end)
+  "Utility to replace region from BEG to END with STR.
+Return the region replaced."
+  (let
+    (
+      (len (length str))
+      (i-beg nil)
+      (i-end nil)
+      (i-end-ofs nil))
+
+    ;; Check for skip end.
+    (let ((i 0))
+      (let ((len-test (min (- end beg) len)))
+        (while (< i len-test)
+          (let ((i-next (1+ i)))
+            (cond
+              ((eq (aref str (- len i-next)) (char-after (- end i-next)))
+                (setq i i-next))
+              (t ;; Break.
+                (setq len-test i))))))
+      (unless (zerop i)
+        (setq i-end (- len i))
+        (setq len (- len i))
+        (setq end (- end i))
+        (setq i-end-ofs i)))
+
+    ;; Check for skip start.
+    (let ((i 0))
+      (let ((len-test (min (- end beg) len)))
+        (while (< i len-test)
+          (cond
+            ((eq (aref str i) (char-after (+ beg i)))
+              (setq i (1+ i)))
+            (t ;; Break.
+              (setq len-test i)))))
+      (unless (zerop i)
+        (setq i-beg i)
+        (setq beg (+ beg i))))
+
+    (when (or i-beg i-end)
+      (setq str (substring str (or i-beg 0) (or i-end len))))
+
+    (goto-char beg)
+    (delete-region beg end)
+    (insert str)
+    (when i-end-ofs
+      ;; Leave the cursor where it would be if the end wasn't clipped.
+      (goto-char (+ (point) i-end-ofs)))
+    (cons beg (+ beg (length str)))))
+
 ;; Make public since users may want to add their own callbacks.
 
 ;;;###autoload
diff --git a/tests/recomplete-test.el b/tests/recomplete-test.el
new file mode 100644
index 0000000000..720e744a1b
--- /dev/null
+++ b/tests/recomplete-test.el
@@ -0,0 +1,127 @@
+;;; recomplete-test.el --- Highlight indent scope test -*- lexical-binding: t 
-*-
+
+;; SPDX-License-Identifier: GPL-3.0-or-later
+;; Copyright (C) 2022  Campbell Barton
+
+;; Author: Campbell Barton <ideasman42@gmail.com>
+
+;; URL: https://codeberg.org/ideasman42/emacs-recomplete
+;; Keywords: convenience
+;; Version: 0.1
+;; Package-Requires: ((emacs "26.1"))
+
+;;; Commentary:
+
+;; This is a test for `recomplete'.
+;;
+
+;;; Usage
+
+;;
+;; To test this file run:
+;;
+;;     `emacs -batch -l tests/recomplete-test.el -f 
ert-run-tests-batch-and-exit'
+;;
+
+;;; Code:
+
+(require 'ert)
+
+;; ---------------------------------------------------------------------------
+;; Setup Environment
+
+(setq recomplete-basedir (concat (file-name-directory load-file-name) ".."))
+(add-to-list 'load-path recomplete-basedir)
+(require 'recomplete)
+
+;; ---------------------------------------------------------------------------
+;; Test Internal Replacement Function
+
+(defmacro ert-replace-in-region (id str-src args output replaced-range)
+  `
+  (ert-deftest ,id ()
+    "Generic test."
+    (with-temp-buffer
+      (insert ,str-src)
+      (let ((result (apply 'recomplete-replace-in-region ,args)))
+        (should (equal ,output (buffer-substring-no-properties (point-min) 
(point-max))))
+        (should (equal result ,replaced-range))))))
+
+(ert-replace-in-region replace-in-region-nop "" '("" 1 1) "" (cons 1 1))
+(ert-replace-in-region replace-in-region-single-same "x" '("x" 1 2) "x" (cons 
1 1))
+(ert-replace-in-region replace-in-region-single-different "x" '("y" 1 2) "y" 
(cons 1 2))
+
+(ert-replace-in-region replace-in-region-word-same "hello" '("hello" 1 6) 
"hello" (cons 1 1))
+(ert-replace-in-region replace-in-region-word-same-start "HELLO" '("Hello" 1 
6) "Hello" (cons 2 6))
+(ert-replace-in-region replace-in-region-word-same-end "HELLO" '("hELLO" 1 6) 
"hELLO" (cons 1 2))
+(ert-replace-in-region
+  replace-in-region-word-different-1
+  "hello"
+  '("world" 1 6)
+  "world"
+  (cons 1 6))
+(ert-replace-in-region
+  replace-in-region-word-different-2
+  "hello"
+  '("HELLO" 1 6)
+  "HELLO"
+  (cons 1 6))
+(ert-replace-in-region
+  replace-in-region-word-contract
+  "commpletion"
+  '("completion" 1 12)
+  "completion"
+  (cons 3 3))
+(ert-replace-in-region
+  replace-in-region-word-expand
+  "copletion"
+  '("completion" 1 10)
+  "completion"
+  (cons 3 4))
+
+(ert-replace-in-region
+  replace-in-region-word-mix-same
+  "pre hello post"
+  '("hello" 5 10)
+  "pre hello post"
+  (cons 5 5))
+(ert-replace-in-region
+  replace-in-region-word-mix-same-start
+  "pre HELLO post"
+  '("Hello" 5 10)
+  "pre Hello post"
+  (cons 6 10))
+(ert-replace-in-region
+  replace-in-region-word-mix-same-end
+  "pre HELLO post"
+  '("hELLO" 5 10)
+  "pre hELLO post"
+  (cons 5 6))
+(ert-replace-in-region
+  replace-in-region-word-mix-different-1
+  "pre hello post"
+  '("world" 5 10)
+  "pre world post"
+  (cons 5 10))
+(ert-replace-in-region
+  replace-in-region-word-mix-different-2
+  "pre hello post"
+  '("HELLO" 5 10)
+  "pre HELLO post"
+  (cons 5 10))
+(ert-replace-in-region
+  replace-in-region-word-mix-contract
+  "pre commpletion post"
+  '("completion" 5 16)
+  "pre completion post"
+  (cons 7 7))
+(ert-replace-in-region
+  replace-in-region-word-mix-expand
+  "pre copletion post"
+  '("completion" 5 14)
+  "pre completion post"
+  (cons 7 8))
+
+
+(provide 'recomplete-test)
+;;; recomplete-test.el ends here



reply via email to

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