diff --git a/src/if_cscope.c b/src/if_cscope.c index 168b3e49e3..4bf28ad1d1 100644 --- a/src/if_cscope.c +++ b/src/if_cscope.c @@ -677,7 +677,7 @@ cs_cnt_matches(int idx) { char *stok; char *buf; - int nlines; + int nlines = 0; buf = (char *)alloc(CSREAD_BUFSIZE); if (buf == NULL) @@ -700,7 +700,10 @@ cs_cnt_matches(int idx) * cscope will output error messages before the number-of-lines output. * Display/discard any output that doesn't match what we want. * Accept "\S*cscope: X lines", also matches "mlcscope". + * Bail out for the "Unable to search" error. */ + if (strstr((const char *)buf, "Unable to search database") != NULL) + break; if ((stok = strtok(buf, (const char *)" ")) == NULL) continue; if (strstr((const char *)stok, "cscope:") == NULL) diff --git a/src/terminal.c b/src/terminal.c index 1da0027132..f26d1e42ce 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -649,6 +649,29 @@ free_terminal(buf_T *buf) in_terminal_loop = NULL; } +/* + * Get the part that is connected to the tty. Normally this is PART_IN, but + * when writing buffer lines to the job it can be another. This makes it + * possible to do "1,5term vim -". + */ + static ch_part_T +get_tty_part(term_T *term) +{ +#ifdef UNIX + ch_part_T parts[3] = {PART_IN, PART_OUT, PART_ERR}; + int i; + + for (i = 0; i < 3; ++i) + { + int fd = term->tl_job->jv_channel->ch_part[parts[i]].ch_fd; + + if (isatty(fd)) + return parts[i]; + } +#endif + return PART_IN; +} + /* * Write job output "msg[len]" to the vterm. */ @@ -656,9 +679,21 @@ free_terminal(buf_T *buf) term_write_job_output(term_T *term, char_u *msg, size_t len) { VTerm *vterm = term->tl_vterm; + size_t prevlen = vterm_output_get_buffer_current(vterm); vterm_input_write(vterm, (char *)msg, len); + /* flush vterm buffer when vterm responded to control sequence */ + if (prevlen != vterm_output_get_buffer_current(vterm)) + { + char buf[KEY_BUF_LEN]; + size_t curlen = vterm_output_read(vterm, buf, KEY_BUF_LEN); + + if (curlen > 0) + channel_send(term->tl_job->jv_channel, get_tty_part(term), + (char_u *)buf, (int)curlen, NULL); + } + /* this invokes the damage callbacks */ vterm_screen_flush_damage(vterm_obtain_screen(vterm)); } @@ -1243,29 +1278,6 @@ term_vgetc() return c; } -/* - * Get the part that is connected to the tty. Normally this is PART_IN, but - * when writing buffer lines to the job it can be another. This makes it - * possible to do "1,5term vim -". - */ - static ch_part_T -get_tty_part(term_T *term) -{ -#ifdef UNIX - ch_part_T parts[3] = {PART_IN, PART_OUT, PART_ERR}; - int i; - - for (i = 0; i < 3; ++i) - { - int fd = term->tl_job->jv_channel->ch_part[parts[i]].ch_fd; - - if (isatty(fd)) - return parts[i]; - } -#endif - return PART_IN; -} - /* * Send keys to terminal. * Return FAIL when the key needs to be handled in Normal mode. diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim index 9b96b49fde..130562fc5e 100644 --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -619,6 +619,8 @@ func Test_search_cmdline_incsearch_highlight_attr() let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile', 'Xsearch.txt'], {'term_rows': 3}) call WaitFor({-> lines == [term_getline(buf, 1), term_getline(buf, 2)] }) + " wait for vim to complete initialization + call term_wait(buf) " Get attr of normal(a0), incsearch(a1), hlsearch(a2) highlight call term_sendkeys(buf, ":set incsearch hlsearch\") diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 89d086ced2..20c21ae143 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -811,3 +811,26 @@ func Test_terminal_term_start_empty_command() let cmd = "call term_start(0, {'curwin' : 1, 'term_finish' : 'close'})" call assert_fails(cmd, 'E474') endfunc + +func Test_terminal_response_to_control_sequence() + if !has('unix') + return + endif + + let buf = Run_shell_in_terminal({}) + call term_wait(buf) + + call term_sendkeys(buf, s:python . " -c 'import sys;sys.stdout.write(\"\\x1b[6n\")'\") + " wait for the response of control sequence from libvterm (and send it to tty) + call term_wait(buf, 100) + " wait for output from tty to display + call term_wait(buf) + call assert_match(';\d\+R', term_getline(buf, 2)) + + call term_sendkeys(buf, "\") + call term_wait(buf) + call Stop_shell_in_terminal(buf) + + exe buf . 'bwipe' + unlet g:job +endfunc diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim index b7235867b9..cc3cceb1ae 100644 --- a/src/testdir/test_undo.vim +++ b/src/testdir/test_undo.vim @@ -359,3 +359,47 @@ func Test_undo_append() norm o quit endfunc + +func Test_undo_0() + new + set ul=100 + normal i1 + undo + normal i2 + undo + normal i3 + + undo 0 + let d = undotree() + call assert_equal('', getline(1)) + call assert_equal(0, d.seq_cur) + + redo + let d = undotree() + call assert_equal('3', getline(1)) + call assert_equal(3, d.seq_cur) + + undo 2 + undo 0 + let d = undotree() + call assert_equal('', getline(1)) + call assert_equal(0, d.seq_cur) + + redo + let d = undotree() + call assert_equal('2', getline(1)) + call assert_equal(2, d.seq_cur) + + undo 1 + undo 0 + let d = undotree() + call assert_equal('', getline(1)) + call assert_equal(0, d.seq_cur) + + redo + let d = undotree() + call assert_equal('1', getline(1)) + call assert_equal(1, d.seq_cur) + + bwipe! +endfunc diff --git a/src/undo.c b/src/undo.c index ae4b4a44c9..0b7656a40f 100644 --- a/src/undo.c +++ b/src/undo.c @@ -2272,7 +2272,7 @@ undo_time( long closest_start; long closest_seq = 0; long val; - u_header_T *uhp; + u_header_T *uhp = NULL; u_header_T *last; int mark; int nomark; @@ -2295,14 +2295,7 @@ undo_time( * Init "closest" to a value we can't reach. */ if (absolute) { - if (step == 0) - { - /* target 0 does not exist, got to 1 and above it. */ - target = 1; - above = TRUE; - } - else - target = step; + target = step; closest = -1; } else @@ -2369,6 +2362,10 @@ undo_time( closest_start = closest; closest_seq = curbuf->b_u_seq_cur; + /* When "target" is 0; Back to origin. */ + if (target == 0) + goto found; + /* * May do this twice: * 1. Search for "target", update "closest" to the best match found. @@ -2494,8 +2491,9 @@ undo_time( above = TRUE; /* stop above the header */ } +found: /* If we found it: Follow the path to go to where we want to be. */ - if (uhp != NULL) + if (uhp != NULL || target == 0) { /* * First go up the tree as much as needed. @@ -2510,87 +2508,93 @@ undo_time( uhp = curbuf->b_u_newhead; else uhp = uhp->uh_next.ptr; - if (uhp == NULL || uhp->uh_walk != mark + if (uhp == NULL || (target > 0 && uhp->uh_walk != mark) || (uhp->uh_seq == target && !above)) break; curbuf->b_u_curhead = uhp; u_undoredo(TRUE); - uhp->uh_walk = nomark; /* don't go back down here */ + if (target > 0) + uhp->uh_walk = nomark; /* don't go back down here */ } - /* - * And now go down the tree (redo), branching off where needed. - */ - while (!got_int) + /* When back to origin, redo is not needed. */ + if (target > 0) { - /* Do the change warning now, for the same reason as above. */ - change_warning(0); + /* + * And now go down the tree (redo), branching off where needed. + */ + while (!got_int) + { + /* Do the change warning now, for the same reason as above. */ + change_warning(0); - uhp = curbuf->b_u_curhead; - if (uhp == NULL) - break; + uhp = curbuf->b_u_curhead; + if (uhp == NULL) + break; - /* Go back to the first branch with a mark. */ - while (uhp->uh_alt_prev.ptr != NULL + /* Go back to the first branch with a mark. */ + while (uhp->uh_alt_prev.ptr != NULL && uhp->uh_alt_prev.ptr->uh_walk == mark) - uhp = uhp->uh_alt_prev.ptr; - - /* Find the last branch with a mark, that's the one. */ - last = uhp; - while (last->uh_alt_next.ptr != NULL - && last->uh_alt_next.ptr->uh_walk == mark) - last = last->uh_alt_next.ptr; - if (last != uhp) - { - /* Make the used branch the first entry in the list of - * alternatives to make "u" and CTRL-R take this branch. */ - while (uhp->uh_alt_prev.ptr != NULL) uhp = uhp->uh_alt_prev.ptr; - if (last->uh_alt_next.ptr != NULL) - last->uh_alt_next.ptr->uh_alt_prev.ptr = + + /* Find the last branch with a mark, that's the one. */ + last = uhp; + while (last->uh_alt_next.ptr != NULL + && last->uh_alt_next.ptr->uh_walk == mark) + last = last->uh_alt_next.ptr; + if (last != uhp) + { + /* Make the used branch the first entry in the list of + * alternatives to make "u" and CTRL-R take this branch. */ + while (uhp->uh_alt_prev.ptr != NULL) + uhp = uhp->uh_alt_prev.ptr; + if (last->uh_alt_next.ptr != NULL) + last->uh_alt_next.ptr->uh_alt_prev.ptr = last->uh_alt_prev.ptr; - last->uh_alt_prev.ptr->uh_alt_next.ptr = last->uh_alt_next.ptr; - last->uh_alt_prev.ptr = NULL; - last->uh_alt_next.ptr = uhp; - uhp->uh_alt_prev.ptr = last; + last->uh_alt_prev.ptr->uh_alt_next.ptr = + last->uh_alt_next.ptr; + last->uh_alt_prev.ptr = NULL; + last->uh_alt_next.ptr = uhp; + uhp->uh_alt_prev.ptr = last; - if (curbuf->b_u_oldhead == uhp) - curbuf->b_u_oldhead = last; - uhp = last; - if (uhp->uh_next.ptr != NULL) - uhp->uh_next.ptr->uh_prev.ptr = uhp; - } - curbuf->b_u_curhead = uhp; + if (curbuf->b_u_oldhead == uhp) + curbuf->b_u_oldhead = last; + uhp = last; + if (uhp->uh_next.ptr != NULL) + uhp->uh_next.ptr->uh_prev.ptr = uhp; + } + curbuf->b_u_curhead = uhp; - if (uhp->uh_walk != mark) - break; /* must have reached the target */ + if (uhp->uh_walk != mark) + break; /* must have reached the target */ - /* Stop when going backwards in time and didn't find the exact - * header we were looking for. */ - if (uhp->uh_seq == target && above) - { - curbuf->b_u_seq_cur = target - 1; - break; - } + /* Stop when going backwards in time and didn't find the exact + * header we were looking for. */ + if (uhp->uh_seq == target && above) + { + curbuf->b_u_seq_cur = target - 1; + break; + } - u_undoredo(FALSE); + u_undoredo(FALSE); - /* Advance "curhead" to below the header we last used. If it - * becomes NULL then we need to set "newhead" to this leaf. */ - if (uhp->uh_prev.ptr == NULL) - curbuf->b_u_newhead = uhp; - curbuf->b_u_curhead = uhp->uh_prev.ptr; - did_undo = FALSE; + /* Advance "curhead" to below the header we last used. If it + * becomes NULL then we need to set "newhead" to this leaf. */ + if (uhp->uh_prev.ptr == NULL) + curbuf->b_u_newhead = uhp; + curbuf->b_u_curhead = uhp->uh_prev.ptr; + did_undo = FALSE; - if (uhp->uh_seq == target) /* found it! */ - break; + if (uhp->uh_seq == target) /* found it! */ + break; - uhp = uhp->uh_prev.ptr; - if (uhp == NULL || uhp->uh_walk != mark) - { - /* Need to redo more but can't find it... */ - internal_error("undo_time()"); - break; + uhp = uhp->uh_prev.ptr; + if (uhp == NULL || uhp->uh_walk != mark) + { + /* Need to redo more but can't find it... */ + internal_error("undo_time()"); + break; + } } } } diff --git a/src/version.c b/src/version.c index 98800d228f..ee2f791c12 100644 --- a/src/version.c +++ b/src/version.c @@ -786,6 +786,14 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1442, +/**/ + 1441, +/**/ + 1440, +/**/ + 1439, /**/ 1438, /**/