Patch 8.1.2207
Problem:    "gn" doesn't work quite right. (Jaehwang Jerry Jung)
Solution:   Improve and simplify the search logic. (Christian Brabandt,
            closes #5103, closes #5075)
Files:      src/search.c, src/testdir/test_gn.vim


*** ../vim-8.1.2206/src/search.c        2019-10-19 14:34:58.122164179 +0200
--- src/search.c        2019-10-24 15:18:21.358971106 +0200
***************
*** 4676,4682 ****
  
  #endif /* FEAT_TEXTOBJ */
  
! static int is_one_char(char_u *pattern, int move, pos_T *cur, int direction);
  
  /*
   * Find next search match under cursor, cursor at end.
--- 4676,4748 ----
  
  #endif /* FEAT_TEXTOBJ */
  
! /*
!  * 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,4703 ****
      char_u    old_p_ws = p_ws;
      int               flags = 0;
      pos_T     save_VIsual = VIsual;
!     int               one_char;
  
      /* wrapping should not occur */
      p_ws = FALSE;
--- 4763,4769 ----
      char_u    old_p_ws = p_ws;
      int               flags = 0;
      pos_T     save_VIsual = VIsual;
!     int               zero_width;
  
      /* wrapping should not occur */
      p_ws = FALSE;
***************
*** 4706,4734 ****
      if (VIsual_active && *p_sel == 'e' && LT_POS(VIsual, curwin->w_cursor))
        dec_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);
!       }
      }
-     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,
                                                                      FORWARD);
!     if (one_char == -1)
      {
        p_ws = old_p_ws;
        return FAIL;  /* pattern not found */
--- 4772,4791 ----
      if (VIsual_active && *p_sel == 'e' && LT_POS(VIsual, curwin->w_cursor))
        dec_cursor();
  
+     orig_pos = pos = curwin->w_cursor;
      if (VIsual_active)
      {
!       if (forward)
!           incl(&pos);
!       else
!           decl(&pos);
      }
  
      /* Is the pattern is zero-width?, this time, don't care about the 
direction
       */
!     zero_width = is_zero_width(spats[last_idx].pat, TRUE, &curwin->w_cursor,
                                                                      FORWARD);
!     if (zero_width == -1)
      {
        p_ws = old_p_ws;
        return FAIL;  /* pattern not found */
***************
*** 4747,4753 ****
            dir = !i;
  
        flags = 0;
!       if (!dir && !one_char)
            flags = SEARCH_END;
        end_pos = pos;
  
--- 4804,4810 ----
            dir = !i;
  
        flags = 0;
!       if (!dir && !zero_width)
            flags = SEARCH_END;
        end_pos = pos;
  
***************
*** 4784,4790 ****
                                ml_get(curwin->w_buffer->b_ml.ml_line_count));
            }
        }
-       p_ws = old_p_ws;
      }
  
      start_pos = pos;
--- 4841,4846 ----
***************
*** 4797,4806 ****
      curwin->w_cursor = end_pos;
      if (LT_POS(VIsual, end_pos))
        dec_cursor();
      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. */
--- 4853,4863 ----
      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';
  
      if (*p_sel == 'e')
      {
        /* Correction for exclusive selection depends on the direction. */
***************
*** 4828,4904 ****
      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)
  /*
--- 4885,4890 ----
*** ../vim-8.1.2206/src/testdir/test_gn.vim     2019-04-20 23:47:42.518391308 
+0200
--- src/testdir/test_gn.vim     2019-10-24 15:17:09.415102003 +0200
***************
*** 128,133 ****
--- 128,154 ----
    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
  
*** ../vim-8.1.2206/src/version.c       2019-10-24 15:12:20.299934958 +0200
--- src/version.c       2019-10-24 15:16:27.895167951 +0200
***************
*** 743,744 ****
--- 743,746 ----
  {   /* Add new patch number below this line */
+ /**/
+     2207,
  /**/

-- 
BEDEVERE:        And what do you burn, apart from witches?
FOURTH VILLAGER: ... Wood?
BEDEVERE:        So why do witches burn?
SECOND VILLAGER: (pianissimo) ... Because they're made of wood...?
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201910241324.x9ODO4N3023245%40masaka.moolenaar.net.

Raspunde prin e-mail lui