diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index 5db68d3cb4..48eaf3f60f 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -878,6 +878,23 @@ export def FTsig() endif enddef +# This function checks the first 100 lines of files matching "*.sil" to +# resolve detection between Swift Intermediate Language and SILE. +export def FTsil() + for lnum in range(1, [line('$'), 100]->min()) + var line: string = getline(lnum) + if line =~ '^\s*[\\%]' + setf sile + return + elseif line =~ '^\s*\S' + setf sil + return + endif + endfor + # no clue, default to "sil" + setf sil +enddef + export def FTsys() if exists("g:filetype_sys") exe "setf " .. g:filetype_sys diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 69557d6146..6beae6ee2c 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1724,11 +1724,11 @@ The valid escape sequences are ** ** *:command-modifiers* The command modifiers, if specified. Otherwise, expands to nothing. Supported modifiers are |:aboveleft|, |:belowright|, - |:botright|, |:browse|, |:confirm|, |:hide|, |:keepalt|, - |:keepjumps|, |:keepmarks|, |:keeppatterns|, |:leftabove|, - |:lockmarks|, |:noautocmd|, |:noswapfile| |:rightbelow|, - |:sandbox|, |:silent|, |:tab|, |:topleft|, |:unsilent|, - |:verbose|, and |:vertical|. + |:botright|, |:browse|, |:confirm|, |:hide|, |:horizontal|, + |:keepalt|, |:keepjumps|, |:keepmarks|, |:keeppatterns|, + |:leftabove|, |:lockmarks|, |:noautocmd|, |:noswapfile| + |:rightbelow|, |:sandbox|, |:silent|, |:tab|, |:topleft|, + |:unsilent|, |:verbose|, and |:vertical|. Note that |:filter| is not supported. Examples: > command! -nargs=+ -complete=file MyEdit diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt index 7acfba78c6..906e44404d 100644 --- a/runtime/doc/term.txt +++ b/runtime/doc/term.txt @@ -643,6 +643,18 @@ Example for an xterm, this changes the color of the cursor: > endif NOTE: When Vim exits the shape for Normal mode will remain. The shape from before Vim started will not be restored. + +For Windows Terminal you can use something like this: > + " Note: This should be set after `set termguicolors` or `set t_Co=256`. + if &term =~ 'xterm' || &term == 'win32' + " Use DECSCUSR escape sequences + let &t_SI = "\e[5 q" " blink bar + let &t_SR = "\e[3 q" " blink underline + let &t_EI = "\e[1 q" " blink block + let &t_ti ..= "\e[1 q" " blink block + let &t_te ..= "\e[0 q" " default (depends on terminal, normally blink block) + endif + {not available when compiled without the |+cursorshape| feature} *termcap-title* diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index b77b789a2c..aba0f0051e 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -1618,7 +1618,7 @@ type, it can not be used in Vim9 script. *E1211* *E1217* *E1218* *E1219* *E1220* *E1221* *E1222* *E1223* *E1224* *E1225* *E1226* *E1227* *E1228* *E1238* *E1250* *E1251* *E1252* *E1253* - *E1256* *E1297* + *E1256* *E1297* *E1298* Types are checked for most builtin functions to make it easier to spot mistakes. diff --git a/runtime/filetype.vim b/runtime/filetype.vim index c2b89a5f80..c7670d08ca 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1822,7 +1822,7 @@ au BufNewFile,BufRead *.score setf slrnsc au BufNewFile,BufRead *.st setf st " Smalltalk (and Rexx, TeX, and Visual Basic) -au BufNewFile,BufRead *.cls call dist#ft#FTcls() +au BufNewFile,BufRead *.cls call dist#ft#FTcls() " Smarty templates au BufNewFile,BufRead *.tpl setf smarty @@ -1929,8 +1929,8 @@ au BufNewFile,BufRead *.cm setf voscm au BufNewFile,BufRead *.swift setf swift au BufNewFile,BufRead *.swift.gyb setf swiftgyb -" Swift Intermediate Language -au BufNewFile,BufRead *.sil setf sil +" Swift Intermediate Language or SILE +au BufNewFile,BufRead *.sil call dist#ft#FTsil() " Sysctl au BufNewFile,BufRead */etc/sysctl.conf,*/etc/sysctl.d/*.conf setf sysctl diff --git a/src/channel.c b/src/channel.c index f185023765..d154ff2a84 100644 --- a/src/channel.c +++ b/src/channel.c @@ -2757,12 +2757,8 @@ channel_exe_cmd(channel_T *channel, ch_part_T part, typval_T *argv) } else if (STRCMP(cmd, "redraw") == 0) { - exarg_T ea; - ch_log(channel, "redraw"); - CLEAR_FIELD(ea); - ea.forceit = *arg != NUL; - ex_redraw(&ea); + redraw_cmd(*arg != NUL); showruler(FALSE); setcursor(); out_flush_cursor(TRUE, FALSE); diff --git a/src/cmdexpand.c b/src/cmdexpand.c index e160b60907..42f9c32658 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -1776,6 +1776,7 @@ set_context_by_cmdname( case CMD_folddoclosed: case CMD_folddoopen: case CMD_hide: + case CMD_horizontal: case CMD_keepalt: case CMD_keepjumps: case CMD_keepmarks: diff --git a/src/errors.h b/src/errors.h index befc8eeb36..7846a0728a 100644 --- a/src/errors.h +++ b/src/errors.h @@ -3323,5 +3323,9 @@ EXTERN char e_cannot_specify_both_type_and_types[] EXTERN char e_can_only_use_left_padding_when_column_is_zero[] INIT(= N_("E1296: Can only use left padding when column is zero")); #endif +#ifdef FEAT_EVAL EXTERN char e_non_null_dict_required_for_argument_nr[] INIT(= N_("E1297: Non-NULL Dictionary required for argument %d")); +EXTERN char e_non_null_list_required_for_argument_nr[] + INIT(= N_("E1298: Non-NULL List required for argument %d")); +#endif diff --git a/src/eval.c b/src/eval.c index 2e8d938ec6..f55d9de8ec 100644 --- a/src/eval.c +++ b/src/eval.c @@ -6729,7 +6729,8 @@ ex_execute(exarg_T *eap) ga_init2(&ga, 1, 80); #ifdef HAS_MESSAGE_WINDOW - in_echowindow = (eap->cmdidx == CMD_echowindow); + if (eap->cmdidx == CMD_echowindow) + start_echowindow(); #endif if (eap->skip) @@ -6833,17 +6834,7 @@ ex_execute(exarg_T *eap) --emsg_skip; #ifdef HAS_MESSAGE_WINDOW if (eap->cmdidx == CMD_echowindow) - { - // show the message window now - ex_redraw(eap); - - // do not overwrite messages - // TODO: only for message window - msg_didout = TRUE; - if (msg_col == 0) - msg_col = 1; - in_echowindow = FALSE; - } + end_echowindow(); #endif set_nextcmd(eap, arg); } diff --git a/src/evalfunc.c b/src/evalfunc.c index 01872f8d4c..14cb770efe 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3235,11 +3235,8 @@ f_call(typval_T *argvars, typval_T *rettv) || check_for_opt_dict_arg(argvars, 2) == FAIL)) return; - if (argvars[1].v_type != VAR_LIST) - { - emsg(_(e_list_required)); + if (check_for_list_arg(argvars, 1) == FAIL) return; - } if (argvars[1].vval.v_list == NULL) return; diff --git a/src/ex_docmd.c b/src/ex_docmd.c index a514098c6a..7f7ea4bcbc 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2461,6 +2461,7 @@ do_one_cmd( case CMD_final: case CMD_help: case CMD_hide: + case CMD_horizontal: case CMD_ijump: case CMD_ilist: case CMD_isearch: @@ -8356,10 +8357,19 @@ ex_redir(exarg_T *eap) } /* - * ":redraw": force redraw + * ":redraw": force redraw, with clear for ":redraw!". */ void ex_redraw(exarg_T *eap) +{ + redraw_cmd(eap->forceit); +} + +/* + * ":redraw": force redraw, with clear if "clear" is TRUE. + */ + void +redraw_cmd(int clear) { int r = RedrawingDisabled; int p = p_lz; @@ -8368,7 +8378,7 @@ ex_redraw(exarg_T *eap) p_lz = FALSE; validate_cursor(); update_topline(); - update_screen(eap->forceit ? UPD_CLEAR : VIsual_active ? UPD_INVERTED : 0); + update_screen(clear ? UPD_CLEAR : VIsual_active ? UPD_INVERTED : 0); if (need_maketitle) maketitle(); #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) diff --git a/src/filepath.c b/src/filepath.c index d840d88c95..a316a96abe 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -1603,19 +1603,20 @@ readdir_checkitem(void *context, void *item) return checkitem_common(context, name, NULL); } +/* + * Process the keys in the Dict argument to the readdir() and readdirex() + * functions. Assumes the Dict argument is the 3rd argument. + */ static int -readdirex_dict_arg(typval_T *tv, int *cmp) +readdirex_dict_arg(typval_T *argvars, int *cmp) { char_u *compare; - if (tv->v_type != VAR_DICT) - { - emsg(_(e_dictionary_required)); + if (check_for_nonnull_dict_arg(argvars, 2) == FAIL) return FAIL; - } - if (dict_has_key(tv->vval.v_dict, "sort")) - compare = dict_get_string(tv->vval.v_dict, "sort", FALSE); + if (dict_has_key(argvars[2].vval.v_dict, "sort")) + compare = dict_get_string(argvars[2].vval.v_dict, "sort", FALSE); else { semsg(_(e_dictionary_key_str_required), "sort"); @@ -1660,7 +1661,7 @@ f_readdir(typval_T *argvars, typval_T *rettv) expr = &argvars[1]; if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN && - readdirex_dict_arg(&argvars[2], &sort) == FAIL) + readdirex_dict_arg(argvars, &sort) == FAIL) return; ret = readdir_core(&ga, path, FALSE, (void *)expr, @@ -1713,7 +1714,7 @@ f_readdirex(typval_T *argvars, typval_T *rettv) expr = &argvars[1]; if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN && - readdirex_dict_arg(&argvars[2], &sort) == FAIL) + readdirex_dict_arg(argvars, &sort) == FAIL) return; ret = readdir_core(&ga, path, TRUE, (void *)expr, diff --git a/src/insexpand.c b/src/insexpand.c index 0953342171..08cbf5c068 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -2934,9 +2934,7 @@ f_complete(typval_T *argvars, typval_T *rettv UNUSED) if (!undo_allowed()) return; - if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL) - emsg(_(e_invalid_argument)); - else + if (check_for_nonnull_list_arg(argvars, 1) != FAIL) { startcol = (int)tv_get_number_chk(&argvars[0], NULL); if (startcol > 0) @@ -3147,11 +3145,8 @@ f_complete_info(typval_T *argvars, typval_T *rettv) if (argvars[0].v_type != VAR_UNKNOWN) { - if (argvars[0].v_type != VAR_LIST) - { - emsg(_(e_list_required)); + if (check_for_list_arg(argvars, 0) == FAIL) return; - } what_list = argvars[0].vval.v_list; } get_complete_info(what_list, rettv->vval.v_dict); diff --git a/src/list.c b/src/list.c index 5e70f2111b..c9697e0514 100644 --- a/src/list.c +++ b/src/list.c @@ -1519,11 +1519,8 @@ f_join(typval_T *argvars, typval_T *rettv) || check_for_opt_string_arg(argvars, 1) == FAIL)) return; - if (argvars[0].v_type != VAR_LIST) - { - emsg(_(e_list_required)); + if (check_for_list_arg(argvars, 0) == FAIL) return; - } if (argvars[0].vval.v_list == NULL) return; @@ -1728,11 +1725,8 @@ f_list2str(typval_T *argvars, typval_T *rettv) || check_for_opt_bool_arg(argvars, 1) == FAIL)) return; - if (argvars[0].v_type != VAR_LIST) - { - emsg(_(e_invalid_argument)); + if (check_for_list_arg(argvars, 0) == FAIL) return; - } l = argvars[0].vval.v_list; if (l == NULL) diff --git a/src/match.c b/src/match.c index 335b06011f..ebdaeabcff 100644 --- a/src/match.c +++ b/src/match.c @@ -1087,11 +1087,8 @@ f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED) || check_for_opt_number_arg(argvars, 1) == FAIL)) return; - if (argvars[0].v_type != VAR_LIST) - { - emsg(_(e_list_required)); + if (check_for_list_arg(argvars, 0) == FAIL) return; - } win = get_optional_window(argvars, 1); if (win == NULL) return; diff --git a/src/mbyte.c b/src/mbyte.c index 73065c7394..54f7fa4fbb 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -5535,14 +5535,9 @@ f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED) size_t cw_table_size_save; char *error = NULL; - if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL) + if (check_for_nonnull_list_arg(argvars, 0) == FAIL) return; - if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL) - { - emsg(_(e_list_required)); - return; - } l = argvars[0].vval.v_list; if (l->lv_len == 0) { diff --git a/src/message.c b/src/message.c index 3a8d857ba7..eceaca5099 100644 --- a/src/message.c +++ b/src/message.c @@ -1448,7 +1448,7 @@ msg_start(void) } #ifdef FEAT_EVAL - if (need_clr_eos || in_echowindow) + if (need_clr_eos) { // Halfway an ":echo" command and getting an (error) message: clear // any text from the command. @@ -3651,6 +3651,10 @@ msg_clr_eos(void) void msg_clr_eos_force(void) { +#ifdef HAS_MESSAGE_WINDOW + if (in_echowindow) + return; // messages go into a popup +#endif if (msg_use_printf()) { if (full_screen) // only when termcap codes are valid diff --git a/src/os_win32.c b/src/os_win32.c index f06227f10a..f6bf91d9fa 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -213,6 +213,7 @@ static int g_color_index_bg = 0; static int g_color_index_fg = 7; # ifdef FEAT_TERMGUICOLORS +static int default_console_color_bg = 0x000000; // black static int default_console_color_fg = 0xc0c0c0; // white # endif @@ -1527,13 +1528,27 @@ decode_mouse_event( static void mch_set_cursor_shape(int thickness) { - CONSOLE_CURSOR_INFO ConsoleCursorInfo; - ConsoleCursorInfo.dwSize = thickness; - ConsoleCursorInfo.bVisible = s_cursor_visible; + if (USE_VTP || USE_WT) + { + if (*T_CSI == NUL) + { + // If 't_SI' is not set, use the default cursor styles. + if (thickness < 50) + vtp_printf("\033[3 q"); // underline + else + vtp_printf("\033[0 q"); // default + } + } + else + { + CONSOLE_CURSOR_INFO ConsoleCursorInfo; + ConsoleCursorInfo.dwSize = thickness; + ConsoleCursorInfo.bVisible = s_cursor_visible; - SetConsoleCursorInfo(g_hConOut, &ConsoleCursorInfo); - if (s_cursor_visible) - SetConsoleCursorPosition(g_hConOut, g_coord); + SetConsoleCursorInfo(g_hConOut, &ConsoleCursorInfo); + if (s_cursor_visible) + SetConsoleCursorPosition(g_hConOut, g_coord); + } } void @@ -6769,6 +6784,21 @@ notsgr: } # endif } + else if (s[0] == ESC && len >= 3-1 && s[1] == '[') + { + int l = 2; + + if (isdigit(s[l])) + l++; + if (s[l] == ' ' && s[l + 1] == 'q') + { + // DECSCUSR (cursor style) sequences + if (USE_VTP || USE_WT) + vtp_printf("%.*s", l + 2, s); // Pass through + s += l + 2; + len -= l + 1; + } + } else { // Write a single character @@ -7878,6 +7908,13 @@ vtp_init(void) store_console_fg_rgb = save_console_fg_rgb; # ifdef FEAT_TERMGUICOLORS + if (!USE_WT) + { + COLORREF bg; + bg = (COLORREF)csbi.ColorTable[g_color_index_bg]; + bg = (GetRValue(bg) << 16) | (GetGValue(bg) << 8) | GetBValue(bg); + default_console_color_bg = bg; + } fg = (COLORREF)csbi.ColorTable[g_color_index_fg]; fg = (GetRValue(fg) << 16) | (GetGValue(fg) << 8) | GetBValue(fg); default_console_color_fg = fg; @@ -7945,7 +7982,7 @@ vtp_sgr_bulks( if (argc == 0) { sgrfgr = sgrbgr = -1; - vtp_printf("033[m"); + vtp_printf("\033[m"); return; } @@ -8160,11 +8197,20 @@ get_default_console_color( ctermbg = -1; if (id > 0) syn_id2cterm_bg(id, &ctermfg, &ctermbg); - cterm_normal_bg_gui_color = guibg = + if (!USE_WT) + { + guibg = ctermbg != -1 ? ctermtoxterm(ctermbg) + : default_console_color_bg; + cterm_normal_bg_gui_color = guibg; + ctermbg = ctermbg < 0 ? 0 : ctermbg; + } + else + { + cterm_normal_bg_gui_color = guibg = ctermbg != -1 ? ctermtoxterm(ctermbg) : INVALCOLOR; - - if (ctermbg < 0) - ctermbg = 0; + if (ctermbg < 0) + ctermbg = 0; + } } *cterm_fg = ctermfg; diff --git a/src/popupwin.c b/src/popupwin.c index 8292dba32e..8688f3e3d1 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1356,6 +1356,8 @@ popup_adjust_position(win_T *wp) if (wp->w_maxheight > 0) maxheight = wp->w_maxheight; + else if (wp->w_popup_pos == POPPOS_BOTTOM) + maxheight = cmdline_row - 1; // start at the desired first line if (wp->w_firstline > 0) @@ -4479,6 +4481,7 @@ popup_get_message_win(void) message_win->w_popup_pos = POPPOS_BOTTOM; message_win->w_wantcol = 1; message_win->w_minwidth = 9999; + message_win->w_firstline = -1; // no padding, border at the top for (i = 0; i < 4; ++i) @@ -4529,6 +4532,31 @@ popup_hide_message_win(void) popup_hide(message_win); } +/* + * Invoked before outputting a message for ":echowindow". + */ + void +start_echowindow(void) +{ + in_echowindow = TRUE; +} + +/* + * Invoked after outputting a message for ":echowindow". + */ + void +end_echowindow(void) +{ + // show the message window now + redraw_cmd(FALSE); + + // do not overwrite messages + // TODO: only for message window + msg_didout = TRUE; + if (msg_col == 0) + msg_col = 1; + in_echowindow = FALSE; +} #endif /* diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro index 509dc11c5d..894b6dae38 100644 --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -56,6 +56,7 @@ void ex_cd(exarg_T *eap); void do_sleep(long msec, int hide_cursor); void ex_may_print(exarg_T *eap); void ex_redraw(exarg_T *eap); +void redraw_cmd(int clear); int vim_mkdir_emsg(char_u *name, int prot); FILE *open_exfile(char_u *fname, int forceit, char *mode); void update_topline_cursor(void); diff --git a/src/proto/popupwin.pro b/src/proto/popupwin.pro index dcc14de091..12be54f1f8 100644 --- a/src/proto/popupwin.pro +++ b/src/proto/popupwin.pro @@ -67,6 +67,8 @@ win_T *popup_get_message_win(void); void popup_show_message_win(void); int popup_message_win_visible(void); void popup_hide_message_win(void); +void start_echowindow(void); +void end_echowindow(void); int popup_win_closed(win_T *win); void popup_set_title(win_T *wp); void popup_update_preview_title(void); diff --git a/src/proto/typval.pro b/src/proto/typval.pro index 154b668b1e..7d32a03d94 100644 --- a/src/proto/typval.pro +++ b/src/proto/typval.pro @@ -20,6 +20,7 @@ int check_for_bool_arg(typval_T *args, int idx); int check_for_opt_bool_arg(typval_T *args, int idx); int check_for_blob_arg(typval_T *args, int idx); int check_for_list_arg(typval_T *args, int idx); +int check_for_nonnull_list_arg(typval_T *args, int idx); int check_for_opt_list_arg(typval_T *args, int idx); int check_for_dict_arg(typval_T *args, int idx); int check_for_nonnull_dict_arg(typval_T *args, int idx); diff --git a/src/sign.c b/src/sign.c index e0264ccb1b..eaefd5f063 100644 --- a/src/sign.c +++ b/src/sign.c @@ -2660,11 +2660,8 @@ f_sign_placelist(typval_T *argvars, typval_T *rettv) if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL) return; - if (argvars[0].v_type != VAR_LIST) - { - emsg(_(e_list_required)); + if (check_for_list_arg(argvars, 0) == FAIL) return; - } // Process the List of sign attributes FOR_ALL_LIST_ITEMS(argvars[0].vval.v_list, li) @@ -2888,11 +2885,8 @@ f_sign_unplacelist(typval_T *argvars, typval_T *rettv) if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL) return; - if (argvars[0].v_type != VAR_LIST) - { - emsg(_(e_list_required)); + if (check_for_list_arg(argvars, 0) == FAIL) return; - } FOR_ALL_LIST_ITEMS(argvars[0].vval.v_list, li) { diff --git a/src/terminal.c b/src/terminal.c index cc38a1abd5..b4f5e69a26 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -6467,11 +6467,9 @@ f_term_setansicolors(typval_T *argvars, typval_T *rettv UNUSED) if (term->tl_vterm == NULL) return; - if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL) - { - emsg(_(e_list_required)); + if (check_for_nonnull_list_arg(argvars, 1) == FAIL) return; - } + if (argvars[1].vval.v_list->lv_first == &range_list_item || argvars[1].vval.v_list->lv_len != 16) { diff --git a/src/testdir/dumps/Test_echowindow_2.dump b/src/testdir/dumps/Test_echowindow_2.dump index f8bea0c4ad..58b2f3fbf1 100644 --- a/src/testdir/dumps/Test_echowindow_2.dump +++ b/src/testdir/dumps/Test_echowindow_2.dump @@ -5,4 +5,4 @@ |═+0#e000002&@74 |f|i|r|s|t| |l|i|n|e| @64 |s|e|c|o|n|d| |l|i|n|e| @63 -| +0#0000000&@56|1|,|1| @10|A|l@1| +|:+0#0000000&|c|a|l@1| |S|h|o|w|M|e|s@1|a|g|e|(|'|s|e|c|o|n|d| |l|i|n|e|'|)| @24|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_echowindow_4.dump b/src/testdir/dumps/Test_echowindow_4.dump new file mode 100644 index 0000000000..c8bd387c72 --- /dev/null +++ b/src/testdir/dumps/Test_echowindow_4.dump @@ -0,0 +1,8 @@ +>═+0#e000002#ffffff0@74 +|l|i|n|e| |1|4| @67 +|l|i|n|e| |1|5| @67 +|l|i|n|e| |1|6| @67 +|l|i|n|e| |1|7| @67 +|l|i|n|e| |1|8| @67 +|l|i|n|e| |1|9| @67 +|:+0#0000000&|c|a|l@1| |M|a|n|y|M|e|s@1|a|g|e|s|(|)| @36|1|,|1| @10|A|l@1| diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim index bb42678acc..0f0ffe878a 100644 --- a/src/testdir/shared.vim +++ b/src/testdir/shared.vim @@ -62,8 +62,8 @@ endfunc " Read the port number from the Xportnr file. func GetPort() let l = [] - " with 200 it sometimes failed - for i in range(400) + " with 200 it sometimes failed, with 400 is rarily failed + for i in range(600) try let l = readfile("Xportnr") catch diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 95db663bdf..bec0f5fdf8 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -1078,6 +1078,10 @@ func Test_cmdline_complete_various() call feedkeys(":all abc\\\"\", 'xt') call assert_equal("\"all abc\", @:) + " completion for :wincmd with :horizontal modifier + call feedkeys(":horizontal wincm\\\"\", 'xt') + call assert_equal("\"horizontal wincmd", @:) + " completion for a command with a command modifier call feedkeys(":topleft new\\\"\", 'xt') call assert_equal("\"topleft new", @:) diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 18233e7ab1..fbb8d2d2dd 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -1827,6 +1827,44 @@ func Test_sig_file() filetype off endfunc +" Test dist#ft#FTsil() +func Test_sil_file() + filetype on + + split Xfile.sil + call assert_equal('sil', &filetype) + bwipe! + + let lines =<< trim END + // valid + let protoErasedPathA = \ABCProtocol.a + + // also valid + let protoErasedPathA = + \ABCProtocol.a + END + call writefile(lines, 'Xfile.sil') + + split Xfile.sil + call assert_equal('sil', &filetype) + bwipe! + + " SILE + + call writefile(['% some comment'], 'Xfile.sil') + split Xfile.sil + call assert_equal('sile', &filetype) + bwipe! + + call writefile(['\begin[papersize=a6]{document}foo\end{document}'], 'Xfile.sil') + split Xfile.sil + call assert_equal('sile', &filetype) + bwipe! + + call delete('Xfile.sil') + filetype off +endfunc + func Test_inc_file() filetype on diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 971be40dc4..43eb265d62 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -2244,9 +2244,12 @@ func Test_readdir_sort() exe "lang collate" collate " 5) Errors - call assert_fails('call readdir(dir, 1, 1)', 'E715:') + call assert_fails('call readdir(dir, 1, 1)', 'E1206:') call assert_fails('call readdir(dir, 1, #{sorta: 1})') + call assert_fails('call readdir(dir, 1, test_null_dict())', 'E1297:') + call assert_fails('call readdirex(dir, 1, 1)', 'E1206:') call assert_fails('call readdirex(dir, 1, #{sorta: 1})') + call assert_fails('call readdirex(dir, 1, test_null_dict())', 'E1297:') " 6) ignore other values in dict let files = readdir(dir, '1', #{sort: 'c'}) @@ -2285,7 +2288,7 @@ endfunc func Test_call() call assert_equal(3, call('len', [123])) call assert_equal(3, 'len'->call([123])) - call assert_fails("call call('len', 123)", 'E714:') + call assert_fails("call call('len', 123)", 'E1211:') call assert_equal(0, call('', [])) call assert_equal(0, call('len', test_null_list())) @@ -2580,7 +2583,7 @@ func Test_range() " list2str() call assert_equal('ABC', list2str(range(65, 67))) - call assert_fails('let s = list2str(5)', 'E474:') + call assert_fails('let s = list2str(5)', 'E1211:') " lock() let thelist = range(5) diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim index e852f00b58..fe6a76b707 100644 --- a/src/testdir/test_gui.vim +++ b/src/testdir/test_gui.vim @@ -1217,13 +1217,20 @@ endfunc " Move the mouse to the top-left in preparation for mouse events func PrepareForMouseEvent(args) - call extend(a:args, #{row: 1, col:1}) + call extend(a:args, #{row: 1, col: 1}) call test_gui_event('mouse', a:args) + let g:eventlist = [] call feedkeys('', 'Lx!') - " on MS-Windows the event may have a slight delay - if has('win32') - sleep 20m - endif + + " Wait a bit for the event. I may not come if the mouse didn't move, wait up + " to 100 msec. + for n in range(10) + if len(g:eventlist) > 0 + break + endif + sleep 10m + endfor + let g:eventlist = [] endfunc func MouseWasMoved() @@ -1236,7 +1243,7 @@ func Test_gui_mouse_move_event() CheckNotMacVim let args = #{move: 1, button: 0, multiclick: 0, modifiers: 0} - " by default, does not generate mouse move events + " by default, no mouse move events are generated set mousemev& call assert_false(&mousemev) @@ -1245,7 +1252,6 @@ func Test_gui_mouse_move_event() " start at mouse pos (1,1), clear counter call PrepareForMouseEvent(args) - let g:eventlist = [] call extend(args, #{row: 3, col: 30, cell: v:true}) call test_gui_event('mouse', args) @@ -1255,13 +1261,12 @@ func Test_gui_mouse_move_event() call test_gui_event('mouse', args) call feedkeys('', 'Lx!') - " no events since mousemev off + " no events since 'mousemev' is off call assert_equal([], g:eventlist) " turn on mouse events and try the same thing set mousemev call PrepareForMouseEvent(args) - let g:eventlist = [] call extend(args, #{row: 3, col: 30, cell: v:true}) call test_gui_event('mouse', args) @@ -1281,7 +1286,6 @@ func Test_gui_mouse_move_event() " wiggle the mouse around within a screen cell, shouldn't trigger events call extend(args, #{cell: v:false}) call PrepareForMouseEvent(args) - let g:eventlist = [] call extend(args, #{row: 1, col: 2, cell: v:false}) call test_gui_event('mouse', args) diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 41998aa0eb..cee6a329f7 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -673,14 +673,14 @@ func Test_complete_func_error() func ListColors() call complete(col('.'), "blue") endfunc - call assert_fails('exe "normal i\=ListColors()\"', 'E474:') + call assert_fails('exe "normal i\=ListColors()\"', 'E1211:') func ListMonths() call complete(col('.'), test_null_list()) endfunc - call assert_fails('exe "normal i\=ListMonths()\"', 'E474:') + call assert_fails('exe "normal i\=ListMonths()\"', 'E1298:') delfunc ListColors delfunc ListMonths - call assert_fails('call complete_info({})', 'E714:') + call assert_fails('call complete_info({})', 'E1211:') call assert_equal([], complete_info(['items']).items) endfunc diff --git a/src/testdir/test_match.vim b/src/testdir/test_match.vim index 45f8389757..f654761d64 100644 --- a/src/testdir/test_match.vim +++ b/src/testdir/test_match.vim @@ -95,7 +95,7 @@ function Test_match() call assert_equal(0, setmatches([])) call assert_equal(0, setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}])) call clearmatches() - call assert_fails('call setmatches(0)', 'E714:') + call assert_fails('call setmatches(0)', 'E1211:') call assert_fails('call setmatches([0])', 'E474:') call assert_fails("call setmatches([{'wrong key': 'wrong value'}])", 'E474:') call assert_equal(-1, setmatches([{'group' : 'Search', 'priority' : 10, 'id' : 5, 'pos1' : {}}])) diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim index 6bdaedfd69..10af69c67d 100644 --- a/src/testdir/test_messages.vim +++ b/src/testdir/test_messages.vim @@ -396,6 +396,11 @@ func Test_echowindow() echowindow a:arg endfunc echowindow 'first line' + func ManyMessages() + for n in range(20) + echowindow 'line' n + endfor + endfunc END call writefile(lines, 'XtestEchowindow') let buf = RunVimInTerminal('-S XtestEchowindow', #{rows: 8}) @@ -407,6 +412,9 @@ func Test_echowindow() call term_sendkeys(buf, ":call popup_clear()\") call VerifyScreenDump(buf, 'Test_echowindow_3', {}) + call term_sendkeys(buf, ":call ManyMessages()\") + call VerifyScreenDump(buf, 'Test_echowindow_4', {}) + " clean up call StopVimInTerminal(buf) call delete('XtestEchowindow') diff --git a/src/testdir/test_method.vim b/src/testdir/test_method.vim index 22a930c5f2..d31cce1876 100644 --- a/src/testdir/test_method.vim +++ b/src/testdir/test_method.vim @@ -52,7 +52,7 @@ func Test_dict_method() call assert_fails("let x = d->insert(0)", 'E899:') call assert_true(d->has_key('two')) call assert_equal([['one', 1], ['two', 2], ['three', 3]], d->items()) - call assert_fails("let x = d->join()", 'E714:') + call assert_fails("let x = d->join()", 'E1211:') call assert_equal(['one', 'two', 'three'], d->keys()) call assert_equal(3, d->len()) call assert_equal(#{one: 2, two: 3, three: 4}, d->map('v:val + 1')) diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim index e23d9ac595..e2387b28c7 100644 --- a/src/testdir/test_signs.vim +++ b/src/testdir/test_signs.vim @@ -2010,7 +2010,7 @@ func Test_sign_funcs_multi() " Invalid arguments call assert_equal([], sign_placelist([])) - call assert_fails('call sign_placelist({})', "E714:") + call assert_fails('call sign_placelist({})', "E1211:") call assert_fails('call sign_placelist([[]])', "E715:") call assert_fails('call sign_placelist(["abc"])', "E715:") call assert_fails('call sign_placelist([100])', "E715:") @@ -2021,7 +2021,7 @@ func Test_sign_funcs_multi() " Invalid arguments call assert_equal([], []->sign_unplacelist()) - call assert_fails('call sign_unplacelist({})', "E714:") + call assert_fails('call sign_unplacelist({})', "E1211:") call assert_fails('call sign_unplacelist([[]])', "E715:") call assert_fails('call sign_unplacelist(["abc"])', "E715:") call assert_fails('call sign_unplacelist([100])', "E715:") diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 7d19aa57ee..08f7224b1f 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2070,7 +2070,7 @@ func Test_terminal_ansicolors_func() let colors[4] = 'Invalid' call assert_fails('call term_setansicolors(buf, colors)', 'E254:') - call assert_fails('call term_setansicolors(buf, {})', 'E714:') + call assert_fails('call term_setansicolors(buf, {})', 'E1211:') set tgc& call StopShellInTerminal(buf) diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index 34fa6c93fc..03ae9c97e0 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -381,7 +381,7 @@ func Test_prop_add_list() call assert_fails('call prop_add_list(#{type: "one"}, [[2, 2, 2, 2], [3, 20, 3, 22]])', 'E964:') call assert_fails('eval #{type: "one"}->prop_add_list([[2, 2, 2, 2], [3, 20, 3, 22]])', 'E964:') call assert_fails('call prop_add_list(test_null_dict(), [[2, 2, 2]])', 'E965:') - call assert_fails('call prop_add_list(#{type: "one"}, test_null_list())', 'E714:') + call assert_fails('call prop_add_list(#{type: "one"}, test_null_list())', 'E1298:') call assert_fails('call prop_add_list(#{type: "one"}, [test_null_list()])', 'E714:') call DeletePropTypes() bw! diff --git a/src/testdir/test_usercommands.vim b/src/testdir/test_usercommands.vim index 9c75a91972..91d8bfd062 100644 --- a/src/testdir/test_usercommands.vim +++ b/src/testdir/test_usercommands.vim @@ -103,6 +103,10 @@ function Test_cmdmods() call assert_equal('vertical', g:mods) vert MyCmd call assert_equal('vertical', g:mods) + horizontal MyCmd + call assert_equal('horizontal', g:mods) + hor MyCmd + call assert_equal('horizontal', g:mods) aboveleft belowright botright browse confirm hide keepalt keepjumps \ keepmarks keeppatterns lockmarks noautocmd noswapfile silent diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim index 862e73b9ab..bb99cb3e60 100644 --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -168,7 +168,7 @@ func Test_setcellwidths() call setcellwidths([]) - call assert_fails('call setcellwidths(1)', 'E714:') + call assert_fails('call setcellwidths(1)', 'E1211:') call assert_fails('call setcellwidths([1, 2, 0])', 'E1109:') diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index be40088d3b..12be156483 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -2274,6 +2274,8 @@ def s:Echomsg() echomsg 'some' 'message' echoconsole 'nothing' echoerr 'went' .. 'wrong' + var local = 'window' + echowin 'in' local enddef def Test_disassemble_echomsg() @@ -2289,7 +2291,14 @@ def Test_disassemble_echomsg() "echoerr 'went' .. 'wrong'\\_s*" .. '\d PUSHS "wentwrong"\_s*' .. '\d ECHOERR 1\_s*' .. - '\d RETURN void', + "var local = 'window'\\_s*" .. + '\d\+ PUSHS "window"\_s*' .. + '\d\+ STORE $0\_s*' .. + "echowin 'in' local\\_s*" .. + '\d\+ PUSHS "in"\_s*' .. + '\d\+ LOAD $0\_s*' .. + '\d\+ ECHOWINDOW 2\_s*' .. + '\d\+ RETURN void', res) enddef diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 5aec8ffc86..bdefc8756a 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2011,6 +2011,13 @@ def Test_echoconsole_cmd() # output goes anywhere enddef +def Test_echowindow_cmd() + var local = 'local' + echowindow 'something' local # comment + # output goes in message window + popup_clear() +enddef + def Test_for_outside_of_function() var lines =<< trim END vim9script diff --git a/src/textprop.c b/src/textprop.c index de3344f89c..5f5c6a2aa2 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -348,11 +348,8 @@ f_prop_add_list(typval_T *argvars, typval_T *rettv UNUSED) || check_for_list_arg(argvars, 1) == FAIL) return; - if (argvars[1].vval.v_list == NULL) - { - emsg(_(e_list_required)); + if (check_for_nonnull_list_arg(argvars, 1) == FAIL) return; - } dict = argvars[0].vval.v_dict; if (dict == NULL || !dict_has_key(dict, "type")) diff --git a/src/typval.c b/src/typval.c index 101f48f34a..12a741ec22 100644 --- a/src/typval.c +++ b/src/typval.c @@ -508,6 +508,23 @@ check_for_list_arg(typval_T *args, int idx) return OK; } +/* + * Give an error and return FAIL unless "args[idx]" is a non-NULL list. + */ + int +check_for_nonnull_list_arg(typval_T *args, int idx) +{ + if (check_for_list_arg(args, idx) == FAIL) + return FAIL; + + if (args[idx].vval.v_list == NULL) + { + semsg(_(e_non_null_list_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /* * Check for an optional list argument at 'idx' */ diff --git a/src/usercmd.c b/src/usercmd.c index 71135119e8..6b3eadc934 100644 --- a/src/usercmd.c +++ b/src/usercmd.c @@ -1443,6 +1443,9 @@ add_win_cmd_modifers(char_u *buf, cmdmod_T *cmod, int *multi_mods) // :vertical if (cmod->cmod_split & WSP_VERT) result += add_cmd_modifier(buf, "vertical", multi_mods); + // :horizontal + if (cmod->cmod_split & WSP_HOR) + result += add_cmd_modifier(buf, "horizontal", multi_mods); return result; } diff --git a/src/version.c b/src/version.c index c8d711f8b7..841ecba1ce 100644 --- a/src/version.c +++ b/src/version.c @@ -722,6 +722,28 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 354, +/**/ + 353, +/**/ + 352, +/**/ + 351, +/**/ + 350, +/**/ + 349, +/**/ + 348, +/**/ + 347, +/**/ + 346, +/**/ + 345, +/**/ + 344, /**/ 343, /**/ diff --git a/src/vim9.h b/src/vim9.h index 3ab1c5aa96..b32dbeab44 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -25,6 +25,7 @@ typedef enum { ISN_EXECUTE, // :execute with isn_arg.number items on top of stack ISN_ECHOMSG, // :echomsg with isn_arg.number items on top of stack ISN_ECHOCONSOLE, // :echoconsole with isn_arg.number items on top of stack + ISN_ECHOWINDOW, // :echowindow with isn_arg.number items on top of stack ISN_ECHOERR, // :echoerr with isn_arg.number items on top of stack ISN_RANGE, // compute range from isn_arg.string, push to stack ISN_SUBSTITUTE, // :s command with expression diff --git a/src/vim9cmds.c b/src/vim9cmds.c index 93032d6bf1..4ad87bc264 100644 --- a/src/vim9cmds.c +++ b/src/vim9cmds.c @@ -1735,6 +1735,10 @@ compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx) generate_MULT_EXPR(cctx, ISN_EXECUTE, count); else if (cmdidx == CMD_echomsg) generate_MULT_EXPR(cctx, ISN_ECHOMSG, count); +#ifdef HAS_MESSAGE_WINDOW + else if (cmdidx == CMD_echowindow) + generate_MULT_EXPR(cctx, ISN_ECHOWINDOW, count); +#endif else if (cmdidx == CMD_echoconsole) generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count); else diff --git a/src/vim9compile.c b/src/vim9compile.c index bf7390b6fa..20366752cf 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3251,10 +3251,13 @@ compile_def_function( case CMD_echo: case CMD_echon: - case CMD_execute: - case CMD_echomsg: - case CMD_echoerr: case CMD_echoconsole: + case CMD_echoerr: + case CMD_echomsg: +#ifdef HAS_MESSAGE_WINDOW + case CMD_echowindow: +#endif + case CMD_execute: line = compile_mult_expr(p, ea.cmdidx, &cctx); break; diff --git a/src/vim9execute.c b/src/vim9execute.c index 2f94f05c54..a1311ee177 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2858,10 +2858,12 @@ exec_instructions(ectx_T *ectx) // :execute {string} ... // :echomsg {string} ... + // :echowindow {string} ... // :echoconsole {string} ... // :echoerr {string} ... case ISN_EXECUTE: case ISN_ECHOMSG: + case ISN_ECHOWINDOW: case ISN_ECHOCONSOLE: case ISN_ECHOERR: { @@ -2932,6 +2934,14 @@ exec_instructions(ectx_T *ectx) msg_attr(ga.ga_data, echo_attr); out_flush(); } +#ifdef HAS_MESSAGE_WINDOW + else if (iptr->isn_type == ISN_ECHOWINDOW) + { + start_echowindow(); + msg_attr(ga.ga_data, echo_attr); + end_echowindow(); + } +#endif else if (iptr->isn_type == ISN_ECHOCONSOLE) { ui_write(ga.ga_data, (int)STRLEN(ga.ga_data), @@ -5570,6 +5580,10 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc) smsg("%s%4d ECHOMSG %lld", pfx, current, (varnumber_T)(iptr->isn_arg.number)); break; + case ISN_ECHOWINDOW: + smsg("%s%4d ECHOWINDOW %lld", pfx, current, + (varnumber_T)(iptr->isn_arg.number)); + break; case ISN_ECHOCONSOLE: smsg("%s%4d ECHOCONSOLE %lld", pfx, current, (varnumber_T)(iptr->isn_arg.number)); diff --git a/src/vim9instr.c b/src/vim9instr.c index f20d993728..a13516bbb2 100644 --- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -2245,6 +2245,7 @@ delete_instr(isn_T *isn) case ISN_ECHOCONSOLE: case ISN_ECHOERR: case ISN_ECHOMSG: + case ISN_ECHOWINDOW: case ISN_ENDTRY: case ISN_EXECCONCAT: case ISN_EXECUTE: