branch: externals/ivy-hydra
commit e598b044e2728f5e3b163db99c0f0c4d7c56c6e4
Author: Oleh Krehel <[email protected]>
Commit: Oleh Krehel <[email protected]>

    ivy.el (ivy--regex): Improve handling of capture groups
    
    Suppose we have this buffer, and we want to capture the symlink name
    and location:
    
        2019 .Xmodmap -> git/home/.Xmodmap
        2019 .authinfo.gpg -> git/home/.authinfo.gpg
        2019 .bashrc -> git/home/.bashrc
    
    Old approach: search for "[^ ]+ -> .*".
    The equivalent regex is "\\([^ ]+\).*\\(->\).*\\(.*\)".
    This does not work, since "[^ ]+" will capture "2019", and the
    important part will be captured by .*.
    
    New approach: search for "[^ ]+\( -> \).*".
    The equivalent regex is "\\([^ ]+\\)\\( -> \\).*?\\(.*\\)".
    
    Note:
    - A capture group is a boundary for splitting the regex into parts,
      instead of a space
    - The space inside the capture group is literal
    - No .* is inserted after the first capture group
---
 ivy-test.el | 14 ++++++++++++--
 ivy.el      | 22 +++++++++++++---------
 swiper.el   |  9 +++++----
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/ivy-test.el b/ivy-test.el
index b7ba0bb..6054e3b 100644
--- a/ivy-test.el
+++ b/ivy-test.el
@@ -240,7 +240,13 @@ will bring the behavior in line with the newer Emacsen."
   (should (equal (ivy--split "abc[^ \n]+\\( -> \\)def")
                  '("abc[^ \n]+" "\\( -> \\)" "def")))
   (should (equal (ivy--split "\\(?:interactive\\|swiper\\) 
\\(?:list\\|symbol\\)")
-                 '("\\(?:interactive\\|swiper\\)" "\\(?:list\\|symbol\\)"))))
+                 '("\\(?:interactive\\|swiper\\)" "\\(?:list\\|symbol\\)")))
+  (should (equal (ivy--split "\\([^ \n]+\\)\\( -> \\).*")
+                 '("\\([^ \n]+\\)"
+                   "\\( -> \\)"
+                   ".*")))
+  (should (equal (ivy--split "[^ ]\\( -> \\).*")
+                 '("[^ ]" "\\( -> \\)" ".*"))))
 
 (ert-deftest ivy--regex ()
   (should (equal (ivy--regex
@@ -256,7 +262,11 @@ will bring the behavior in line with the newer Emacsen."
                   ".org")
                  "\\.org"))
   (should (equal (ivy--regex "foo\\") "foo"))
-  (should (equal (ivy--regex "foo\\|") "foo")))
+  (should (equal (ivy--regex "foo\\|") "foo"))
+  (should (equal (ivy--regex "[^ \n]+\\( -> \\).*")
+                 "\\([^ \n]+\\)\\( -> \\).*?\\(.*\\)"))
+  (should (equal (ivy--regex "\\([^ \\n]+\\)\\( -> \\).*")
+                 "\\([^ \\n]+\\)\\( -> \\).*?\\(.*\\)")))
 
 (ert-deftest ivy--split-negation ()
   (should (equal (ivy--split-negation "") ()))
diff --git a/ivy.el b/ivy.el
index b4d82b5..a7788a8 100644
--- a/ivy.el
+++ b/ivy.el
@@ -2673,7 +2673,7 @@ regexp is passed to `regexp-quote'."
                    (progn
                      (when (> i start)
                        (push (substring str start i) res))
-                     (if (string-match "\\\\(.*?\\\\)" str i)
+                     (if (eq (string-match "\\\\([^\0]*?\\\\)" str i) i)
                          (progn
                            (push (match-string 0 str) res)
                            (setq i (match-end 0))
@@ -2715,7 +2715,7 @@ regexp is passed to `regexp-quote'."
              (cl-decf open-count)))
       (cl-incf i))
     (when (= open-count 0)
-      (if (string-match "[+*?]" str i)
+      (if (eq (string-match "[+*?]" str i) i)
           (match-end 0)
         i))))
 
@@ -2748,13 +2748,17 @@ When GREEDY is non-nil, join words in a greedy way."
                              (car subs)))
                         (cons
                          (setq ivy--subexps (length subs))
-                         (mapconcat
-                          (lambda (x)
-                            (if (string-match-p "\\`\\\\([^?].*\\\\)\\'" x)
-                                x
-                              (format "\\(%s\\)" x)))
-                          subs
-                          (if greedy ".*" ".*?")))))
+                         (replace-regexp-in-string
+                          "\\.\\*\\??\\\\( "
+                          "\\( "
+                          (mapconcat
+                           (lambda (x)
+                             (if (string-match-p "\\`\\\\([^?][^\0]*\\\\)\\'" 
x)
+                                 x
+                               (format "\\(%s\\)" x)))
+                           subs
+                           (if greedy ".*" ".*?"))
+                          nil t))))
                     ivy--regex-hash)))))
 
 (defun ivy--regex-p (object)
diff --git a/swiper.el b/swiper.el
index 55bfd88..3f2ec3c 100644
--- a/swiper.el
+++ b/swiper.el
@@ -1047,10 +1047,11 @@ WND, when specified is the window."
             (em (match-end j)))
         (when (and (integerp em)
                    (integerp bm))
-          (while (and (< j ivy--subexps)
-                      (integerp (match-beginning (+ j 1)))
-                      (= em (match-beginning (+ j 1))))
-            (setq em (match-end (cl-incf j))))
+          (when (eq (ivy-alist-setting ivy-re-builders-alist t) 
#'ivy--regex-fuzzy)
+            (while (and (< j ivy--subexps)
+                        (integerp (match-beginning (+ j 1)))
+                        (= em (match-beginning (+ j 1))))
+              (setq em (match-end (cl-incf j)))))
           (funcall adder-fn
                    bm em
                    (nth (1+ (mod (+ i 2) (1- (length faces))))

Reply via email to