From 865767126e97d9ac65e052a657b29bbc32dcb512 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 25 Jan 2019 20:48:33 +0100 Subject: [PATCH 1/4] patch 8.1.0819: a failed assert with a long string is hard to read Problem: A failed assert with a long string is hard to read. Solution: Shorten the assert message. --- src/eval.c | 86 ++++++++++++++++++++++++++++--------- src/testdir/test_assert.vim | 4 ++ src/version.c | 2 + 3 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/eval.c b/src/eval.c index 67a006ec95..82de63e1f8 100644 --- a/src/eval.c +++ b/src/eval.c @@ -9494,15 +9494,55 @@ assert_fails(typval_T *argvars) return ret; } +/* + * Append "p[clen]" to "gap", escaping unprintable characters. + * Changes NL to \n, CR to \r, etc. + */ + static void +ga_concat_esc(garray_T *gap, char_u *p, int clen) +{ + char_u buf[NUMBUFLEN]; + + if (clen > 1) + { + mch_memmove(buf, p, clen); + buf[clen] = NUL; + ga_concat(gap, buf); + } + else switch (*p) + { + case BS: ga_concat(gap, (char_u *)"\\b"); break; + case ESC: ga_concat(gap, (char_u *)"\\e"); break; + case FF: ga_concat(gap, (char_u *)"\\f"); break; + case NL: ga_concat(gap, (char_u *)"\\n"); break; + case TAB: ga_concat(gap, (char_u *)"\\t"); break; + case CAR: ga_concat(gap, (char_u *)"\\r"); break; + case '\\': ga_concat(gap, (char_u *)"\\\\"); break; + default: + if (*p < ' ') + { + vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p); + ga_concat(gap, buf); + } + else + ga_append(gap, *p); + break; + } +} + /* * Append "str" to "gap", escaping unprintable characters. * Changes NL to \n, CR to \r, etc. */ static void -ga_concat_esc(garray_T *gap, char_u *str) +ga_concat_shorten_esc(garray_T *gap, char_u *str) { char_u *p; + char_u *s; + int c; + int clen; char_u buf[NUMBUFLEN]; + int same_len; if (str == NULL) { @@ -9511,25 +9551,29 @@ ga_concat_esc(garray_T *gap, char_u *str) } for (p = str; *p != NUL; ++p) - switch (*p) + { + same_len = 1; + s = p; + c = mb_ptr2char_adv(&s); + clen = s - p; + while (*s != NUL && c == mb_ptr2char(s)) { - case BS: ga_concat(gap, (char_u *)"\\b"); break; - case ESC: ga_concat(gap, (char_u *)"\\e"); break; - case FF: ga_concat(gap, (char_u *)"\\f"); break; - case NL: ga_concat(gap, (char_u *)"\\n"); break; - case TAB: ga_concat(gap, (char_u *)"\\t"); break; - case CAR: ga_concat(gap, (char_u *)"\\r"); break; - case '\\': ga_concat(gap, (char_u *)"\\\\"); break; - default: - if (*p < ' ') - { - vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p); - ga_concat(gap, buf); - } - else - ga_append(gap, *p); - break; + ++same_len; + s += clen; } + if (same_len > 20) + { + ga_concat(gap, (char_u *)"\\["); + ga_concat_esc(gap, p, clen); + ga_concat(gap, (char_u *)" occurs "); + vim_snprintf((char *)buf, NUMBUFLEN, "%d", same_len); + ga_concat(gap, buf); + ga_concat(gap, (char_u *)" times]"); + p = s - 1; + } + else + ga_concat_esc(gap, p, clen); + } } /* @@ -9562,11 +9606,11 @@ fill_assert_error( ga_concat(gap, (char_u *)"Expected "); if (exp_str == NULL) { - ga_concat_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0)); + ga_concat_shorten_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0)); vim_free(tofree); } else - ga_concat_esc(gap, exp_str); + ga_concat_shorten_esc(gap, exp_str); if (atype != ASSERT_NOTEQUAL) { if (atype == ASSERT_MATCH) @@ -9575,7 +9619,7 @@ fill_assert_error( ga_concat(gap, (char_u *)" does match "); else ga_concat(gap, (char_u *)" but got "); - ga_concat_esc(gap, tv2string(got_tv, &tofree, numbuf, 0)); + ga_concat_shorten_esc(gap, tv2string(got_tv, &tofree, numbuf, 0)); vim_free(tofree); } } diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim index fb31478aa4..298a6db15a 100644 --- a/src/testdir/test_assert.vim +++ b/src/testdir/test_assert.vim @@ -31,6 +31,10 @@ func Test_assert_equal() call assert_equal(1, assert_equal('bar', s)) call assert_match("Expected 'bar' but got 'foo'", v:errors[0]) call remove(v:errors, 0) + + call assert_equal('XxxxxxxxxxxxxxxxxxxxxxX', 'XyyyyyyyyyyyyyyyyyyyyyyyyyX') + call assert_match("Expected 'X\\\\\\[x occurs 21 times]X' but got 'X\\\\\\[y occurs 25 times]X'", v:errors[0]) + call remove(v:errors, 0) endfunc func Test_assert_equalfile() diff --git a/src/version.c b/src/version.c index 4beae276fd..3a75c99fc4 100644 --- a/src/version.c +++ b/src/version.c @@ -787,6 +787,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 819, /**/ 818, /**/ From e295609be20c1b065d6b489214d70e171ae49234 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 25 Jan 2019 21:01:17 +0100 Subject: [PATCH 2/4] patch 8.1.0820: test for sending large data over channel sometimes fails Problem: Test for sending large data over channel sometimes fails. Solution: Handle that the job may have finished early. Also fix that file changed test doesn't work in the GUI and reduce flakyness. (Ozaki Kiichi, closes #3861) --- src/testdir/test_channel.vim | 78 +++++++++++++++++--------------- src/testdir/test_filechanged.vim | 2 +- src/version.c | 2 + 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index e7fcf95826..7b0a917352 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -879,19 +879,19 @@ endfunc func Test_pipe_err_to_buffer_name() call Run_test_pipe_err_to_buffer(1, 0, 1) endfunc - + func Test_pipe_err_to_buffer_nr() call Run_test_pipe_err_to_buffer(0, 0, 1) endfunc - + func Test_pipe_err_to_buffer_name_nomod() call Run_test_pipe_err_to_buffer(1, 1, 1) endfunc - + func Test_pipe_err_to_buffer_name_nomsg() call Run_test_pipe_err_to_buffer(1, 0, 0) endfunc - + func Test_pipe_both_to_buffer() if !has('job') return @@ -966,15 +966,15 @@ func Run_pipe_through_sort(all, use_buffer) let options.in_top = 2 let options.in_bot = 4 endif - let g:job = job_start('sort', options) + let job = job_start('sort', options) if !a:use_buffer - call assert_equal("run", job_status(g:job)) - call ch_sendraw(g:job, "ccc\naaa\nddd\nbbb\neee\n") - call ch_close_in(g:job) + call assert_equal("run", job_status(job)) + call ch_sendraw(job, "ccc\naaa\nddd\nbbb\neee\n") + call ch_close_in(job) endif - call WaitForAssert({-> assert_equal("dead", job_status(g:job))}) + call WaitForAssert({-> assert_equal("dead", job_status(job))}) sp sortout call WaitFor('line("$") > 3') @@ -985,8 +985,7 @@ func Run_pipe_through_sort(all, use_buffer) call assert_equal(['aaa', 'bbb', 'ddd'], getline(2, 4)) endif - call job_stop(g:job) - unlet g:job + call job_stop(job) if a:use_buffer bwipe! sortin endif @@ -1186,7 +1185,8 @@ func Test_pipe_to_buffer_raw() split testout let job = job_start([s:python, '-c', \ 'import sys; [sys.stdout.write(".") and sys.stdout.flush() for _ in range(10000)]'], options) - call assert_equal("run", job_status(job)) + " the job may be done quickly, also accept "dead" + call assert_match('^\%(dead\|run\)$', job_status(job)) call WaitFor('len(join(getline(1, "$"), "")) >= 10000') try let totlen = 0 @@ -1247,9 +1247,9 @@ func Test_out_cb() endfunc let job = job_start(s:python . " test_channel_pipe.py", \ {'out_cb': dict.outHandler, - \ 'out_mode': 'json', - \ 'err_cb': dict.errHandler, - \ 'err_mode': 'json'}) + \ 'out_mode': 'json', + \ 'err_cb': dict.errHandler, + \ 'err_mode': 'json'}) call assert_equal("run", job_status(job)) try let g:Ch_outmsg = '' @@ -1290,8 +1290,9 @@ func Test_out_close_cb() endfunc let job = job_start(s:python . " test_channel_pipe.py quit now", \ {'out_cb': 'OutHandler', - \ 'close_cb': 'CloseHandler'}) - call assert_equal("run", job_status(job)) + \ 'close_cb': 'CloseHandler'}) + " the job may be done quickly, also accept "dead" + call assert_match('^\%(dead\|run\)$', job_status(job)) try call WaitForAssert({-> assert_equal('quit', g:Ch_msg1)}) call WaitForAssert({-> assert_equal(2, g:Ch_closemsg)}) @@ -1314,7 +1315,8 @@ func Test_read_in_close_cb() endfunc let job = job_start(s:python . " test_channel_pipe.py quit now", \ {'close_cb': 'CloseHandler'}) - call assert_equal("run", job_status(job)) + " the job may be done quickly, also accept "dead" + call assert_match('^\%(dead\|run\)$', job_status(job)) try call WaitForAssert({-> assert_equal('quit', g:Ch_received)}) finally @@ -1338,7 +1340,8 @@ func Test_read_in_close_cb_incomplete() endfunc let job = job_start(s:python . " test_channel_pipe.py incomplete", \ {'close_cb': 'CloseHandler'}) - call assert_equal("run", job_status(job)) + " the job may be done quickly, also accept "dead" + call assert_match('^\%(dead\|run\)$', job_status(job)) try call WaitForAssert({-> assert_equal('incomplete', g:Ch_received)}) finally @@ -1354,10 +1357,10 @@ func Test_out_cb_lambda() call ch_log('Test_out_cb_lambda()') let job = job_start(s:python . " test_channel_pipe.py", - \ {'out_cb': {ch, msg -> execute("let g:Ch_outmsg = 'lambda: ' . msg")}, - \ 'out_mode': 'json', - \ 'err_cb': {ch, msg -> execute(":let g:Ch_errmsg = 'lambda: ' . msg")}, - \ 'err_mode': 'json'}) + \ {'out_cb': {ch, msg -> execute("let g:Ch_outmsg = 'lambda: ' . msg")}, + \ 'out_mode': 'json', + \ 'err_cb': {ch, msg -> execute(":let g:Ch_errmsg = 'lambda: ' . msg")}, + \ 'err_mode': 'json'}) call assert_equal("run", job_status(job)) try let g:Ch_outmsg = '' @@ -1385,14 +1388,13 @@ func Test_close_and_exit_cb() let self.ret['exit_cb'] = job_status(a:job) endfunc - let g:job = job_start(has('win32') ? 'cmd /c echo:' : 'echo', { - \ 'close_cb': g:retdict.close_cb, - \ 'exit_cb': g:retdict.exit_cb, - \ }) - call assert_equal('run', job_status(g:job)) - unlet g:job + let job = job_start([&shell, &shellcmdflag, 'echo'], + \ {'close_cb': g:retdict.close_cb, + \ 'exit_cb': g:retdict.exit_cb}) + " the job may be done quickly, also accept "dead" + call assert_match('^\%(dead\|run\)$', job_status(job)) call WaitForAssert({-> assert_equal(2, len(g:retdict.ret))}) - call assert_match('^\%(dead\|run\)', g:retdict.ret['close_cb']) + call assert_match('^\%(dead\|run\)$', g:retdict.ret['close_cb']) call assert_equal('dead', g:retdict.ret['exit_cb']) unlet g:retdict endfunc @@ -1415,7 +1417,7 @@ func Test_exit_cb_wipes_buf() let g:wipe_buf = bufnr('') let job = job_start(has('win32') ? 'cmd /c echo:' : ['true'], - \ {'exit_cb': 'ExitCbWipe'}) + \ {'exit_cb': 'ExitCbWipe'}) let timer = timer_start(300, {-> feedkeys("\", 'nt')}, {'repeat': 5}) call feedkeys(repeat('g', 1000) . 'o', 'ntx!') call WaitForAssert({-> assert_equal("dead", job_status(job))}) @@ -1933,7 +1935,8 @@ func Test_keep_pty_open() return endif - let job = job_start(s:python . ' -c "import time;time.sleep(0.2)"', {'out_io': 'null', 'err_io': 'null', 'pty': 1}) + let job = job_start(s:python . ' -c "import time;time.sleep(0.2)"', + \ {'out_io': 'null', 'err_io': 'null', 'pty': 1}) let elapsed = WaitFor({-> job_status(job) ==# 'dead'}) call assert_inrange(200, 1000, elapsed) call job_stop(job) @@ -1985,13 +1988,14 @@ func Test_raw_large_data() try let g:out = '' let job = job_start(s:python . " test_channel_pipe.py", - \ {'mode': 'raw', 'drop': 'never', 'noblock': 1, - \ 'callback': {ch, msg -> execute('let g:out .= msg')}}) + \ {'mode': 'raw', 'drop': 'never', 'noblock': 1, + \ 'callback': {ch, msg -> execute('let g:out .= msg')}}) - let want = repeat('X', 79999) . "\n" + let outlen = 79999 + let want = repeat('X', outlen) . "\n" call ch_sendraw(job, want) - let g:Ch_job = job - call WaitForAssert({-> assert_equal("dead", job_status(g:Ch_job))}) + call WaitFor({-> len(g:out) >= outlen}, 10000) + call WaitForAssert({-> assert_equal("dead", job_status(job))}) call assert_equal(want, substitute(g:out, '\r', '', 'g')) finally call job_stop(job) diff --git a/src/testdir/test_filechanged.vim b/src/testdir/test_filechanged.vim index ab34420b41..43f752d277 100644 --- a/src/testdir/test_filechanged.vim +++ b/src/testdir/test_filechanged.vim @@ -90,7 +90,7 @@ func Test_FileChangedShell_reload() endfunc func Test_file_changed_dialog() - if !has('unix') + if !has('unix') || has('gui_running') return endif au! FileChangedShell diff --git a/src/version.c b/src/version.c index 3a75c99fc4..e999fd19fd 100644 --- a/src/version.c +++ b/src/version.c @@ -787,6 +787,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 820, /**/ 819, /**/ From 970f5d39f27717b1a529b7b250a8ed7c3f791949 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 25 Jan 2019 21:52:17 +0100 Subject: [PATCH 3/4] patch 8.1.0821: xxd "usage" output and other arguments not tested Problem: Xxd "usage" output and other arguments not tested. Solution: Add a test to trigger the usage output in various ways. Fix uncovered problem. --- src/testdir/test_xxd.vim | 79 ++++++++++++++++++++++++++++++---------- src/version.c | 2 + src/xxd/xxd.c | 8 ++-- 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/src/testdir/test_xxd.vim b/src/testdir/test_xxd.vim index 4538790f3d..b1a7b0888f 100644 --- a/src/testdir/test_xxd.vim +++ b/src/testdir/test_xxd.vim @@ -20,7 +20,7 @@ endfunc func Test_xxd() call PrepareBuffer(range(1,30)) set ff=unix - w XXDfile + w! XXDfile " Test 1: simple, filter the result through xxd let s:test = 1 @@ -39,15 +39,19 @@ func Test_xxd() exe '%!' . s:xxd_cmd . ' -r' call assert_equal(map(range(1,30), {v,c -> string(c)}), getline(1,'$'), s:Mess(s:test)) - " Test 3: Skip the first 30 bytes + " Test 3: Skip the first 0x30 bytes let s:test += 1 - exe '%!' . s:xxd_cmd . ' -s 0x30 %' - call assert_equal(expected[3:], getline(1,'$'), s:Mess(s:test)) + for arg in ['-s 0x30', '-s0x30', '-s+0x30', '-skip 0x030', '-seek 0x30', '-seek +0x30 --'] + exe '%!' . s:xxd_cmd . ' ' . arg . ' %' + call assert_equal(expected[3:], getline(1,'$'), s:Mess(s:test)) + endfor " Test 4: Skip the first 30 bytes let s:test += 1 - exe '%!' . s:xxd_cmd . ' -s -0x31 %' - call assert_equal(expected[2:], getline(1,'$'), s:Mess(s:test)) + for arg in ['-s -0x31', '-s-0x31'] + exe '%!' . s:xxd_cmd . ' ' . arg . ' %' + call assert_equal(expected[2:], getline(1,'$'), s:Mess(s:test)) + endfor " Test 5: Print 120 bytes as continuous hexdump with 20 octets per line let s:test += 1 @@ -56,7 +60,7 @@ func Test_xxd() if has('win32') && !filereadable(fname) let fname = '../../doc/xxd.1' endif - exe '0r! ' . s:xxd_cmd . ' -l 120 -ps -c 20 ' . fname + exe '0r! ' . s:xxd_cmd . ' -l 120 -ps -c20 ' . fname $d let expected = [ \ '2e54482058584420312022417567757374203139', @@ -69,10 +73,12 @@ func Test_xxd() " Test 6: Print the date from xxd.1 let s:test += 1 - %d - exe '0r! ' . s:xxd_cmd . ' -s 0x36 -l 13 -c 13 ' . fname - $d - call assert_equal('00000036: 3231 7374 204d 6179 2031 3939 36 21st May 1996', getline(1), s:Mess(s:test)) + for arg in ['-l 13', '-l13', '-len 13'] + %d + exe '0r! ' . s:xxd_cmd . ' -s 0x36 -l 13 -cols 13 ' . fname + $d + call assert_equal('00000036: 3231 7374 204d 6179 2031 3939 36 21st May 1996', getline(1), s:Mess(s:test)) + endfor " Test 7: Print C include let s:test += 1 @@ -87,14 +93,16 @@ func Test_xxd() " Test 8: Print C include capitalized let s:test += 1 - call writefile(['TESTabcd09'], 'XXDfile') - %d - exe '0r! ' . s:xxd_cmd . ' -i -C XXDfile' - $d - let expected = ['unsigned char XXDFILE[] = {', - \ ' 0x54, 0x45, 0x53, 0x54, 0x61, 0x62, 0x63, 0x64, 0x30, 0x39, 0x0a', '};', - \ 'unsigned int XXDFILE_LEN = 11;'] - call assert_equal(expected, getline(1,'$'), s:Mess(s:test)) + for arg in ['-C', '-capitalize'] + call writefile(['TESTabcd09'], 'XXDfile') + %d + exe '0r! ' . s:xxd_cmd . ' -i ' . arg . ' XXDfile' + $d + let expected = ['unsigned char XXDFILE[] = {', + \ ' 0x54, 0x45, 0x53, 0x54, 0x61, 0x62, 0x63, 0x64, 0x30, 0x39, 0x0a', '};', + \ 'unsigned int XXDFILE_LEN = 11;'] + call assert_equal(expected, getline(1,'$'), s:Mess(s:test)) + endfor " Test 9: Create a file with containing a single 'A' let s:test += 1 @@ -110,6 +118,39 @@ func Test_xxd() call PrepareBuffer(readfile('XXDfile')[0]) call assert_equal('A', getline(1), s:Mess(s:test)) call delete('XXDfile') + + " Test 10: group with 4 octets + let s:test += 1 + for arg in ['-g 4', '-group 4', '-g4'] + call writefile(['TESTabcd09'], 'XXDfile') + %d + exe '0r! ' . s:xxd_cmd . ' ' . arg . ' XXDfile' + $d + let expected = ['00000000: 54455354 61626364 30390a TESTabcd09.'] + call assert_equal(expected, getline(1,'$'), s:Mess(s:test)) + call delete('XXDfile') + endfor + + " TODO: + " -o -offset + %d bw! endfunc + +" Various ways with wrong arguments that trigger the usage output. +func Test_xxd_usage() + for arg in ['-c', '-g', '-o', '-s', '-l', '-X', 'one two three'] + new + exe 'r! ' . s:xxd_cmd . ' ' . arg + call assert_match("Usage:", join(getline(1, 3))) + bwipe! + endfor +endfunc + +func Test_xxd_version() + new + exe 'r! ' . s:xxd_cmd . ' -v' + call assert_match("xxd V1.10 .* by Juergen Weigert", join(getline(1, 3))) + bwipe! +endfunc diff --git a/src/version.c b/src/version.c index e999fd19fd..ad2f5e7a7b 100644 --- a/src/version.c +++ b/src/version.c @@ -787,6 +787,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 821, /**/ 820, /**/ diff --git a/src/xxd/xxd.c b/src/xxd/xxd.c index d102db451b..d7a556a31d 100644 --- a/src/xxd/xxd.c +++ b/src/xxd/xxd.c @@ -508,10 +508,10 @@ main(int argc, char *argv[]) } else if (!STRNCMP(pp, "-c", 2)) { - if (pp[2] && STRNCMP("ols", pp + 2, 3)) - cols = (int)strtol(pp + 2, NULL, 0); - else if (pp[2] && STRNCMP("apitalize", pp + 2, 9)) + if (pp[2] && !STRNCMP("apitalize", pp + 2, 9)) capitalize = 1; + else if (pp[2] && STRNCMP("ols", pp + 2, 3)) + cols = (int)strtol(pp + 2, NULL, 0); else { if (!argv[2]) @@ -523,7 +523,7 @@ main(int argc, char *argv[]) } else if (!STRNCMP(pp, "-g", 2)) { - if (pp[2] && STRNCMP("group", pp + 2, 5)) + if (pp[2] && STRNCMP("roup", pp + 2, 4)) octspergrp = (int)strtol(pp + 2, NULL, 0); else { From cb574f415486adff645ce384979bfecf27f5be8c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 25 Jan 2019 22:29:57 +0100 Subject: [PATCH 4/4] patch 8.1.0822: peeking and flushing output slows down execution Problem: Peeking and flushing output slows down execution. Solution: Do not update the mode message when global_busy is set. Do not flush when only peeking for a character. (Ken Takata) --- src/edit.c | 2 +- src/getchar.c | 5 +++-- src/proto/screen.pro | 1 + src/screen.c | 32 ++++++++++++++++++++++---------- src/version.c | 2 ++ 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/edit.c b/src/edit.c index 92dbf4cb51..f797d7f04e 100644 --- a/src/edit.c +++ b/src/edit.c @@ -8722,7 +8722,7 @@ ins_esc( */ if (reg_recording != 0 || restart_edit != NUL) showmode(); - else if (p_smd) + else if (p_smd && !skip_showmode()) msg(""); return TRUE; /* exit Insert mode */ diff --git a/src/getchar.c b/src/getchar.c index ff1b06b026..fe74dbfa1c 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -3039,9 +3039,10 @@ inchar( /* * Always flush the output characters when getting input characters - * from the user. + * from the user and not just peeking. */ - out_flush(); + if (wait_time == -1L || wait_time > 10L) + out_flush(); /* * Fill up to a third of the buffer, because each character may be diff --git a/src/proto/screen.pro b/src/proto/screen.pro index b78796e744..0657831db6 100644 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -49,6 +49,7 @@ int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear, int clear_attr); int screen_ins_lines(int off, int row, int line_count, int end, int clear_attr, win_T *wp); int screen_del_lines(int off, int row, int line_count, int end, int force, int clear_attr, win_T *wp); +int skip_showmode(void); int showmode(void); void unshowmode(int force); void clearmode(void); diff --git a/src/screen.c b/src/screen.c index a80e8de65e..9cdbf16b09 100644 --- a/src/screen.c +++ b/src/screen.c @@ -10109,6 +10109,26 @@ screen_del_lines( return OK; } +/* + * Return TRUE when postponing displaying the mode message: when not redrawing + * or inside a mapping. + */ + int +skip_showmode() +{ + // Call char_avail() only when we are going to show something, because it + // takes a bit of time. redrawing() may also call char_avail_avail(). + if (global_busy + || msg_silent != 0 + || !redrawing() + || (char_avail() && !KeyTyped)) + { + redraw_cmdline = TRUE; // show mode later + return TRUE; + } + return FALSE; +} + /* * Show the current mode and ruler. * @@ -10135,16 +10155,8 @@ showmode(void) || VIsual_active)); if (do_mode || reg_recording != 0) { - /* - * Don't show mode right now, when not redrawing or inside a mapping. - * Call char_avail() only when we are going to show something, because - * it takes a bit of time. - */ - if (!redrawing() || (char_avail() && !KeyTyped) || msg_silent != 0) - { - redraw_cmdline = TRUE; /* show mode later */ - return 0; - } + if (skip_showmode()) + return 0; // show mode later nwr_save = need_wait_return; diff --git a/src/version.c b/src/version.c index ad2f5e7a7b..4d7730cf55 100644 --- a/src/version.c +++ b/src/version.c @@ -787,6 +787,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 822, /**/ 821, /**/