diff options
-rw-r--r-- | runtime/doc/eval.txt | 11 | ||||
-rwxr-xr-x | scripts/vim-patch.sh | 2 | ||||
-rw-r--r-- | src/nvim/edit.c | 6 | ||||
-rw-r--r-- | src/nvim/eval.c | 41 | ||||
-rw-r--r-- | src/nvim/event/process.c | 3 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 4 | ||||
-rw-r--r-- | src/nvim/globals.h | 4 | ||||
-rw-r--r-- | src/nvim/mark.c | 25 | ||||
-rw-r--r-- | src/nvim/option.c | 9 | ||||
-rw-r--r-- | src/nvim/screen.c | 2 | ||||
-rw-r--r-- | src/nvim/search.c | 10 | ||||
-rw-r--r-- | src/nvim/shada.c | 14 | ||||
-rw-r--r-- | src/nvim/tag.c | 9 | ||||
-rw-r--r-- | src/nvim/testdir/test_cmdline.vim | 44 | ||||
-rw-r--r-- | src/nvim/testdir/test_mksession.vim | 11 | ||||
-rw-r--r-- | src/nvim/testdir/test_popup.vim | 30 | ||||
-rw-r--r-- | src/nvim/vim.h | 3 | ||||
-rw-r--r-- | src/nvim/window.c | 41 | ||||
-rw-r--r-- | test/README.md | 5 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 9 | ||||
-rw-r--r-- | test/functional/core/job_spec.lua | 42 | ||||
-rw-r--r-- | test/functional/eval/ctx_functions_spec.lua | 8 | ||||
-rw-r--r-- | test/functional/plugin/shada_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/ui/wildmode_spec.lua | 4 | ||||
-rw-r--r-- | test/helpers.lua | 2 | ||||
-rw-r--r-- | test/unit/viml/expressions/parser_spec.lua | 4 |
27 files changed, 226 insertions, 127 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index f45f99ede2..06f88955c9 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -5411,7 +5411,8 @@ jobstop({id}) *jobstop()* See |job-control|. jobwait({ids}[, {timeout}]) *jobwait()* - Wait for a set of jobs to complete. + Wait for a set of jobs and their |on_exit| handlers to + complete. {ids} is a list of |job-id|s to wait for. {timeout} is the maximum waiting time in milliseconds, -1 @@ -5427,10 +5428,10 @@ jobwait({ids}[, {timeout}]) *jobwait()* Returns a list of len({ids}) integers, where each integer is the wait-result of the corresponding job. Each wait-result is one of the following: - * Exit-code, if the job exited - * -1 if the timeout was exceeded - * -2 if the job was interrupted - * -3 if the |job-id| is invalid + Exit-code, if the job exited + -1 if the timeout was exceeded + -2 if the job was interrupted (by |CTRL-C|) + -3 if the job-id is invalid join({list} [, {sep}]) *join()* Join the items in {list} together into one String. diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index a5dca26b46..2cc32f0dd0 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -430,6 +430,7 @@ list_missing_vimpatches() { fi # Get missing Vim commits + set +u # Avoid "unbound variable" with bash < 4.4 below. for vim_commit in $(list_vim_commits "${git_log_args[@]}"); do # Check for vim-patch:<commit_hash> (usually runtime updates). token="vim-patch:${vim_commit:0:7}" @@ -449,6 +450,7 @@ list_missing_vimpatches() { echo "$vim_commit" fi done + set -u } # Prints a human-formatted list of Vim commits, with instructional messages. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index ca64cc091d..16c4882975 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -5541,13 +5541,15 @@ insertchar ( // 'paste' is set).. // Don't do this when there an InsertCharPre autocommand is defined, // because we need to fire the event for every character. + // Do the check for InsertCharPre before the call to vpeekc() because the + // InsertCharPre autocommand could change the input buffer. if (!ISSPECIAL(c) && (!has_mbyte || (*mb_char2len)(c) == 1) + && !has_event(EVENT_INSERTCHARPRE) && vpeekc() != NUL && !(State & REPLACE_FLAG) && !cindent_on() - && !p_ri - && !has_event(EVENT_INSERTCHARPRE)) { + && !p_ri) { #define INPUT_BUFLEN 100 char_u buf[INPUT_BUFLEN + 1]; int i; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index b9a0913baa..fa9777b651 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -12437,35 +12437,30 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (check_restricted() || check_secure()) { return; } - if (argvars[0].v_type != VAR_LIST || (argvars[1].v_type != VAR_NUMBER && argvars[1].v_type != VAR_UNKNOWN)) { EMSG(_(e_invarg)); return; } - + ui_busy_start(); list_T *args = argvars[0].vval.v_list; Channel **jobs = xcalloc(tv_list_len(args), sizeof(*jobs)); - - ui_busy_start(); MultiQueue *waiting_jobs = multiqueue_new_parent(loop_on_put, &main_loop); - // For each item in the input list append an integer to the output list. -3 - // is used to represent an invalid job id, -2 is for a interrupted job and - // -1 for jobs that were skipped or timed out. + // Validate, prepare jobs for waiting. int i = 0; TV_LIST_ITER_CONST(args, arg, { Channel *chan = NULL; if (TV_LIST_ITEM_TV(arg)->v_type != VAR_NUMBER || !(chan = find_job(TV_LIST_ITEM_TV(arg)->vval.v_number, false))) { - jobs[i] = NULL; + jobs[i] = NULL; // Invalid job. } else { jobs[i] = chan; channel_incref(chan); if (chan->stream.proc.status < 0) { - // Process any pending events for the job because we'll temporarily - // replace the parent queue + // Process any pending events on the job's queue before temporarily + // replacing it. multiqueue_process_events(chan->events); multiqueue_replace_parent(chan->events, waiting_jobs); } @@ -12482,40 +12477,36 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) for (i = 0; i < tv_list_len(args); i++) { if (remaining == 0) { - // timed out - break; + break; // Timeout. } - - // if the job already exited, but wasn't freed yet - if (jobs[i] == NULL || jobs[i]->stream.proc.status >= 0) { - continue; + if (jobs[i] == NULL) { + continue; // Invalid job, will assign status=-3 below. } - int status = process_wait(&jobs[i]->stream.proc, remaining, waiting_jobs); if (status < 0) { - // interrupted or timed out, skip remaining jobs. - break; + break; // Interrupted (CTRL-C) or timeout, skip remaining jobs. } if (remaining > 0) { uint64_t now = os_hrtime(); - remaining -= (int) ((now - before) / 1000000); + remaining = MIN(0, remaining - (int)((now - before) / 1000000)); before = now; - if (remaining <= 0) { - break; - } } } list_T *const rv = tv_list_alloc(tv_list_len(args)); - // restore the parent queue for any jobs still alive + // For each job: + // * Restore its parent queue if the job is still alive. + // * Append its status to the output list, or: + // -3 for "invalid job id" + // -2 for "interrupted" (user hit CTRL-C) + // -1 for jobs that were skipped or timed out for (i = 0; i < tv_list_len(args); i++) { if (jobs[i] == NULL) { tv_list_append_number(rv, -3); continue; } - // restore the parent queue for the job multiqueue_process_events(jobs[i]->events); multiqueue_replace_parent(jobs[i]->events, main_loop.events); diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index c31ecdaddf..8e9964bd37 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -181,8 +181,7 @@ int process_wait(Process *proc, int ms, MultiQueue *events) got_int // interrupted by the user || proc->refcount == 1); // job exited - // we'll assume that a user frantically hitting interrupt doesn't like - // the current job. Signal that it has to be killed. + // Assume that a user hitting CTRL-C does not like the current job. Kill it. if (got_int) { got_int = false; process_stop(proc); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index b880ec4f6d..85ec4efd3a 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -9990,12 +9990,18 @@ static void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } +void set_no_hlsearch(bool flag) +{ + no_hlsearch = flag; + set_vim_var_nr(VV_HLSEARCH, !no_hlsearch && p_hls); +} + /* * ":nohlsearch" */ static void ex_nohlsearch(exarg_T *eap) { - SET_NO_HLSEARCH(TRUE); + set_no_hlsearch(true); redraw_all_later(SOME_VALID); } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 4f35555098..f00367d9ca 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1830,7 +1830,7 @@ static int command_line_changed(CommandLineState *s) // If there is no command line, don't do anything if (ccline.cmdlen == 0) { i = 0; - SET_NO_HLSEARCH(true); // turn off previous highlight + set_no_hlsearch(true); // turn off previous highlight redraw_all_later(SOME_VALID); } else { int search_flags = SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK; @@ -1888,7 +1888,7 @@ static int command_line_changed(CommandLineState *s) // Disable 'hlsearch' highlighting if the pattern matches // everything. Avoids a flash when typing "foo\|". if (empty_pattern(ccline.cmdbuff)) { - SET_NO_HLSEARCH(true); + set_no_hlsearch(true); } validate_cursor(); diff --git a/src/nvim/globals.h b/src/nvim/globals.h index ad321963fe..9a7b5425bf 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -862,8 +862,8 @@ EXTERN char_u wim_flags[4]; # define STL_IN_TITLE 2 EXTERN int stl_syntax INIT(= 0); -/* don't use 'hlsearch' temporarily */ -EXTERN int no_hlsearch INIT(= FALSE); +// don't use 'hlsearch' temporarily +EXTERN bool no_hlsearch INIT(= false); /* Page number used for %N in 'pageheader' and 'guitablabel'. */ EXTERN linenr_T printer_page_num; diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 9f357575d0..e103d3cb55 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -1162,21 +1162,18 @@ void mark_col_adjust( // When deleting lines, this may create duplicate marks in the // jumplist. They will be removed here for the specified window. -// When "loadfiles" is true first ensure entries have the "fnum" field set -// (this may be a bit slow). -void cleanup_jumplist(win_T *wp, bool loadfiles) +// When "checktail" is true, removes tail jump if it matches current position. +void cleanup_jumplist(win_T *wp, bool checktail) { int i; - if (loadfiles) { - // If specified, load all the files from the jump list. This is - // needed to properly clean up duplicate entries, but will take some - // time. - for (i = 0; i < wp->w_jumplistlen; i++) { - if ((wp->w_jumplist[i].fmark.fnum == 0) - && (wp->w_jumplist[i].fmark.mark.lnum != 0)) { - fname2fnum(&wp->w_jumplist[i]); - } + // Load all the files from the jump list. This is + // needed to properly clean up duplicate entries, but will take some + // time. + for (i = 0; i < wp->w_jumplistlen; i++) { + if ((wp->w_jumplist[i].fmark.fnum == 0) + && (wp->w_jumplist[i].fmark.mark.lnum != 0)) { + fname2fnum(&wp->w_jumplist[i]); } } @@ -1213,8 +1210,8 @@ void cleanup_jumplist(win_T *wp, bool loadfiles) // When pointer is below last jump, remove the jump if it matches the current // line. This avoids useless/phantom jumps. #9805 - if (loadfiles // otherwise (i.e.: Shada), last entry should be kept - && wp->w_jumplistlen && wp->w_jumplistidx == wp->w_jumplistlen) { + if (checktail && wp->w_jumplistlen + && wp->w_jumplistidx == wp->w_jumplistlen) { const xfmark_T *fm_last = &wp->w_jumplist[wp->w_jumplistlen - 1]; if (fm_last->fmark.fnum == curbuf->b_fnum && fm_last->fmark.mark.lnum == wp->w_cursor.lnum) { diff --git a/src/nvim/option.c b/src/nvim/option.c index d1753526a7..ed9128dbbf 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3959,7 +3959,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, redraw_all_later(SOME_VALID); } else if ((int *)varp == &p_hls) { // when 'hlsearch' is set or reset: reset no_hlsearch - SET_NO_HLSEARCH(false); + set_no_hlsearch(false); } else if ((int *)varp == &curwin->w_p_scb) { // when 'scrollbind' is set: snapshot the current position to avoid a jump // at the end of normal_cmd() @@ -4330,19 +4330,26 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, // Number options that need some action when changed if (pp == &p_wh) { + // 'winheight' if (!ONE_WINDOW && curwin->w_height < p_wh) { win_setheight((int)p_wh); } } else if (pp == &p_hh) { + // 'helpheight' if (!ONE_WINDOW && curbuf->b_help && curwin->w_height < p_hh) { win_setheight((int)p_hh); } } else if (pp == &p_wmh) { + // 'winminheight' win_setminheight(); } else if (pp == &p_wiw) { + // 'winwidth' if (!ONE_WINDOW && curwin->w_width < p_wiw) { win_setwidth((int)p_wiw); } + } else if (pp == &p_wmw) { + // 'winminwidth' + win_setminwidth(); } else if (pp == &p_ls) { last_status(false); // (re)set last window status line. } else if (pp == &p_stal) { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index b9469686b5..13eb088813 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -5762,7 +5762,7 @@ next_search_hl ( if (shl == &search_hl) { // don't free regprog in the match list, it's a copy vim_regfree(shl->rm.regprog); - SET_NO_HLSEARCH(TRUE); + set_no_hlsearch(true); } shl->rm.regprog = NULL; shl->lnum = 0; diff --git a/src/nvim/search.c b/src/nvim/search.c index 26549208a8..7d1c19d68c 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -100,7 +100,7 @@ static struct spat saved_spats[2]; // searching static struct spat saved_last_search_spat; static int saved_last_idx = 0; -static int saved_no_hlsearch = 0; +static bool saved_no_hlsearch = false; static char_u *mr_pattern = NULL; // pattern used by search_regcomp() static int mr_pattern_alloced = false; // mr_pattern was allocated @@ -248,7 +248,7 @@ void save_re_pat(int idx, char_u *pat, int magic) /* If 'hlsearch' set and search pat changed: need redraw. */ if (p_hls) redraw_all_later(SOME_VALID); - SET_NO_HLSEARCH(FALSE); + set_no_hlsearch(false); } } @@ -281,7 +281,7 @@ void restore_search_patterns(void) free_spat(&spats[1]); spats[1] = saved_spats[1]; last_idx = saved_last_idx; - SET_NO_HLSEARCH(saved_no_hlsearch); + set_no_hlsearch(saved_no_hlsearch); } } @@ -330,7 +330,7 @@ void restore_last_search_pattern(void) spats[RE_SEARCH] = saved_last_search_spat; set_vv_searchforward(); last_idx = saved_last_idx; - SET_NO_HLSEARCH(saved_no_hlsearch); + set_no_hlsearch(saved_no_hlsearch); } char_u *last_search_pattern(void) @@ -1048,7 +1048,7 @@ int do_search( */ if (no_hlsearch && !(options & SEARCH_KEEP)) { redraw_all_later(SOME_VALID); - SET_NO_HLSEARCH(FALSE); + set_no_hlsearch(false); } /* diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 69e6d61464..7e7e7cfdf7 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -32,6 +32,7 @@ #include "nvim/api/private/helpers.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" +#include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/search.h" #include "nvim/regexp.h" @@ -1274,7 +1275,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) if (cur_entry.data.search_pattern.is_last_used) { set_last_used_pattern( cur_entry.data.search_pattern.is_substitute_pattern); - SET_NO_HLSEARCH(!cur_entry.data.search_pattern.highlighted); + set_no_hlsearch(!cur_entry.data.search_pattern.highlighted); } // Do not free shada entry: its allocated memory was saved above. break; @@ -2736,6 +2737,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, } // Initialize jump list + setpcmark(); + cleanup_jumplist(curwin, false); wms->jumps_size = shada_init_jumps(wms->jumps, &removable_bufs); // Initialize global marks @@ -4085,11 +4088,13 @@ static bool shada_removable(const char *name) static inline size_t shada_init_jumps( PossiblyFreedShadaEntry *jumps, khash_t(bufset) *const removable_bufs) { - // Initialize jump list + if (!curwin->w_jumplistlen) { + return 0; + } + size_t jumps_size = 0; const void *jump_iter = NULL; - setpcmark(); - cleanup_jumplist(curwin, false); + do { xfmark_T fm; jump_iter = mark_jumplist_iter(jump_iter, curwin, &fm); @@ -4163,6 +4168,7 @@ void shada_encode_jumps(msgpack_sbuffer *const sbuf) khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); find_removable_bufs(&removable_bufs); PossiblyFreedShadaEntry jumps[JUMPLISTSIZE]; + cleanup_jumplist(curwin, true); size_t jumps_size = shada_init_jumps(jumps, &removable_bufs); msgpack_packer packer; msgpack_packer_init(&packer, sbuf, msgpack_sbuffer_write); diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 88676abc2e..beee3c7594 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -2310,7 +2310,6 @@ static int jumpto_tag( int retval = FAIL; int getfile_result = GETFILE_UNUSED; int search_options; - int save_no_hlsearch; win_T *curwin_save = NULL; char_u *full_fname = NULL; const bool old_KeyTyped = KeyTyped; // getting the file may reset it @@ -2453,9 +2452,9 @@ static int jumpto_tag( secure = 1; ++sandbox; save_magic = p_magic; - p_magic = FALSE; /* always execute with 'nomagic' */ - /* Save value of no_hlsearch, jumping to a tag is not a real search */ - save_no_hlsearch = no_hlsearch; + p_magic = false; // always execute with 'nomagic' + // Save value of no_hlsearch, jumping to a tag is not a real search + const bool save_no_hlsearch = no_hlsearch; /* * If 'cpoptions' contains 't', store the search pattern for the "n" @@ -2560,7 +2559,7 @@ static int jumpto_tag( --sandbox; /* restore no_hlsearch when keeping the old search pattern */ if (search_options) { - SET_NO_HLSEARCH(save_no_hlsearch); + set_no_hlsearch(save_no_hlsearch); } // Return OK if jumped to another file (at least we found the file!). diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index f43ea0e923..e6aafd964b 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -15,14 +15,48 @@ func Test_complete_list() endfunc func Test_complete_wildmenu() - call writefile(['testfile1'], 'Xtestfile1') - call writefile(['testfile2'], 'Xtestfile2') + call mkdir('Xdir1/Xdir2', 'p') + call writefile(['testfile1'], 'Xdir1/Xtestfile1') + call writefile(['testfile2'], 'Xdir1/Xtestfile2') + call writefile(['testfile3'], 'Xdir1/Xdir2/Xtestfile3') + call writefile(['testfile3'], 'Xdir1/Xdir2/Xtestfile4') set wildmenu - call feedkeys(":e Xtestf\t\t\r", "tx") + + " Pressing <Tab> completes, and moves to next files when pressing again. + call feedkeys(":e Xdir1/\<Tab>\<Tab>\<CR>", 'tx') + call assert_equal('testfile1', getline(1)) + call feedkeys(":e Xdir1/\<Tab>\<Tab>\<Tab>\<CR>", 'tx') + call assert_equal('testfile2', getline(1)) + + " <S-Tab> is like <Tab> but begin with the last match and then go to + " previous. + call feedkeys(":e Xdir1/Xtest\<S-Tab>\<CR>", 'tx') call assert_equal('testfile2', getline(1)) + call feedkeys(":e Xdir1/Xtest\<S-Tab>\<S-Tab>\<CR>", 'tx') + call assert_equal('testfile1', getline(1)) - call delete('Xtestfile1') - call delete('Xtestfile2') + " <Left>/<Right> to move to previous/next file. + call feedkeys(":e Xdir1/\<Tab>\<Right>\<CR>", 'tx') + call assert_equal('testfile1', getline(1)) + call feedkeys(":e Xdir1/\<Tab>\<Right>\<Right>\<CR>", 'tx') + call assert_equal('testfile2', getline(1)) + call feedkeys(":e Xdir1/\<Tab>\<Right>\<Right>\<Left>\<CR>", 'tx') + call assert_equal('testfile1', getline(1)) + + " <Up>/<Down> to go up/down directories. + call feedkeys(":e Xdir1/\<Tab>\<Down>\<CR>", 'tx') + call assert_equal('testfile3', getline(1)) + call feedkeys(":e Xdir1/\<Tab>\<Down>\<Up>\<Right>\<CR>", 'tx') + call assert_equal('testfile1', getline(1)) + + " cleanup + %bwipe + call delete('Xdir1/Xdir2/Xtestfile4') + call delete('Xdir1/Xdir2/Xtestfile3') + call delete('Xdir1/Xtestfile2') + call delete('Xdir1/Xtestfile1') + call delete('Xdir1/Xdir2', 'd') + call delete('Xdir1', 'd') set nowildmenu endfunc diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim index 0e56ed2ff3..b7169444d1 100644 --- a/src/nvim/testdir/test_mksession.vim +++ b/src/nvim/testdir/test_mksession.vim @@ -106,13 +106,22 @@ endfunc func Test_mksession_winheight() new - set winheight=10 winminheight=2 + set winheight=10 + set winminheight=2 mksession! Xtest_mks.out source Xtest_mks.out call delete('Xtest_mks.out') endfunc +func Test_mksession_large_winheight() + set winheight=999 + mksession! Xtest_mks_winheight.out + set winheight& + source Xtest_mks_winheight.out + call delete('Xtest_mks_winheight.out') +endfunc + " Verify that arglist is stored correctly to the session file. func Test_mksession_arglist() argdel * diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index 162df4b76e..53df30bb19 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -746,6 +746,36 @@ func Test_popup_complete_backwards() bwipe! endfunc +fun! Test_complete_o_tab() + throw 'skipped: Nvim does not support test_override()' + let s:o_char_pressed = 0 + + fun! s:act_on_text_changed() + if s:o_char_pressed + let s:o_char_pressed = 0 + call feedkeys("\<c-x>\<c-n>", 'i') + endif + endf + + set completeopt=menu,noselect + new + imap <expr> <buffer> <tab> pumvisible() ? "\<c-p>" : "X" + autocmd! InsertCharPre <buffer> let s:o_char_pressed = (v:char ==# 'o') + autocmd! TextChangedI <buffer> call <sid>act_on_text_changed() + call setline(1, ['hoard', 'hoax', 'hoarse', '']) + let l:expected = ['hoard', 'hoax', 'hoarse', 'hoax', 'hoax'] + call cursor(4,1) + call test_override("char_avail", 1) + call feedkeys("Ahoa\<tab>\<tab>\<c-y>\<esc>", 'tx') + call feedkeys("oho\<tab>\<tab>\<c-y>\<esc>", 'tx') + call assert_equal(l:expected, getline(1,'$')) + + call test_override("char_avail", 0) + bwipe! + set completeopt& + delfunc s:act_on_text_changed +endf + func Test_popup_complete_info_01() new inoremap <buffer><F5> <C-R>=complete_info().mode<CR> diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 60737014b3..51f143a3d7 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -296,9 +296,6 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() #include "nvim/buffer_defs.h" // buffer and windows #include "nvim/ex_cmds_defs.h" // Ex command defines -# define SET_NO_HLSEARCH(flag) no_hlsearch = (flag); set_vim_var_nr( \ - VV_HLSEARCH, !no_hlsearch && p_hls) - // Used for flags in do_in_path() #define DIP_ALL 0x01 // all matches, not just the first one #define DIP_DIR 0x02 // find directories instead of files diff --git a/src/nvim/window.c b/src/nvim/window.c index 0e8cfcedf5..6861e19ca7 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5229,27 +5229,42 @@ static void frame_setwidth(frame_T *curfrp, int width) } } -/* - * Check 'winminheight' for a valid value. - */ +// Check 'winminheight' for a valid value and reduce it if needed. void win_setminheight(void) { - int room; - int first = TRUE; + bool first = true; - /* loop until there is a 'winminheight' that is possible */ + // loop until there is a 'winminheight' that is possible while (p_wmh > 0) { - /* TODO: handle vertical splits */ - room = -p_wh; - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - room += wp->w_height - p_wmh; + const int room = Rows - p_ch; + const int needed = frame_minheight(topframe, NULL); + if (room >= needed) { + break; + } + p_wmh--; + if (first) { + EMSG(_(e_noroom)); + first = false; } - if (room >= 0) + } +} + +// Check 'winminwidth' for a valid value and reduce it if needed. +void win_setminwidth(void) +{ + bool first = true; + + // loop until there is a 'winminheight' that is possible + while (p_wmw > 0) { + const int room = Columns; + const int needed = frame_minwidth(topframe, NULL); + if (room >= needed) { break; - --p_wmh; + } + p_wmw--; if (first) { EMSG(_(e_noroom)); - first = FALSE; + first = false; } } } diff --git a/test/README.md b/test/README.md index 73d51c995c..60279589b1 100644 --- a/test/README.md +++ b/test/README.md @@ -249,11 +249,6 @@ the file). Configuration ============= -busted (luassert) by default does not print the full result of deeply-nested -tables. But sometimes it's useful while debugging a test. - - assert:set_parameter('TableFormatLevel', 1000000) - Test behaviour is affected by environment variables. Currently supported (Functional, Unit, Benchmarks) (when Defined; when set to _1_; when defined, treated as Integer; when defined, treated as String; when defined, treated as diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 851feddb54..07c0c5c8f3 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -922,11 +922,9 @@ describe('API', function() }, ['jumps'] = eval(([[ - filter(map(add( - getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }), - 'filter( - { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum }, - { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)') + filter(map(getjumplist()[0], 'filter( + { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum }, + { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)') ]]):gsub('\n', '')), ['buflist'] = eval([[ @@ -1568,7 +1566,6 @@ describe('API', function() return ('%s(%s)%s'):format(typ, args, rest) end end - assert:set_parameter('TableFormatLevel', 1000000) require('test.unit.viml.expressions.parser_tests')( it_maybe_pending, _check_parsing, hl, fmtn) end) diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index 73b0a0009d..88951e5b51 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -582,13 +582,17 @@ describe('jobs', function() it('will run callbacks while waiting', function() source([[ - let g:dict = {'id': 10} - let g:exits = 0 - function g:dict.on_exit(id, code, event) + let g:dict = {} + let g:jobs = [] + let g:exits = [] + function g:dict.on_stdout(id, code, event) abort + call add(g:jobs, a:id) + endfunction + function g:dict.on_exit(id, code, event) abort if a:code != 5 throw 'Error!' endif - let g:exits += 1 + call add(g:exits, a:id) endfunction call jobwait(has('win32') ? [ \ jobstart('Start-Sleep -Milliseconds 100; exit 5', g:dict), @@ -601,9 +605,10 @@ describe('jobs', function() \ jobstart('sleep 0.050; exit 5', g:dict), \ jobstart('sleep 0.070; exit 5', g:dict) \ ]) - call rpcnotify(g:channel, 'wait', g:exits) + call rpcnotify(g:channel, 'wait', sort(g:jobs), sort(g:exits)) ]]) - eq({'notification', 'wait', {4}}, next_msg()) + eq({'notification', 'wait', + {{3,4,5,6}, {3,4,5,6}}}, next_msg()) end) it('will return status codes in the order of passed ids', function() @@ -728,15 +733,28 @@ describe('jobs', function() end) end) - -- FIXME need to wait until jobsend succeeds before calling jobstop - pending('will only emit the "exit" event after "stdout" and "stderr"', function() - nvim('command', "let g:job_opts.on_stderr = function('s:OnEvent')") + pending('exit event follows stdout, stderr', function() + nvim('command', "let g:job_opts.on_stderr = function('OnEvent')") nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") - local jobid = nvim('eval', 'j') nvim('eval', 'jobsend(j, "abcdef")') nvim('eval', 'jobstop(j)') - eq({'notification', 'j', {0, {jobid, 'stdout', {'abcdef'}}}}, next_msg()) - eq({'notification', 'j', {0, {jobid, 'exit'}}}, next_msg()) + expect_msg_seq( + { {'notification', 'stdout', {0, {'abcdef'}}}, + {'notification', 'stdout', {0, {''}}}, + {'notification', 'stderr', {0, {''}}}, + }, + -- Alternative sequence: + { {'notification', 'stderr', {0, {''}}}, + {'notification', 'stdout', {0, {'abcdef'}}}, + {'notification', 'stdout', {0, {''}}}, + }, + -- Alternative sequence: + { {'notification', 'stdout', {0, {'abcdef'}}}, + {'notification', 'stderr', {0, {''}}}, + {'notification', 'stdout', {0, {''}}}, + } + ) + eq({'notification', 'exit', {0, 143}}, next_msg()) end) it('cannot have both rpc and pty options', function() diff --git a/test/functional/eval/ctx_functions_spec.lua b/test/functional/eval/ctx_functions_spec.lua index 35133e2341..742fc4893b 100644 --- a/test/functional/eval/ctx_functions_spec.lua +++ b/test/functional/eval/ctx_functions_spec.lua @@ -291,11 +291,9 @@ describe('context functions', function() local with_jumps = { ['jumps'] = eval(([[ - filter(map(add( - getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }), - 'filter( - { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum }, - { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)') + filter(map(getjumplist()[0], 'filter( + { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum }, + { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)') ]]):gsub('\n', '')) } diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua index c0104a58f7..d96b479a62 100644 --- a/test/functional/plugin/shada_spec.lua +++ b/test/functional/plugin/shada_spec.lua @@ -1360,8 +1360,6 @@ describe('autoload/shada.vim', function() nvim_command('unlet g:__actual') end - assert:set_parameter('TableFormatLevel', 100) - it('works with multiple items', function() strings2sd_eq({{ type=11, timestamp=0, data={ diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index 738466ae2b..2215c0c7d9 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -98,8 +98,8 @@ describe("'wildmenu'", function() ]]} -- cmdline CTRL-D display should also be preserved. - feed([[<C-\><C-N>]]) - feed([[:sign <C-D>]]) -- Invoke cmdline CTRL-D. + feed([[<C-U>]]) + feed([[sign <C-D>]]) -- Invoke cmdline CTRL-D. expect_stay_unchanged{grid=[[ :sign | define place | diff --git a/test/helpers.lua b/test/helpers.lua index 25fff55596..779d33e3b1 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -6,6 +6,8 @@ local lfs = require('lfs') local relpath = require('pl.path').relpath local Paths = require('test.config.paths') +assert:set_parameter('TableFormatLevel', 100) + local quote_me = '[^.%w%+%-%@%_%/]' -- complement (needn't quote) local function shell_quote(str) if string.find(str, quote_me) or str == '' then diff --git a/test/unit/viml/expressions/parser_spec.lua b/test/unit/viml/expressions/parser_spec.lua index a8f29529ec..032baf6578 100644 --- a/test/unit/viml/expressions/parser_spec.lua +++ b/test/unit/viml/expressions/parser_spec.lua @@ -451,10 +451,6 @@ local function phl2lua(pstate) return ret end -child_call_once(function() - assert:set_parameter('TableFormatLevel', 1000000) -end) - describe('Expressions parser', function() local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs, nz_flags_exps) |