]> granicus.if.org Git - vim/commitdiff
patch 8.1.2207: "gn" doesn't work quite right v8.1.2207
authorBram Moolenaar <Bram@vim.org>
Thu, 24 Oct 2019 13:23:37 +0000 (15:23 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 24 Oct 2019 13:23:37 +0000 (15:23 +0200)
Problem:    "gn" doesn't work quite right. (Jaehwang Jerry Jung)
Solution:   Improve and simplify the search logic. (Christian Brabandt,
            closes #5103, closes #5075)

src/search.c
src/testdir/test_gn.vim
src/version.c

index ab0edc48b980c0886b9801cc5059296512b77770..a1f8998df77d10dd907a53a3a10c4225e88289e1 100644 (file)
@@ -4676,7 +4676,73 @@ abort_search:
 
 #endif /* FEAT_TEXTOBJ */
 
-static int is_one_char(char_u *pattern, int move, pos_T *cur, int direction);
+/*
+ * Check if the pattern is one character long or zero-width.
+ * If move is TRUE, check from the beginning of the buffer, else from position
+ * "cur".
+ * "direction" is FORWARD or BACKWARD.
+ * Returns TRUE, FALSE or -1 for failure.
+ */
+    static int
+is_zero_width(char_u *pattern, int move, pos_T *cur, int direction)
+{
+    regmmatch_T        regmatch;
+    int                nmatched = 0;
+    int                result = -1;
+    pos_T      pos;
+    int                save_called_emsg = called_emsg;
+    int                flag = 0;
+
+    if (pattern == NULL)
+       pattern = spats[last_idx].pat;
+
+    if (search_regcomp(pattern, RE_SEARCH, RE_SEARCH,
+                                             SEARCH_KEEP, &regmatch) == FAIL)
+       return -1;
+
+    // init startcol correctly
+    regmatch.startpos[0].col = -1;
+    // move to match
+    if (move)
+    {
+       CLEAR_POS(&pos);
+    }
+    else
+    {
+       pos = *cur;
+       // accept a match at the cursor position
+       flag = SEARCH_START;
+    }
+
+    if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
+                                 SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL)
+    {
+       // Zero-width pattern should match somewhere, then we can check if
+       // start and end are in the same position.
+       called_emsg = FALSE;
+       do
+       {
+           regmatch.startpos[0].col++;
+           nmatched = vim_regexec_multi(&regmatch, curwin, curbuf,
+                              pos.lnum, regmatch.startpos[0].col, NULL, NULL);
+           if (nmatched != 0)
+               break;
+       } while (direction == FORWARD ? regmatch.startpos[0].col < pos.col
+                                     : regmatch.startpos[0].col > pos.col);
+
+       if (!called_emsg)
+       {
+           result = (nmatched != 0
+               && regmatch.startpos[0].lnum == regmatch.endpos[0].lnum
+               && regmatch.startpos[0].col == regmatch.endpos[0].col);
+       }
+    }
+
+    called_emsg |= save_called_emsg;
+    vim_regfree(regmatch.regprog);
+    return result;
+}
+
 
 /*
  * Find next search match under cursor, cursor at end.
@@ -4697,7 +4763,7 @@ current_search(
     char_u     old_p_ws = p_ws;
     int                flags = 0;
     pos_T      save_VIsual = VIsual;
-    int                one_char;
+    int                zero_width;
 
     /* wrapping should not occur */
     p_ws = FALSE;
@@ -4706,29 +4772,20 @@ current_search(
     if (VIsual_active && *p_sel == 'e' && LT_POS(VIsual, curwin->w_cursor))
        dec_cursor();
 
+    orig_pos = pos = curwin->w_cursor;
     if (VIsual_active)
     {
-       orig_pos = curwin->w_cursor;
-
-       pos = curwin->w_cursor;
-
-       /* make sure, searching further will extend the match */
-       if (VIsual_active)
-       {
-           if (forward)
-               incl(&pos);
-           else
-               decl(&pos);
-       }
+       if (forward)
+           incl(&pos);
+       else
+           decl(&pos);
     }
-    else
-       orig_pos = pos = curwin->w_cursor;
 
     /* Is the pattern is zero-width?, this time, don't care about the direction
      */
-    one_char = is_one_char(spats[last_idx].pat, TRUE, &curwin->w_cursor,
+    zero_width = is_zero_width(spats[last_idx].pat, TRUE, &curwin->w_cursor,
                                                                      FORWARD);
-    if (one_char == -1)
+    if (zero_width == -1)
     {
        p_ws = old_p_ws;
        return FAIL;  /* pattern not found */
@@ -4747,7 +4804,7 @@ current_search(
            dir = !i;
 
        flags = 0;
-       if (!dir && !one_char)
+       if (!dir && !zero_width)
            flags = SEARCH_END;
        end_pos = pos;
 
@@ -4784,7 +4841,6 @@ current_search(
                                ml_get(curwin->w_buffer->b_ml.ml_line_count));
            }
        }
-       p_ws = old_p_ws;
     }
 
     start_pos = pos;
@@ -4797,10 +4853,11 @@ current_search(
     curwin->w_cursor = end_pos;
     if (LT_POS(VIsual, end_pos))
        dec_cursor();
+    else if (VIsual_active && LT_POS(curwin->w_cursor, VIsual))
+       curwin->w_cursor = pos;   // put the cursor on the start of the match
     VIsual_active = TRUE;
     VIsual_mode = 'v';
 
-    redraw_curbuf_later(INVERTED);     /* update the inversion */
     if (*p_sel == 'e')
     {
        /* Correction for exclusive selection depends on the direction. */
@@ -4828,77 +4885,6 @@ current_search(
     return OK;
 }
 
-/*
- * Check if the pattern is one character long or zero-width.
- * If move is TRUE, check from the beginning of the buffer, else from position
- * "cur".
- * "direction" is FORWARD or BACKWARD.
- * Returns TRUE, FALSE or -1 for failure.
- */
-    static int
-is_one_char(char_u *pattern, int move, pos_T *cur, int direction)
-{
-    regmmatch_T        regmatch;
-    int                nmatched = 0;
-    int                result = -1;
-    pos_T      pos;
-    int                save_called_emsg = called_emsg;
-    int                flag = 0;
-
-    if (pattern == NULL)
-       pattern = spats[last_idx].pat;
-
-    if (search_regcomp(pattern, RE_SEARCH, RE_SEARCH,
-                                             SEARCH_KEEP, &regmatch) == FAIL)
-       return -1;
-
-    /* init startcol correctly */
-    regmatch.startpos[0].col = -1;
-    /* move to match */
-    if (move)
-    {
-       CLEAR_POS(&pos);
-    }
-    else
-    {
-       pos = *cur;
-       /* accept a match at the cursor position */
-       flag = SEARCH_START;
-    }
-
-    if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
-                        SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL)
-    {
-       /* Zero-width pattern should match somewhere, then we can check if
-        * start and end are in the same position. */
-       called_emsg = FALSE;
-       do
-       {
-           regmatch.startpos[0].col++;
-           nmatched = vim_regexec_multi(&regmatch, curwin, curbuf,
-                              pos.lnum, regmatch.startpos[0].col, NULL, NULL);
-           if (nmatched != 0)
-               break;
-       } while (direction == FORWARD ? regmatch.startpos[0].col < pos.col
-                                     : regmatch.startpos[0].col > pos.col);
-
-       if (!called_emsg)
-       {
-           result = (nmatched != 0
-               && regmatch.startpos[0].lnum == regmatch.endpos[0].lnum
-               && regmatch.startpos[0].col == regmatch.endpos[0].col);
-           // one char width
-           if (!result && nmatched != 0
-                       && inc(&pos) >= 0 && pos.col == regmatch.endpos[0].col)
-               result = TRUE;
-       }
-    }
-
-    called_emsg |= save_called_emsg;
-    vim_regfree(regmatch.regprog);
-    return result;
-}
-
 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(FEAT_TEXTOBJ) \
        || defined(PROTO)
 /*
index fc7e89190dd968f9ea5119ea27d4afac129e0012..ecf9b82899da56babc5f2a7189ac6910469feea2 100644 (file)
@@ -128,6 +128,27 @@ func Test_gn_command()
   call assert_equal([' nnoremap', '', 'match'], getline(1,'$'))
   sil! %d_
 
+  " make sure it works correctly for one-char wide search items
+  call setline('.', ['abcdefghi'])
+  let @/ = 'a'
+  exe "norm! 0fhvhhgNgU"
+  call assert_equal(['ABCDEFGHi'], getline(1,'$'))
+  call setline('.', ['abcdefghi'])
+  let @/ = 'b'
+  exe "norm! 0fhvhhgngU"
+  call assert_equal(['abcdefghi'], getline(1,'$'))
+  sil! %d _
+  call setline('.', ['abcdefghi'])
+  let @/ = 'f'
+  exe "norm! 0vllgngU"
+  call assert_equal(['ABCDEFghi'], getline(1,'$'))
+  sil! %d _
+  call setline('.', ['12345678'])
+  let @/ = '5'
+  norm! gg0f7vhhhhgnd
+  call assert_equal(['12348'], getline(1,'$'))
+  sil! %d _
+
   set wrapscan&vim
 endfu
 
index e6a66be3cc555113f2c0a3b454d31c23dc880142..91cdf338a30d274e5b497010a8db9e4dacd55096 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2207,
 /**/
     2206,
 /**/