diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 498f34e1f0..b6dd928b12 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -1055,23 +1055,23 @@ install.exe: dosinst.c dosinst.h version.h uninstall.exe: uninstall.c dosinst.h version.h $(CC) $(CFLAGS) -o uninstall.exe uninstall.c $(LIB) -lole32 -$(OBJ): $(OUTDIR) +$(OBJ): | $(OUTDIR) -$(EXEOBJG): $(OUTDIR) +$(EXEOBJG): | $(OUTDIR) -$(EXEOBJC): $(OUTDIR) +$(EXEOBJC): | $(OUTDIR) ifeq ($(VIMDLL),yes) -$(TARGET): $(OUTDIR) $(OBJ) +$(TARGET): $(OBJ) $(LINK) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid -lgdi32 $(LUA_LIB) $(MZSCHEME_LIBDIR) $(MZSCHEME_LIB) $(PYTHONLIB) $(PYTHON3LIB) $(RUBYLIB) -$(GVIMEXE): $(OUTDIR) $(EXEOBJG) $(VIMDLLBASE).dll +$(GVIMEXE): $(EXEOBJG) $(VIMDLLBASE).dll $(CC) -L. $(EXELFLAGS) -mwindows -o $@ $(EXEOBJG) -l$(VIMDLLBASE) -$(VIMEXE): $(OUTDIR) $(EXEOBJC) $(VIMDLLBASE).dll +$(VIMEXE): $(EXEOBJC) $(VIMDLLBASE).dll $(CC) -L. $(EXELFLAGS) -o $@ $(EXEOBJC) -l$(VIMDLLBASE) else -$(TARGET): $(OUTDIR) $(OBJ) +$(TARGET): $(OBJ) $(LINK) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid $(LUA_LIB) $(MZSCHEME_LIBDIR) $(MZSCHEME_LIB) $(PYTHONLIB) $(PYTHON3LIB) $(RUBYLIB) endif @@ -1286,7 +1286,7 @@ $(OUTDIR)/%.o : xdiff/%.c $(XDIFF_DEPS) $(CC) -c $(CFLAGS) $< -o $@ -$(PATHDEF_SRC): $(OUTDIR) Make_cyg_ming.mak Make_cyg.mak Make_ming.mak +$(PATHDEF_SRC): Make_cyg_ming.mak Make_cyg.mak Make_ming.mak | $(OUTDIR) ifneq (sh.exe, $(SHELL)) @echo creating $(PATHDEF_SRC) @echo '/* pathdef.c */' > $(PATHDEF_SRC) diff --git a/src/evalfunc.c b/src/evalfunc.c index 7f4ef9ba7e..5e6658ef0f 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -295,7 +295,7 @@ arg_float_or_nr(type_T *type, argcontext_T *context) static int arg_number(type_T *type, argcontext_T *context) { - return check_type(&t_number, type, TRUE, context->arg_idx + 1); + return check_arg_type(&t_number, type, context->arg_idx + 1); } /* @@ -304,7 +304,7 @@ arg_number(type_T *type, argcontext_T *context) static int arg_string(type_T *type, argcontext_T *context) { - return check_type(&t_string, type, TRUE, context->arg_idx + 1); + return check_arg_type(&t_string, type, context->arg_idx + 1); } /* @@ -342,7 +342,7 @@ arg_same_as_prev(type_T *type, argcontext_T *context) { type_T *prev_type = context->arg_types[context->arg_idx - 1]; - return check_type(prev_type, type, TRUE, context->arg_idx + 1); + return check_arg_type(prev_type, type, context->arg_idx + 1); } /* @@ -363,7 +363,7 @@ arg_item_of_prev(type_T *type, argcontext_T *context) // probably VAR_ANY, can't check return OK; - return check_type(expected, type, TRUE, context->arg_idx + 1); + return check_arg_type(expected, type, context->arg_idx + 1); } /* diff --git a/src/popupmenu.c b/src/popupmenu.c index 8033d72111..f4f210b5d7 100644 --- a/src/popupmenu.c +++ b/src/popupmenu.c @@ -361,6 +361,8 @@ pum_display( // redo the positioning. Limit this to two times, when there is not // much room the window size will keep changing. } while (pum_set_selected(selected, redo_count) && ++redo_count <= 2); + + pum_redraw(); } /* @@ -541,8 +543,23 @@ pum_redraw(void) { if (st != NULL) { - screen_puts_len(st, (int)STRLEN(st), row, col, - attr); + int size = (int)STRLEN(st); + int cells = (*mb_string2cells)(st, size); + + // only draw the text that fits + while (size > 0 + && col + cells > pum_width + pum_col) + { + --size; + if (has_mbyte) + { + size -= (*mb_head_off)(st, st + size); + cells -= (*mb_ptr2cells)(st + size); + } + else + --cells; + } + screen_puts_len(st, size, row, col, attr); vim_free(st); } col += width; @@ -990,9 +1007,6 @@ pum_set_selected(int n, int repeat UNUSED) popup_hide_info(); #endif - if (!resized) - pum_redraw(); - return resized; } diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 49213c839e..fbee55c954 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -1,6 +1,7 @@ /* vim9compile.c */ int check_defined(char_u *p, size_t len, cctx_T *cctx); int check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2); +int use_typecheck(type_T *actual, type_T *expected); int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx); imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx); imported_T *find_imported_in_script(char_u *name, size_t len, int sid); diff --git a/src/proto/vim9type.pro b/src/proto/vim9type.pro index e80f303a4d..90f2345b8e 100644 --- a/src/proto/vim9type.pro +++ b/src/proto/vim9type.pro @@ -15,6 +15,7 @@ int check_typval_type(type_T *expected, typval_T *actual_tv, int argidx); void type_mismatch(type_T *expected, type_T *actual); void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); int check_type(type_T *expected, type_T *actual, int give_msg, int argidx); +int check_arg_type(type_T *expected, type_T *actual, int argidx); char_u *skip_type(char_u *start, int optional); type_T *parse_type(char_u **arg, garray_T *type_gap); void common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap); diff --git a/src/testdir/test_netbeans.vim b/src/testdir/test_netbeans.vim index 490e528c43..d56b4683fb 100644 --- a/src/testdir/test_netbeans.vim +++ b/src/testdir/test_netbeans.vim @@ -36,7 +36,7 @@ func ReadXnetbeans() let l = readfile("Xnetbeans") " Xnetbeans may include '0:geometry=' messages in the GUI Vim if the window " position, size, or z order are changed. Remove these messages because - " these message will break the assert for the output. + " these messages will break the assert for the output. return filter(l, 'v:val !~ "^0:geometry="') endfunc @@ -927,7 +927,7 @@ endfunc " error. func Test_nb_bwipe_buffer() call s:run_server('Nb_bwipe_buffer') - %bwipe! + silent! %bwipe! sleep 100m nbclose endfunc diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 3b18aadfa4..f732ec4d90 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -1242,20 +1242,36 @@ func Test_terminal_popup_with_cmd() unlet s:winid endfunc +func Test_terminal_popup_bufload() + let termbuf = term_start(&shell, #{hidden: v:true, term_finish: 'close'}) + let winid = popup_create(termbuf, {}) + sleep 50m + + let newbuf = bufadd('') + call bufload(newbuf) + call setbufline(newbuf, 1, 'foobar') + + " must not have switched to another window + call assert_equal(winid, win_getid()) + + call StopShellInTerminal(termbuf) + call WaitFor({-> win_getid() != winid}) + exe 'bwipe! ' .. newbuf +endfunc + func Test_terminal_popup_insert_cmd() CheckUnix inoremap call StartTermInPopup() func StartTermInPopup() - call term_start(['/bin/sh', '-c', 'cat'], #{hidden: v:true})->popup_create(#{highlight: 'Pmenu'}) + call term_start(['/bin/sh', '-c', 'cat'], #{hidden: v:true, term_finish: 'close'})->popup_create(#{highlight: 'Pmenu'}) endfunc call feedkeys("i\") sleep 10m call assert_equal('n', mode()) call feedkeys("\", 'xt') - sleep 20m - call feedkeys(":q\", 'xt') + sleep 50m delfunc StartTermInPopup iunmap endfunc diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 24f62d85d2..0acf6c3ab7 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -408,6 +408,15 @@ def Test_assignment_dict() # overwrite dict3['key'] = 'another' + assert_equal(dict3, #{key: 'another'}) + dict3.key = 'yet another' + assert_equal(dict3, #{key: 'yet another'}) + + var lines =<< trim END + var dd = #{one: 1} + dd.one) = 2 + END + CheckDefFailure(lines, 'E15:', 2) # empty key can be used var dd = {} @@ -418,7 +427,7 @@ def Test_assignment_dict() var somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'} # assignment to script-local dict - var lines =<< trim END + lines =<< trim END vim9script var test: dict = {} def FillDict(): dict diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index bbb7e85d0f..cf122673c3 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -195,10 +195,16 @@ def Test_extend_arg_types() assert_equal([1, 2, 3], extend([1, 2], [3])) assert_equal([3, 1, 2], extend([1, 2], [3], 0)) assert_equal([1, 3, 2], extend([1, 2], [3], 1)) + assert_equal([1, 3, 2], extend([1, 2], [3], s:number_one)) assert_equal(#{a: 1, b: 2, c: 3}, extend(#{a: 1, b: 2}, #{c: 3})) assert_equal(#{a: 1, b: 4}, extend(#{a: 1, b: 2}, #{b: 4})) assert_equal(#{a: 1, b: 2}, extend(#{a: 1, b: 2}, #{b: 4}, 'keep')) + assert_equal(#{a: 1, b: 2}, extend(#{a: 1, b: 2}, #{b: 4}, s:string_keep)) + + var res: list> + extend(res, map([1, 2], {_, v -> {}})) + assert_equal([{}, {}], res) CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list but got number') CheckDefFailure(['extend([1, 2], ["x"])'], 'E1013: Argument 2: type mismatch, expected list but got list') @@ -338,6 +344,10 @@ def Test_index() index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3) enddef +let s:number_one = 1 +let s:number_two = 2 +let s:string_keep = 'keep' + def Test_insert() var l = insert([2, 1], 3) var res = 0 @@ -347,9 +357,12 @@ def Test_insert() res->assert_equal(6) assert_equal([1, 2, 3], insert([2, 3], 1)) + assert_equal([1, 2, 3], insert([2, 3], s:number_one)) assert_equal([1, 2, 3], insert([1, 2], 3, 2)) + assert_equal([1, 2, 3], insert([1, 2], 3, s:number_two)) assert_equal(['a', 'b', 'c'], insert(['b', 'c'], 'a')) assert_equal(0z1234, insert(0z34, 0x12)) + CheckDefFailure(['insert([2, 3], "a")'], 'E1013: Argument 2: type mismatch, expected number but got string', 1) CheckDefFailure(['insert([2, 3], 1, "x")'], 'E1013: Argument 3: type mismatch, expected number but got string', 1) enddef diff --git a/src/version.c b/src/version.c index c97db74de0..f6b2ea8142 100644 --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,22 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2000, +/**/ + 1999, +/**/ + 1998, +/**/ + 1997, +/**/ + 1996, +/**/ + 1995, +/**/ + 1994, +/**/ + 1993, /**/ 1992, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 9a38f056a4..6b2b766bea 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -820,7 +820,7 @@ generate_TYPECHECK( * Return TRUE if "actual" could be "expected" and a runtime typecheck is to be * used. Return FALSE if the types will never match. */ - static int + int use_typecheck(type_T *actual, type_T *expected) { if (actual->tt_type == VAR_ANY @@ -5384,14 +5384,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) member_type = type; if (var_end > var_start + varlen) { - // Something follows after the variable: "var[idx]". + // Something follows after the variable: "var[idx]" or "var.key". if (is_decl) { emsg(_(e_cannot_use_index_when_declaring_variable)); goto theend; } - if (var_start[varlen] == '[') + if (var_start[varlen] == '[' || var_start[varlen] == '.') { has_index = TRUE; if (type->tt_member == NULL) @@ -5635,21 +5635,33 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) { int r; - // Compile the "idx" in "var[idx]". + // Compile the "idx" in "var[idx]" or "key" in "var.key". if (new_local) --cctx->ctx_locals.ga_len; - p = skipwhite(var_start + varlen + 1); - r = compile_expr0(&p, cctx); + p = var_start + varlen; + if (*p == '[') + { + p = skipwhite(p + 1); + r = compile_expr0(&p, cctx); + if (r == OK && *skipwhite(p) != ']') + { + // this should not happen + emsg(_(e_missbrac)); + r = FAIL; + } + } + else // if (*p == '.') + { + char_u *key_end = to_name_end(p + 1, TRUE); + char_u *key = vim_strnsave(p + 1, key_end - p - 1); + + r = generate_PUSHS(cctx, key); + } if (new_local) ++cctx->ctx_locals.ga_len; if (r == FAIL) goto theend; - if (*skipwhite(p) != ']') - { - // this should not happen - emsg(_(e_missbrac)); - goto theend; - } + if (type == &t_any) { type_T *idx_type = ((type_T **)stack->ga_data)[ diff --git a/src/vim9type.c b/src/vim9type.c index 27daf83667..d655a63db5 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -516,6 +516,20 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx) return ret; } +/* + * Like check_type() but also allow for a runtime type check. E.g. "any" can be + * used for "number". + */ + int +check_arg_type(type_T *expected, type_T *actual, int argidx) +{ + if (check_type(expected, actual, FALSE, 0) == OK + || use_typecheck(actual, expected)) + return OK; + // TODO: should generate a TYPECHECK instruction. + return check_type(expected, actual, TRUE, argidx); +} + /* * Skip over a type definition and return a pointer to just after it. * When "optional" is TRUE then a leading "?" is accepted. diff --git a/src/window.c b/src/window.c index 26e6d7d672..fd651944f3 100644 --- a/src/window.c +++ b/src/window.c @@ -1467,6 +1467,7 @@ win_valid(win_T *win) /* * Find window "id" in the current tab page. + * Also find popup windows. * Return NULL if not found. */ win_T * @@ -1477,6 +1478,14 @@ win_find_by_id(int id) FOR_ALL_WINDOWS(wp) if (wp->w_id == id) return wp; +#ifdef FEAT_PROP_POPUP + FOR_ALL_POPUPWINS(wp) + if (wp->w_id == id) + return wp; + FOR_ALL_POPUPWINS_IN_TAB(curtab, wp) + if (wp->w_id == id) + return wp; +#endif return NULL; }