To: vim_dev@googlegroups.com Subject: Patch 8.1.2207 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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, ®match) == 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(®match, 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, ®match) == 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(®match, 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 -- Bram@Moolenaar.net -- 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 ///