diff --git a/.github/workflows/ci-windows.yaml b/.github/workflows/ci-windows.yaml index d23beef414..0fef20da5b 100644 --- a/.github/workflows/ci-windows.yaml +++ b/.github/workflows/ci-windows.yaml @@ -127,6 +127,11 @@ jobs: ) goto :eof + - name: Copy src directory to src2 + shell: cmd + run: | + xcopy src src2\ /E > nul + - name: Build (MSVC) if: matrix.toolchain == 'msvc' shell: cmd @@ -196,10 +201,6 @@ jobs: echo %COL_GREEN%vim version:%COL_RESET% .\vim --version || exit 1 - mkdir ..\src2 - xcopy testdir ..\src2\testdir\ /E > nul || exit 1 - copy evalfunc.c ..\src2 > nul - echo %COL_GREEN%Start testing vim in background.%COL_RESET% start cmd /c "cd ..\src2\testdir & nmake -nologo -f Make_dos.mak VIMPROG=..\..\src\vim > nul & echo done>done.txt" diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 1e88a62ffa..46cb9b59c3 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -1,4 +1,4 @@ -*sign.txt* For Vim version 8.2. Last change: 2019 Nov 30 +*sign.txt* For Vim version 8.2. Last change: 2020 Aug 31 VIM REFERENCE MANUAL by Gordon Prieur @@ -85,6 +85,10 @@ When the line on which the sign is placed is deleted, the sign is moved to the next line (or the last line of the buffer, if there is no next line). When the delete is undone the sign does not move back. +When a sign with line highlighting and 'cursorline' highlighting are both +present, if the priority is 100 or more then the sign highlighting takes +precedence, otherwise the 'cursorline' highlighting. + ============================================================================== 2. Commands *sign-commands* *:sig* *:sign* diff --git a/runtime/filetype.vim b/runtime/filetype.vim index ae6dc6f1d3..5d4d77609a 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -240,10 +240,10 @@ au BufNewFile,BufRead */etc/blkid.tab,*/etc/blkid.tab.old setf xml au BufNewFile,BufRead *bsd,*.bsdl setf bsdl " Bazel (http://bazel.io) -autocmd BufRead,BufNewFile *.bzl,WORKSPACE,BUILD.bazel setf bzl +autocmd BufRead,BufNewFile *.bzl,*.bazel,WORKSPACE setf bzl if has("fname_case") " There is another check for BUILD further below. - autocmd BufRead,BufNewFile BUILD setf bzl + autocmd BufRead,BufNewFile *.BUILD,BUILD setf bzl endif " C or lpc @@ -2042,7 +2042,7 @@ au BufNewFile,BufRead bzr_log.* setf bzr " Bazel build file if !has("fname_case") - au BufNewFile,BufRead BUILD setf bzl + au BufNewFile,BufRead *.BUILD,BUILD setf bzl endif " BIND zone diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 6680b48cce..832dcf584b 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -2,7 +2,7 @@ " " Author: Bram Moolenaar " Copyright: Vim license applies, see ":help license" -" Last Change: 2020 Jul 12 +" Last Change: 2020 Aug 31 " " WORK IN PROGRESS - Only the basics work " Note: On MS-Windows you need a recent version of gdb. The one included with @@ -937,7 +937,7 @@ func s:HandleCursor(msg) endif exe lnum exe 'sign unplace ' . s:pc_id - exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fname + exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC priority=110 file=' . fname setlocal signcolumn=yes endif elseif !s:stopped || fname != '' diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index db0513f432..5fc08331da 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -38,6 +38,9 @@ DEBUG=no # set to yes to create a mapfile #MAP=yes +# set to yes to measure code coverage +COVERAGE=no + # set to SIZE for size, SPEED for speed, MAXSPEED for maximum optimization OPTIMIZE=MAXSPEED @@ -700,6 +703,11 @@ CFLAGS += -O2 LFLAGS += -s endif +ifeq ($(COVERAGE),yes) +CFLAGS += --coverage +LFLAGS += --coverage +endif + LIB = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomdlg32 -lcomctl32 -lnetapi32 -lversion GUIOBJ = $(OUTDIR)/gui.o $(OUTDIR)/gui_w32.o $(OUTDIR)/gui_beval.o CUIOBJ = $(OUTDIR)/iscygpty.o @@ -938,6 +946,9 @@ EXELFLAGS += -municode ifneq ($(DEBUG),yes) EXELFLAGS += -s endif + ifeq ($(COVERAGE),yes) +EXELFLAGS += --coverage + endif DEFINES += $(DEF_GUI) -DVIMDLL OBJ += $(GUIOBJ) $(CUIOBJ) OUTDIR = dobj$(DEBUG_SUFFIX)$(MZSCHEME_SUFFIX)$(ARCH) diff --git a/src/Makefile b/src/Makefile index eb52638f0f..9e435895ea 100644 --- a/src/Makefile +++ b/src/Makefile @@ -610,8 +610,9 @@ CClink = $(CC) # Use this with GCC to check for mistakes, unused arguments, etc. # Note: If you use -Wextra and get warnings in GTK code about function -# parameters, you can add -Wno-cast-function-type +# parameters, you can add -Wno-cast-function-type (but not with clang) #CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-cast-function-type -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 +#CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 # Add -Wpedantic to find // comments and other C99 constructs. # Better disable Perl and Python to avoid a lot of warnings. #CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wpedantic -Wunreachable-code -Wunused-result -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 @@ -690,8 +691,8 @@ LINT_OPTIONS = -beprxzF # Uncomment one of the next two lines to compile Vim with the -# address sanitizer (asan) or with the undefined sanitizer. Works with gcc and -# clang. May make Vim twice as slow. Errors reported on stderr. +# address sanitizer (asan) or with the undefined sanitizer. Works with gcc. +# May make Vim twice as slow. Errors are reported on stderr. # More at: https://code.google.com/p/address-sanitizer/ # Useful environment variables: # $ export ASAN_OPTIONS="print_stacktrace=1 log_path=asan" @@ -699,6 +700,13 @@ LINT_OPTIONS = -beprxzF # When running tests output can be found in testdir/asan.* #SANITIZER_CFLAGS = -g -O0 -fsanitize=address -fno-omit-frame-pointer #SANITIZER_CFLAGS = -g -O0 -fsanitize=undefined -fno-omit-frame-pointer + +# Similarly when compiling with clang and using ubsan. +# $ export UBSAN_OPTIONS="print_stacktrace=1 log_path=ubsan" +# $ export LSAN_OPTIONS="suppressions=`pwd`/testdir/lsan-suppress.txt" +# When running tests output can be found in testdir/ubsan.* +#SANITIZER_CFLAGS = -g -O0 -fsanitize-recover=all -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer + SANITIZER_LIBS = $(SANITIZER_CFLAGS) # MEMORY LEAK DETECTION diff --git a/src/auto/configure b/src/auto/configure index df9e61689d..c66b6ee5ce 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -13934,7 +13934,7 @@ DIR * dir=opendir("dirname"); dirfd(dir); return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; $as_echo "#define HAVE_DIRFD 1" >>confdefs.h @@ -13942,7 +13942,8 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not usable" >&5 $as_echo "not usable" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for flock" >&5 $as_echo_n "checking for flock... " >&6; } @@ -13957,7 +13958,7 @@ flock(10, LOCK_SH); return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; $as_echo "#define HAVE_FLOCK 1" >>confdefs.h @@ -13965,7 +13966,8 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not usable" >&5 $as_echo "not usable" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysctl" >&5 $as_echo_n "checking for sysctl... " >&6; } diff --git a/src/configure.ac b/src/configure.ac index e23470a69e..5a67095430 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -4143,7 +4143,7 @@ AC_TRY_LINK([#include ], [rename("this", "that")], dnl check for dirfd() AC_MSG_CHECKING(for dirfd) -AC_TRY_COMPILE( +AC_TRY_LINK( [#include #include ], [DIR * dir=opendir("dirname"); dirfd(dir);], @@ -4151,7 +4151,7 @@ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_DIRFD), AC_MSG_RESULT(not usable)) dnl check for flock() AC_MSG_CHECKING(for flock) -AC_TRY_COMPILE( +AC_TRY_LINK( [#include ], [flock(10, LOCK_SH);], AC_MSG_RESULT(yes); AC_DEFINE(HAVE_FLOCK), AC_MSG_RESULT(not usable)) diff --git a/src/drawline.c b/src/drawline.c index 2c89f643d9..d2c9b24b6d 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -909,7 +909,19 @@ win_line( if (!cul_screenline) { cul_attr = HL_ATTR(HLF_CUL); - line_attr = cul_attr; +# ifdef FEAT_SIGNS + // Combine the 'cursorline' and sign highlighting, depending on + // the sign priority. + if (sign_present && sattr.sat_linehl > 0) + { + if (sattr.sat_priority >= 100) + line_attr = hl_combine_attr(cul_attr, line_attr); + else + line_attr = hl_combine_attr(line_attr, cul_attr); + } + else +# endif + line_attr = cul_attr; wp->w_last_cursorline = wp->w_cursor.lnum; } else diff --git a/src/eval.c b/src/eval.c index be3f4622cb..3eb4be46f0 100644 --- a/src/eval.c +++ b/src/eval.c @@ -395,7 +395,7 @@ skip_expr_concatenate( typval_T rettv; int res; int vim9script = in_vim9script(); - garray_T *gap = &evalarg->eval_ga; + garray_T *gap = evalarg == NULL ? NULL : &evalarg->eval_ga; int save_flags = evalarg == NULL ? 0 : evalarg->eval_flags; int evaluate = evalarg == NULL ? FALSE : (evalarg->eval_flags & EVAL_EVALUATE); diff --git a/src/evalbuffer.c b/src/evalbuffer.c index 5cf884a80c..300441551b 100644 --- a/src/evalbuffer.c +++ b/src/evalbuffer.c @@ -364,16 +364,7 @@ f_bufname(typval_T *argvars, typval_T *rettv) if (tv->v_type == VAR_UNKNOWN) buf = curbuf; else - { - ++emsg_off; - buf = tv_get_buf(tv, FALSE); - --emsg_off; - if (buf == NULL - && tv->v_type != VAR_NUMBER - && tv->v_type != VAR_STRING) - // issue errmsg for type error - (void)tv_get_number(tv); - } + buf = tv_get_buf_from_arg(tv); rettv->v_type = VAR_STRING; if (buf != NULL && buf->b_fname != NULL) rettv->vval.v_string = vim_strsave(buf->b_fname); @@ -394,13 +385,7 @@ f_bufnr(typval_T *argvars, typval_T *rettv) if (argvars[0].v_type == VAR_UNKNOWN) buf = curbuf; else - { - if (argvars[0].v_type != VAR_STRING) - (void)tv_get_number(&argvars[0]); // issue errmsg if type error - ++emsg_off; - buf = tv_get_buf(&argvars[0], FALSE); - --emsg_off; - } + buf = tv_get_buf_from_arg(&argvars[0]); // If the buffer isn't found and the second argument is not zero create a // new buffer. @@ -425,9 +410,7 @@ buf_win_common(typval_T *argvars, typval_T *rettv, int get_nr) int winnr = 0; buf_T *buf; - (void)tv_get_number(&argvars[0]); // issue errmsg if type error - ++emsg_off; - buf = tv_get_buf(&argvars[0], TRUE); + buf = tv_get_buf_from_arg(&argvars[0]); FOR_ALL_WINDOWS(wp) { ++winnr; @@ -435,7 +418,6 @@ buf_win_common(typval_T *argvars, typval_T *rettv, int get_nr) break; } rettv->vval.v_number = (wp != NULL ? (get_nr ? winnr : wp->w_id) : -1); - --emsg_off; } /* @@ -662,10 +644,7 @@ f_getbufinfo(typval_T *argvars, typval_T *rettv) else if (argvars[0].v_type != VAR_UNKNOWN) { // Information about one buffer. Argument specifies the buffer - (void)tv_get_number(&argvars[0]); // issue errmsg if type error - ++emsg_off; - argbuf = tv_get_buf(&argvars[0], FALSE); - --emsg_off; + argbuf = tv_get_buf_from_arg(&argvars[0]); if (argbuf == NULL) return; } @@ -752,10 +731,7 @@ f_getbufline(typval_T *argvars, typval_T *rettv) linenr_T end; buf_T *buf; - (void)tv_get_number(&argvars[0]); // issue errmsg if type error - ++emsg_off; - buf = tv_get_buf(&argvars[0], FALSE); - --emsg_off; + buf = tv_get_buf_from_arg(&argvars[0]); lnum = tv_get_lnum_buf(&argvars[1], buf); if (argvars[2].v_type == VAR_UNKNOWN) diff --git a/src/evalfunc.c b/src/evalfunc.c index cc1c478843..8a2cf5d892 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2434,7 +2434,7 @@ f_expand(typval_T *argvars, typval_T *rettv) rettv->v_type = VAR_STRING; if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN - && tv_get_number_chk(&argvars[2], &error) + && tv_get_bool_chk(&argvars[2], &error) && !error) rettv_list_set(rettv, NULL); @@ -2458,7 +2458,7 @@ f_expand(typval_T *argvars, typval_T *rettv) // When the optional second argument is non-zero, don't remove matches // for 'wildignore' and don't put matches for 'suffixes' at the end. if (argvars[1].v_type != VAR_UNKNOWN - && tv_get_number_chk(&argvars[1], &error)) + && tv_get_bool_chk(&argvars[1], &error)) options |= WILD_KEEP_ALL; if (!error) { @@ -3081,12 +3081,7 @@ f_getchangelist(typval_T *argvars, typval_T *rettv) if (argvars[0].v_type == VAR_UNKNOWN) buf = curbuf; else - { - (void)tv_get_number(&argvars[0]); // issue errmsg if type error - ++emsg_off; - buf = tv_get_buf(&argvars[0], FALSE); - --emsg_off; - } + buf = tv_get_buf_from_arg(&argvars[0]); if (buf == NULL) return; @@ -3341,9 +3336,9 @@ f_getreg(typval_T *argvars, typval_T *rettv) error = strregname == NULL; if (argvars[1].v_type != VAR_UNKNOWN) { - arg2 = (int)tv_get_number_chk(&argvars[1], &error); + arg2 = (int)tv_get_bool_chk(&argvars[1], &error); if (!error && argvars[2].v_type != VAR_UNKNOWN) - return_list = (int)tv_get_number_chk(&argvars[2], &error); + return_list = (int)tv_get_bool_chk(&argvars[2], &error); } } else @@ -4848,7 +4843,7 @@ f_hasmapto(typval_T *argvars, typval_T *rettv) { mode = tv_get_string_buf(&argvars[1], buf); if (argvars[2].v_type != VAR_UNKNOWN) - abbr = (int)tv_get_number(&argvars[2]); + abbr = (int)tv_get_bool(&argvars[2]); } if (map_to_exists(name, mode, abbr)) @@ -4984,7 +4979,7 @@ f_index(typval_T *argvars, typval_T *rettv) item = list_find(l, (long)tv_get_number_chk(&argvars[2], &error)); idx = l->lv_u.mat.lv_idx; if (argvars[3].v_type != VAR_UNKNOWN) - ic = (int)tv_get_number_chk(&argvars[3], &error); + ic = (int)tv_get_bool_chk(&argvars[3], &error); if (error) item = NULL; } diff --git a/src/evalvars.c b/src/evalvars.c index 2208c4c182..34aac4e596 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -3664,10 +3664,8 @@ f_getbufvar(typval_T *argvars, typval_T *rettv) dictitem_T *v; int done = FALSE; - (void)tv_get_number(&argvars[0]); // issue errmsg if type error varname = tv_get_string_chk(&argvars[1]); - ++emsg_off; - buf = tv_get_buf(&argvars[0], FALSE); + buf = tv_get_buf_from_arg(&argvars[0]); rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -3719,8 +3717,6 @@ f_getbufvar(typval_T *argvars, typval_T *rettv) if (!done && argvars[2].v_type != VAR_UNKNOWN) // use the default value copy_tv(&argvars[2], rettv); - - --emsg_off; } /* @@ -3791,9 +3787,8 @@ f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED) if (check_secure()) return; - (void)tv_get_number(&argvars[0]); // issue errmsg if type error varname = tv_get_string_chk(&argvars[1]); - buf = tv_get_buf(&argvars[0], FALSE); + buf = tv_get_buf_from_arg(&argvars[0]); varp = &argvars[2]; if (buf != NULL && varname != NULL && varp != NULL) diff --git a/src/evalwindow.c b/src/evalwindow.c index b50776d74d..3ddd96bcbc 100644 --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -117,7 +117,7 @@ win_id2wp_tp(int id, tabpage_T **tpp) if (wp->w_id == id) { if (tpp != NULL) - *tpp = tp; + *tpp = curtab; // any tabpage would do return wp; } #endif diff --git a/src/ex_getln.c b/src/ex_getln.c index c2d011df5b..f40e50c993 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -397,7 +397,8 @@ may_do_incsearch_highlighting( // NOTE: must call restore_last_search_pattern() before returning! save_last_search_pattern(); - if (!do_incsearch_highlighting(firstc, &search_delim, is_state, &skiplen, &patlen)) + if (!do_incsearch_highlighting(firstc, &search_delim, is_state, + &skiplen, &patlen)) { restore_last_search_pattern(); finish_incsearch_highlighting(FALSE, is_state, TRUE); @@ -1235,10 +1236,10 @@ getcmdline_int( if (has_mbyte) j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + j); if (vim_ispathsep(ccline.cmdbuff[j]) -#ifdef BACKSLASH_IN_FILENAME +# ifdef BACKSLASH_IN_FILENAME && vim_strchr((char_u *)" *?[{`$%#", ccline.cmdbuff[j + 1]) == NULL -#endif +# endif ) { if (found) @@ -1425,6 +1426,7 @@ getcmdline_int( if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm) { int options = WILD_NO_BEEP; + if (wim_flags[wim_index] & WIM_BUFLASTUSED) options |= WILD_BUFLASTUSED; if (xpc.xp_numfiles > 0) // typed p_wc at least twice @@ -1442,8 +1444,7 @@ getcmdline_int( res = nextwild(&xpc, WILD_LONGEST, options, firstc != '@'); else if (wim_flags[wim_index] & WIM_FULL) - res = nextwild(&xpc, WILD_NEXT, options, - firstc != '@'); + res = nextwild(&xpc, WILD_NEXT, options, firstc != '@'); else res = OK; // don't insert 'wildchar' now } @@ -1454,11 +1455,10 @@ getcmdline_int( // if 'wildmode' first contains "longest", get longest // common part if (wim_flags[0] & WIM_LONGEST) - res = nextwild(&xpc, WILD_LONGEST, options, - firstc != '@'); + res = nextwild(&xpc, WILD_LONGEST, options, firstc != '@'); else res = nextwild(&xpc, WILD_EXPAND_KEEP, options, - firstc != '@'); + firstc != '@'); // if interrupted while completing, behave like it failed if (got_int) @@ -1483,7 +1483,7 @@ getcmdline_int( wim_index = 1; if ((wim_flags[wim_index] & WIM_LIST) #ifdef FEAT_WILDMENU - || (p_wmnu && (wim_flags[wim_index] & WIM_FULL) != 0) + || (p_wmnu && (wim_flags[wim_index] & WIM_FULL) != 0) #endif ) { @@ -1511,8 +1511,7 @@ getcmdline_int( nextwild(&xpc, WILD_LONGEST, options, firstc != '@'); else if (wim_flags[wim_index] & WIM_FULL) - nextwild(&xpc, WILD_NEXT, options, - firstc != '@'); + nextwild(&xpc, WILD_NEXT, options, firstc != '@'); } else vim_beep(BO_WILD); @@ -2357,7 +2356,8 @@ cmdline_changed: trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED); #ifdef FEAT_SEARCH_EXTRA - may_do_incsearch_highlighting(firstc, count, &is_state); + if (xpc.xp_context == EXPAND_NOTHING) + may_do_incsearch_highlighting(firstc, count, &is_state); #endif #ifdef FEAT_RIGHTLEFT diff --git a/src/fileio.c b/src/fileio.c index 35bc567aaa..d701bde167 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -24,6 +24,11 @@ // Is there any system that doesn't have access()? #define USE_MCH_ACCESS +#if defined(__hpux) && !defined(HAVE_DIRFD) +# define dirfd(x) ((x)->__dd_fd) +# define HAVE_DIRFD +#endif + static char_u *next_fenc(char_u **pp, int *alloced); #ifdef FEAT_EVAL static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp); diff --git a/src/filepath.c b/src/filepath.c index 5a63887187..22d8047b6f 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -1174,14 +1174,14 @@ f_glob(typval_T *argvars, typval_T *rettv) rettv->v_type = VAR_STRING; if (argvars[1].v_type != VAR_UNKNOWN) { - if (tv_get_number_chk(&argvars[1], &error)) + if (tv_get_bool_chk(&argvars[1], &error)) options |= WILD_KEEP_ALL; if (argvars[2].v_type != VAR_UNKNOWN) { - if (tv_get_number_chk(&argvars[2], &error)) + if (tv_get_bool_chk(&argvars[2], &error)) rettv_list_set(rettv, NULL); if (argvars[3].v_type != VAR_UNKNOWN - && tv_get_number_chk(&argvars[3], &error)) + && tv_get_bool_chk(&argvars[3], &error)) options |= WILD_ALLLINKS; } } @@ -1241,14 +1241,14 @@ f_globpath(typval_T *argvars, typval_T *rettv) rettv->v_type = VAR_STRING; if (argvars[2].v_type != VAR_UNKNOWN) { - if (tv_get_number_chk(&argvars[2], &error)) + if (tv_get_bool_chk(&argvars[2], &error)) flags |= WILD_KEEP_ALL; if (argvars[3].v_type != VAR_UNKNOWN) { - if (tv_get_number_chk(&argvars[3], &error)) + if (tv_get_bool_chk(&argvars[3], &error)) rettv_list_set(rettv, NULL); if (argvars[4].v_type != VAR_UNKNOWN - && tv_get_number_chk(&argvars[4], &error)) + && tv_get_bool_chk(&argvars[4], &error)) flags |= WILD_ALLLINKS; } } diff --git a/src/fold.c b/src/fold.c index 043037fa64..5c55b0777b 100644 --- a/src/fold.c +++ b/src/fold.c @@ -608,35 +608,41 @@ foldCreate(linenr_T start, linenr_T end) // Find the place to insert the new fold. gap = &curwin->w_folds; - for (;;) + if (gap->ga_len == 0) + i = 0; + else { - if (!foldFind(gap, start_rel, &fp)) - break; - if (fp->fd_top + fp->fd_len > end_rel) + for (;;) { - // New fold is completely inside this fold: Go one level deeper. - gap = &fp->fd_nested; - start_rel -= fp->fd_top; - end_rel -= fp->fd_top; - if (use_level || fp->fd_flags == FD_LEVEL) + if (!foldFind(gap, start_rel, &fp)) + break; + if (fp->fd_top + fp->fd_len > end_rel) { - use_level = TRUE; - if (level >= curwin->w_p_fdl) + // New fold is completely inside this fold: Go one level + // deeper. + gap = &fp->fd_nested; + start_rel -= fp->fd_top; + end_rel -= fp->fd_top; + if (use_level || fp->fd_flags == FD_LEVEL) + { + use_level = TRUE; + if (level >= curwin->w_p_fdl) + closed = TRUE; + } + else if (fp->fd_flags == FD_CLOSED) closed = TRUE; + ++level; + } + else + { + // This fold and new fold overlap: Insert here and move some + // folds inside the new fold. + break; } - else if (fp->fd_flags == FD_CLOSED) - closed = TRUE; - ++level; - } - else - { - // This fold and new fold overlap: Insert here and move some folds - // inside the new fold. - break; } + i = (int)(fp - (fold_T *)gap->ga_data); } - i = (int)(fp - (fold_T *)gap->ga_data); if (ga_grow(gap, 1) == OK) { fp = (fold_T *)gap->ga_data + i; @@ -820,13 +826,16 @@ foldUpdate(win_T *wp, linenr_T top, linenr_T bot) return; #endif - // Mark all folds from top to bot as maybe-small. - (void)foldFind(&wp->w_folds, top, &fp); - while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len - && fp->fd_top < bot) + if (wp->w_folds.ga_len > 0) { - fp->fd_small = MAYBE; - ++fp; + // Mark all folds from top to bot as maybe-small. + (void)foldFind(&wp->w_folds, top, &fp); + while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len + && fp->fd_top < bot) + { + fp->fd_small = MAYBE; + ++fp; + } } if (foldmethodIsIndent(wp) @@ -1127,6 +1136,12 @@ foldFind(garray_T *gap, linenr_T lnum, fold_T **fpp) fold_T *fp; int i; + if (gap->ga_len == 0) + { + *fpp = NULL; + return FALSE; + } + /* * Perform a binary search. * "low" is lowest index of possible match. @@ -1299,7 +1314,7 @@ setManualFoldWin( if (!foldFind(gap, lnum, &fp)) { // If there is a following fold, continue there next time. - if (fp < (fold_T *)gap->ga_data + gap->ga_len) + if (fp != NULL && fp < (fold_T *)gap->ga_data + gap->ga_len) next = fp->fd_top + off; break; } @@ -1500,6 +1515,9 @@ foldMarkAdjustRecurse( linenr_T last; linenr_T top; + if (gap->ga_len == 0) + return; + // In Insert mode an inserted line at the top of a fold is considered part // of the fold, otherwise it isn't. if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) @@ -2500,14 +2518,14 @@ foldUpdateIEMSRecurse( // Find an existing fold to re-use. Preferably one that // includes startlnum, otherwise one that ends just before // startlnum or starts after it. - if (foldFind(gap, startlnum, &fp) + if (gap->ga_len > 0 && (foldFind(gap, startlnum, &fp) || (fp < ((fold_T *)gap->ga_data) + gap->ga_len && fp->fd_top <= firstlnum) || foldFind(gap, firstlnum - concat, &fp) || (fp < ((fold_T *)gap->ga_data) + gap->ga_len && ((lvl < level && fp->fd_top < flp->lnum) || (lvl >= level - && fp->fd_top <= flp->lnum_save)))) + && fp->fd_top <= flp->lnum_save))))) { if (fp->fd_top + fp->fd_len + concat > firstlnum) { @@ -2622,7 +2640,10 @@ foldUpdateIEMSRecurse( { // Insert new fold. Careful: ga_data may be NULL and it // may change! - i = (int)(fp - (fold_T *)gap->ga_data); + if (gap->ga_len == 0) + i = 0; + else + i = (int)(fp - (fold_T *)gap->ga_data); if (foldInsert(gap, i) != OK) return bot; fp = (fold_T *)gap->ga_data + i; @@ -2841,7 +2862,7 @@ foldInsert(garray_T *gap, int i) if (ga_grow(gap, 1) != OK) return FAIL; fp = (fold_T *)gap->ga_data + i; - if (i < gap->ga_len) + if (gap->ga_len > 0 && i < gap->ga_len) mch_memmove(fp + 1, fp, sizeof(fold_T) * (gap->ga_len - i)); ++gap->ga_len; ga_init2(&fp->fd_nested, (int)sizeof(fold_T), 10); @@ -2884,18 +2905,20 @@ foldSplit( // any between top and bot, they have been removed by the caller. gap1 = &fp->fd_nested; gap2 = &fp[1].fd_nested; - (void)(foldFind(gap1, bot + 1 - fp->fd_top, &fp2)); - len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2); - if (len > 0 && ga_grow(gap2, len) == OK) + if (foldFind(gap1, bot + 1 - fp->fd_top, &fp2)) { - for (idx = 0; idx < len; ++idx) + len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2); + if (len > 0 && ga_grow(gap2, len) == OK) { - ((fold_T *)gap2->ga_data)[idx] = fp2[idx]; - ((fold_T *)gap2->ga_data)[idx].fd_top - -= fp[1].fd_top - fp->fd_top; + for (idx = 0; idx < len; ++idx) + { + ((fold_T *)gap2->ga_data)[idx] = fp2[idx]; + ((fold_T *)gap2->ga_data)[idx].fd_top + -= fp[1].fd_top - fp->fd_top; + } + gap2->ga_len = len; + gap1->ga_len -= len; } - gap2->ga_len = len; - gap1->ga_len -= len; } fp->fd_len = top - fp->fd_top; fold_changed = TRUE; @@ -2928,7 +2951,7 @@ foldRemove(garray_T *gap, linenr_T top, linenr_T bot) if (bot < top) return; // nothing to do - for (;;) + while (gap->ga_len > 0) { // Find fold that includes top or a following one. if (foldFind(gap, top, &fp) && fp->fd_top < top) @@ -3036,7 +3059,7 @@ truncate_fold(fold_T *fp, linenr_T end) } #define fold_end(fp) ((fp)->fd_top + (fp)->fd_len - 1) -#define valid_fold(fp, gap) ((fp) < ((fold_T *)(gap)->ga_data + (gap)->ga_len)) +#define valid_fold(fp, gap) ((gap)->ga_len > 0 && (fp) < ((fold_T *)(gap)->ga_data + (gap)->ga_len)) #define fold_index(fp, gap) ((size_t)(fp - ((fold_T *)(gap)->ga_data))) void diff --git a/src/globals.h b/src/globals.h index e0c8caf055..b79f540e6a 100644 --- a/src/globals.h +++ b/src/globals.h @@ -773,7 +773,8 @@ EXTERN int ru_wid; // 'rulerfmt' width of ruler when non-zero EXTERN int sc_col; // column for shown command #ifdef TEMPDIRNAMES -# if defined(UNIX) && defined(HAVE_FLOCK) && defined(HAVE_DIRFD) +# if defined(UNIX) && defined(HAVE_FLOCK) \ + && (defined(HAVE_DIRFD) || defined(__hpux)) EXTERN DIR *vim_tempdir_dp INIT(= NULL); // File descriptor of temp dir # endif EXTERN char_u *vim_tempdir INIT(= NULL); // Name of Vim's own temp dir. diff --git a/src/list.c b/src/list.c index e7d288a2fb..e0c8c2e17d 100644 --- a/src/list.c +++ b/src/list.c @@ -2167,7 +2167,7 @@ f_count(typval_T *argvars, typval_T *rettv) int error = FALSE; if (argvars[2].v_type != VAR_UNKNOWN) - ic = (int)tv_get_number_chk(&argvars[2], &error); + ic = (int)tv_get_bool_chk(&argvars[2], &error); if (argvars[0].v_type == VAR_STRING) { diff --git a/src/map.c b/src/map.c index 42102fa257..d1ea8c2e94 100644 --- a/src/map.c +++ b/src/map.c @@ -2204,9 +2204,9 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact) which = tv_get_string_buf_chk(&argvars[1], buf); if (argvars[2].v_type != VAR_UNKNOWN) { - abbr = (int)tv_get_number(&argvars[2]); + abbr = (int)tv_get_bool(&argvars[2]); if (argvars[3].v_type != VAR_UNKNOWN) - get_dict = (int)tv_get_number(&argvars[3]); + get_dict = (int)tv_get_bool(&argvars[3]); } } else diff --git a/src/os_win32.c b/src/os_win32.c index 96af44364b..52573fe621 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -2065,6 +2065,13 @@ theend: buf[len++] = typeahead[0]; mch_memmove(typeahead, typeahead + 1, --typeaheadlen); } +# ifdef FEAT_JOB_CHANNEL + if (len > 0) + { + buf[len] = NUL; + ch_log(NULL, "raw key input: \"%s\"", buf); + } +# endif return len; #else // FEAT_GUI_MSWIN diff --git a/src/popupwin.c b/src/popupwin.c index 053d6d3fd8..953e76cc7e 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -2125,7 +2125,7 @@ f_popup_clear(typval_T *argvars, typval_T *rettv UNUSED) int force = FALSE; if (argvars[0].v_type != VAR_UNKNOWN) - force = (int)tv_get_number(&argvars[0]); + force = (int)tv_get_bool(&argvars[0]); close_all_popups(force); } diff --git a/src/proto/typval.pro b/src/proto/typval.pro index 25ad3e6737..9c57226da2 100644 --- a/src/proto/typval.pro +++ b/src/proto/typval.pro @@ -29,4 +29,5 @@ int eval_env_var(char_u **arg, typval_T *rettv, int evaluate); linenr_T tv_get_lnum(typval_T *argvars); linenr_T tv_get_lnum_buf(typval_T *argvars, buf_T *buf); buf_T *tv_get_buf(typval_T *tv, int curtab_only); +buf_T *tv_get_buf_from_arg(typval_T *tv); /* vim: set ft=c : */ diff --git a/src/quickfix.c b/src/quickfix.c index 99b0169ea5..f8ff7765ed 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -6022,7 +6022,7 @@ vgr_process_args( static int existing_swapfile(buf_T *buf) { - if (buf->b_ml.ml_mfp != NULL) + if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) { char_u *fname = buf->b_ml.ml_mfp->mf_fname; size_t len = STRLEN(fname); diff --git a/src/sign.c b/src/sign.c index fb452b30c5..fd373b5c3e 100644 --- a/src/sign.c +++ b/src/sign.c @@ -517,6 +517,7 @@ buf_get_signattrs(win_T *wp, linenr_T lnum, sign_attrs_T *sattr) sattr->sat_texthl = syn_id2attr(sp->sn_text_hl); if (sp->sn_line_hl > 0) sattr->sat_linehl = syn_id2attr(sp->sn_line_hl); + sattr->sat_priority = sign->se_priority; // If there is another sign next with the same priority, may // combine the text and the line highlighting. diff --git a/src/spellfile.c b/src/spellfile.c index 6aeac86b85..869db7f3ff 100644 --- a/src/spellfile.c +++ b/src/spellfile.c @@ -816,11 +816,15 @@ read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) // read the length bytes, MSB first for (i = 0; i < cnt_bytes; ++i) - cnt = (cnt << 8) + getc(fd); - if (cnt < 0) { - *cntp = SP_TRUNCERROR; - return NULL; + int c = getc(fd); + + if (c == EOF) + { + *cntp = SP_TRUNCERROR; + return NULL; + } + cnt = (cnt << 8) + (unsigned)c; } *cntp = cnt; if (cnt == 0) @@ -3529,8 +3533,7 @@ spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) spin->si_msg_count = 999999; // Read and ignore the first line: word count. - (void)vim_fgets(line, MAXLINELEN, fd); - if (!vim_isdigit(*skipwhite(line))) + if (vim_fgets(line, MAXLINELEN, fd) || !vim_isdigit(*skipwhite(line))) semsg(_("E760: No word count in %s"), fname); /* diff --git a/src/spellsuggest.c b/src/spellsuggest.c index 0821dc62cb..e2423cd98a 100644 --- a/src/spellsuggest.c +++ b/src/spellsuggest.c @@ -3606,6 +3606,8 @@ check_suggestions( int len; hlf_T attr; + if (gap->ga_len == 0) + return; stp = &SUG(*gap, 0); for (i = gap->ga_len - 1; i >= 0; --i) { @@ -3729,9 +3731,6 @@ cleanup_suggestions( int maxscore, int keep) // nr of suggestions to keep { - suggest_T *stp = &SUG(*gap, 0); - int i; - if (gap->ga_len > 0) { // Sort the list. @@ -3742,6 +3741,9 @@ cleanup_suggestions( // displayed. if (gap->ga_len > keep) { + int i; + suggest_T *stp = &SUG(*gap, 0); + for (i = keep; i < gap->ga_len; ++i) vim_free(stp[i].st_word); gap->ga_len = keep; diff --git a/src/structs.h b/src/structs.h index feeb6240f1..835eae639a 100644 --- a/src/structs.h +++ b/src/structs.h @@ -817,6 +817,7 @@ typedef struct sign_attrs_S { char_u *sat_text; int sat_texthl; int sat_linehl; + int sat_priority; } sign_attrs_T; #if defined(FEAT_SIGNS) || defined(PROTO) diff --git a/src/testdir/dumps/Test_sign_cursor_5.dump b/src/testdir/dumps/Test_sign_cursor_5.dump new file mode 100644 index 0000000000..2f256a507f --- /dev/null +++ b/src/testdir/dumps/Test_sign_cursor_5.dump @@ -0,0 +1,6 @@ +| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0@72 +| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0@1| @70 +| +0#0000e05#a8a8a8255@1>m+8#0000001#40ff4011@3| @68 +| +0#0000e05#a8a8a8255@1|y+0#0000000#ffffff0@3| @68 +|~+0#4040ff13&| @73 +|:+0#0000000&| @55|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_sign_cursor_6.dump b/src/testdir/dumps/Test_sign_cursor_6.dump new file mode 100644 index 0000000000..efd9042a3e --- /dev/null +++ b/src/testdir/dumps/Test_sign_cursor_6.dump @@ -0,0 +1,6 @@ +| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0@72 +| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0@1| @70 +| +0#0000e05#a8a8a8255@1>m+8#0000001#ffd7ff255@3| @68 +| +0#0000e05#a8a8a8255@1|y+0#0000000#ffffff0@3| @68 +|~+0#4040ff13&| @73 +|:+0#0000000&| @55|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_wildmenu_1.dump b/src/testdir/dumps/Test_wildmenu_1.dump new file mode 100644 index 0000000000..a118969584 --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_1.dump @@ -0,0 +1,8 @@ +| +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|v+0#0000001#ffff4012|i|m|9|s|c|r|i|p|t| +3#0000000#ffffff0@1|v|i|m|g|r|e|p| @1|v|i|m|g|r|e|p|a|d@1| @43 +|:+0&&|v|i|m|9|s|c|r|i|p|t> @63 diff --git a/src/testdir/dumps/Test_wildmenu_2.dump b/src/testdir/dumps/Test_wildmenu_2.dump new file mode 100644 index 0000000000..46b41ae075 --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_2.dump @@ -0,0 +1,8 @@ +| +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|v+3#0000000&|i|m|9|s|c|r|i|p|t| @1|v+0#0000001#ffff4012|i|m|g|r|e|p| +3#0000000#ffffff0@1|v|i|m|g|r|e|p|a|d@1| @43 +|:+0&&|v|i|m|g|r|e|p> @66 diff --git a/src/testdir/dumps/Test_wildmenu_3.dump b/src/testdir/dumps/Test_wildmenu_3.dump new file mode 100644 index 0000000000..44749367df --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_3.dump @@ -0,0 +1,8 @@ +| +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|v+3#0000000&|i|m|9|s|c|r|i|p|t| @1|v|i|m|g|r|e|p| @1|v+0#0000001#ffff4012|i|m|g|r|e|p|a|d@1| +3#0000000#ffffff0@43 +|:+0&&|v|i|m|g|r|e|p|a|d@1> @63 diff --git a/src/testdir/dumps/Test_wildmenu_4.dump b/src/testdir/dumps/Test_wildmenu_4.dump new file mode 100644 index 0000000000..3703fd5292 --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_4.dump @@ -0,0 +1,8 @@ +| +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|v+3#0000000&|i|m|9|s|c|r|i|p|t| @1|v|i|m|g|r|e|p| @1|v|i|m|g|r|e|p|a|d@1| @43 +|:+0&&|v|i|m> @70 diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index c14183f85f..fc2e52c225 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -382,7 +382,9 @@ endif " Names of flaky tests. let s:flaky_tests = [ + \ 'Test_BufWrite_lockmarks()', \ 'Test_autocmd_SafeState()', + \ 'Test_bufunload_all()', \ 'Test_client_server()', \ 'Test_close_and_exit_cb()', \ 'Test_close_output_buffer()', diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 266513ee9f..6ebfa31c86 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -84,6 +84,34 @@ func Test_complete_wildmenu() call delete('Xdir1', 'd') set nowildmenu endfunc +f +func Test_wildmenu_screendump() + CheckScreendump + + let lines =<< trim [SCRIPT] + set wildmenu hlsearch + [SCRIPT] + call writefile(lines, 'XTest_wildmenu') + + let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8}) + call term_sendkeys(buf, ":vim\") + call VerifyScreenDump(buf, 'Test_wildmenu_1', {}) + + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_wildmenu_2', {}) + + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_wildmenu_3', {}) + + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_wildmenu_4', {}) + call term_sendkeys(buf, "\") + + " clean up + call StopVimInTerminal(buf) + call delete('XTest_wildmenu') +endfunc + func Test_map_completion() CheckFeature cmdline_compl diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 6957954a6e..5d37a866f2 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -75,6 +75,7 @@ let s:filename_checks = { \ 'ave': ['file.ave'], \ 'awk': ['file.awk', 'file.gawk'], \ 'b': ['file.mch', 'file.ref', 'file.imp'], + \ 'bzl': ['file.bazel', 'file.bzl', 'WORKSPACE'], \ 'bc': ['file.bc'], \ 'bdf': ['file.bdf'], \ 'bib': ['file.bib'], @@ -527,6 +528,7 @@ let s:filename_checks = { let s:filename_case_checks = { \ 'modula2': ['file.DEF', 'file.MOD'], + \ 'bzl': ['file.BUILD', 'BUILD'], \ } func CheckItems(checks) diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index 1aebe058f7..ec4898fa63 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -2239,6 +2239,18 @@ func Test_popup_settext() call delete('XtestPopupSetText') endfunc +func Test_popup_settext_getline() + let id = popup_create('', #{ tabpage: 0 }) + call popup_settext(id, ['a','b']) + call assert_equal(2, line('$', id)) " OK :) + call popup_close(id) + + let id = popup_create('', #{ tabpage: -1 }) + call popup_settext(id, ['a','b']) + call assert_equal(2, line('$', id)) " Fails :( + call popup_close(id) +endfunc + func Test_popup_hidden() new @@ -2559,20 +2571,23 @@ endfunc func Test_popupwin_close_prevwin() CheckFeature terminal + call Popupwin_close_prevwin() +endfunc - call assert_equal(1, winnr('$')) +def Popupwin_close_prevwin() + assert_equal(1, winnr('$')) split wincmd b - call assert_equal(2, winnr()) + assert_equal(2, winnr()) let buf = term_start(&shell, #{hidden: 1}) - call popup_create(buf, {}) - call TermWait(buf, 100) - call popup_clear(1) - call assert_equal(2, winnr()) + popup_create(buf, {}) + TermWait(buf, 100) + popup_clear(true) + assert_equal(2, winnr()) quit exe 'bwipe! ' .. buf -endfunc +enddef func Test_popupwin_with_buffer_and_filter() new Xwithfilter diff --git a/src/testdir/test_python2.vim b/src/testdir/test_python2.vim index 8fa73401bd..fd8fe70e49 100644 --- a/src/testdir/test_python2.vim +++ b/src/testdir/test_python2.vim @@ -2412,7 +2412,7 @@ func Test_python_chdir() cb.append(vim.eval('@%')) os.chdir('..') path = fnamemodify('.', ':p:h:t') - if path != 'src': + if path != 'src' and path != 'src2': # Running tests from a shadow directory, so move up another level # This will result in @% looking like shadow/testdir/Xfile, hence the # extra fnamemodify @@ -2422,7 +2422,8 @@ func Test_python_chdir() os.chdir(path) del path else: - cb.append(fnamemodify('.', ':p:h:t')) + # Also accept running from src2/testdir/ for MS-Windows CI. + cb.append(fnamemodify('.', ':p:h:t').replace('src2', 'src')) cb.append(vim.eval('@%').replace(os.path.sep, '/')) os.chdir('testdir') cb.append(fnamemodify('.', ':p:h:t')) diff --git a/src/testdir/test_python3.vim b/src/testdir/test_python3.vim index 0885c96988..1bdb4c1719 100644 --- a/src/testdir/test_python3.vim +++ b/src/testdir/test_python3.vim @@ -2591,7 +2591,7 @@ func Test_python3_chdir() cb.append(vim.eval('@%')) os.chdir('..') path = fnamemodify('.', ':p:h:t') - if path != b'src': + if path != b'src' and path != b'src2': # Running tests from a shadow directory, so move up another level # This will result in @% looking like shadow/testdir/Xfile, hence the # slicing to remove the leading path and path separator @@ -2600,7 +2600,8 @@ func Test_python3_chdir() cb.append(vim.eval('@%')[len(path)+1:].replace(os.path.sep, '/')) os.chdir(path) else: - cb.append(str(fnamemodify('.', ':p:h:t'))) + # Also accept running from src2/testdir/ for MS-Windows CI. + cb.append(str(fnamemodify('.', ':p:h:t').replace(b'src2', b'src'))) cb.append(vim.eval('@%').replace(os.path.sep, '/')) del path os.chdir('testdir') diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index c35b11c669..8faf69a318 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -2833,6 +2833,21 @@ func Test_vimgrep_with_no_last_search_pat() call delete('Xresult') endfunc +" Test vimgrep without swap file +func Test_vimgrep_without_swap_file() + let lines =<< trim [SCRIPT] + vimgrep grep test_c* + call writefile(['done'], 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -n -S Xscript Xscript') + call assert_equal(['done'], readfile('Xresult')) + endif + call delete('Xscript') + call delete('Xresult') +endfunc + func Test_vimgrep_existing_swapfile() call writefile(['match apple with apple'], 'Xapple') call writefile(['swapfile'], '.Xapple.swp') diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim index e8508b8d35..3ee2b49fa1 100644 --- a/src/testdir/test_signs.vim +++ b/src/testdir/test_signs.vim @@ -1762,6 +1762,20 @@ func Test_sign_cursor_position() call term_sendkeys(buf, ":sign unplace 10\") call VerifyScreenDump(buf, 'Test_sign_cursor_4', {}) + " 'cursorline' highlighting overrules sign + call term_sendkeys(buf, ":sign place 12 line=2 name=s2\") + call term_sendkeys(buf, ":set cursorline\") + call term_sendkeys(buf, ":hi CursorLine ctermbg=Green\") + call term_sendkeys(buf, "2G") + call term_sendkeys(buf, ":\") + call VerifyScreenDump(buf, 'Test_sign_cursor_5', {}) + + " sign highlighting overrules 'cursorline' + call term_sendkeys(buf, ":sign unplace 12\") + call term_sendkeys(buf, ":sign place 13 line=2 priority=100 name=s2\") + call term_sendkeys(buf, ":\") + call VerifyScreenDump(buf, 'Test_sign_cursor_6', {}) + " clean up call StopVimInTerminal(buf) call delete('XtestSigncolumn') diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index 9db5275d52..bacb288c52 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -211,8 +211,29 @@ func Test_prop_find() call prop_clear(1,6) call prop_type_delete('prop_name') + + bwipe! endfunc +def Test_prop_find2() + # Multiple props per line, start on the first, should find the second. + new + ['the quikc bronw fox jumsp over the layz dog']->repeat(2)->setline(1) + prop_type_add('misspell', #{highlight: 'ErrorMsg'}) + for lnum in [1, 2] + for col in [8, 14, 24, 38] + prop_add(lnum, col, #{type: 'misspell', length: 2}) + endfor + endfor + cursor(1, 8) + let expected = {'lnum': 1, 'id': 0, 'col': 14, 'end': 1, 'type': 'misspell', 'length': 2, 'start': 1} + let result = prop_find(#{type: 'misspell', skipstart: true}, 'f') + assert_equal(expected, result) + + prop_type_delete('misspell') + bwipe! +enddef + func Test_prop_find_smaller_len_than_match_col() new call prop_type_add('test', {'highlight': 'ErrorMsg'}) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 282d8dcec2..f79c2e0bdb 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1426,6 +1426,42 @@ def Test_setbufvar() settabwinvar(1, 1, '&ts', 15) assert_equal(15, &ts) setlocal ts=8 + + setbufvar('%', 'myvar', 123) + assert_equal(123, getbufvar('%', 'myvar')) +enddef + +def Test_bufwinid() + let origwin = win_getid() + below split SomeFile + let SomeFileID = win_getid() + below split OtherFile + below split SomeFile + assert_equal(SomeFileID, bufwinid('SomeFile')) + + win_gotoid(origwin) + only + bwipe SomeFile + bwipe OtherFile +enddef + +def Test_getbufline() + e SomeFile + let buf = bufnr() + e # + let lines = ['aaa', 'bbb', 'ccc'] + setbufline(buf, 1, lines) + assert_equal(lines, getbufline('#', 1, '$')) + + bwipe! +enddef + +def Test_getchangelist() + new + setline(1, 'some text') + let changelist = bufnr()->getchangelist() + assert_equal(changelist, getchangelist('%')) + bwipe! enddef def Test_setreg() @@ -1443,6 +1479,11 @@ def Test_bufname() close enddef +def Test_gebufinfo() + let bufinfo = getbufinfo(bufnr()) + assert_equal(bufinfo, getbufinfo('%')) +enddef + def Fibonacci(n: number): number if n < 2 return n @@ -1451,6 +1492,74 @@ def Fibonacci(n: number): number endif enddef +def Test_count() + assert_equal(3, count('ABC ABC ABC', 'b', true)) + assert_equal(0, count('ABC ABC ABC', 'b', false)) +enddef + +def Test_index() + assert_equal(3, index(['a', 'b', 'a', 'B'], 'b', 2, true)) +enddef + +def Test_expand() + split SomeFile + assert_equal(['SomeFile'], expand('%', true, true)) + close +enddef + +def Test_getreg() + let lines = ['aaa', 'bbb', 'ccc'] + setreg('a', lines) + assert_equal(lines, getreg('a', true, true)) +enddef + +def Test_glob() + assert_equal(['runtest.vim'], glob('runtest.vim', true, true, true)) +enddef + +def Test_globpath() + assert_equal(['./runtest.vim'], globpath('.', 'runtest.vim', true, true, true)) +enddef + +def Test_hasmapto() + assert_equal(0, hasmapto('foobar', 'i', true)) + iabbrev foo foobar + assert_equal(1, hasmapto('foobar', 'i', true)) + iunabbrev foo +enddef + +def SID(): number + return expand('') + ->matchstr('\zs\d\+\ze_$') + ->str2nr() +enddef + +def Test_maparg() + let lnum = str2nr(expand('')) + map foo bar + assert_equal(#{ + lnum: lnum + 1, + script: 0, + mode: ' ', + silent: 0, + noremap: 0, + lhs: 'foo', + lhsraw: 'foo', + nowait: 0, + expr: 0, + sid: SID(), + rhs: 'bar', + buffer: 0}, + maparg('foo', '', false, true)) + unmap foo +enddef + +def Test_mapcheck() + iabbrev foo foobar + assert_equal('foobar', mapcheck('foo', 'i', true)) + iunabbrev foo +enddef + def Test_recursive_call() assert_equal(6765, Fibonacci(20)) enddef diff --git a/src/textprop.c b/src/textprop.c index 0645e1fd70..beb9a273d0 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -645,9 +645,7 @@ f_prop_find(typval_T *argvars, typval_T *rettv) return; } - di = dict_find(dict, (char_u *)"skipstart", -1); - if (di != NULL) - skipstart = tv_get_number(&di->di_tv); + skipstart = dict_get_bool(dict, (char_u *)"skipstart", 0); if (dict_find(dict, (char_u *)"id", -1) != NULL) id = dict_get_number(dict, (char_u *)"id"); @@ -718,7 +716,7 @@ f_prop_find(typval_T *argvars, typval_T *rettv) // on a prop and we're not skipping. if (start_pos_has_prop && !skipstart) dir = -1; - break; + continue; } // If skipstart is true, skip the prop at start pos (even if @@ -726,7 +724,7 @@ f_prop_find(typval_T *argvars, typval_T *rettv) if (start_pos_has_prop && skipstart && !seen_end) { start_pos_has_prop = 0; - break; + continue; } prop_fill_dict(rettv->vval.v_dict, &prop, buf); diff --git a/src/typval.c b/src/typval.c index d1732f2b7c..db52d59730 100644 --- a/src/typval.c +++ b/src/typval.c @@ -283,7 +283,6 @@ tv_get_bool(typval_T *varp) tv_get_bool_chk(typval_T *varp, int *denote) { return tv_get_bool_or_number_chk(varp, denote, TRUE); - } #ifdef FEAT_FLOAT @@ -1562,4 +1561,23 @@ tv_get_buf(typval_T *tv, int curtab_only) return buf; } +/* + * Like tv_get_buf() but give an error message is the type is wrong. + */ + buf_T * +tv_get_buf_from_arg(typval_T *tv) +{ + buf_T *buf; + + ++emsg_off; + buf = tv_get_buf(tv, FALSE); + --emsg_off; + if (buf == NULL + && tv->v_type != VAR_NUMBER + && tv->v_type != VAR_STRING) + // issue errmsg for type error + (void)tv_get_number(tv); + return buf; +} + #endif // FEAT_EVAL diff --git a/src/ui.c b/src/ui.c index 6efb1a2f33..80b2962e51 100644 --- a/src/ui.c +++ b/src/ui.c @@ -972,6 +972,13 @@ fill_input_buf(int exit_on_error UNUSED) # else len = read(read_cmd_fd, (char *)inbuf + inbufcount, readlen); # endif +# ifdef FEAT_JOB_CHANNEL + if (len > 0) + { + inbuf[inbufcount + len] = NUL; + ch_log(NULL, "raw key input: \"%s\"", inbuf + inbufcount); + } +# endif if (len > 0 || got_int) break; diff --git a/src/version.c b/src/version.c index 2339dc5122..2fee5bf1e2 100644 --- a/src/version.c +++ b/src/version.c @@ -769,6 +769,72 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1584, +/**/ + 1583, +/**/ + 1582, +/**/ + 1581, +/**/ + 1580, +/**/ + 1579, +/**/ + 1578, +/**/ + 1577, +/**/ + 1576, +/**/ + 1575, +/**/ + 1574, +/**/ + 1573, +/**/ + 1572, +/**/ + 1571, +/**/ + 1570, +/**/ + 1569, +/**/ + 1568, +/**/ + 1567, +/**/ + 1566, +/**/ + 1565, +/**/ + 1564, +/**/ + 1563, +/**/ + 1562, +/**/ + 1561, +/**/ + 1560, +/**/ + 1559, +/**/ + 1558, +/**/ + 1557, +/**/ + 1556, +/**/ + 1555, +/**/ + 1554, +/**/ + 1553, +/**/ + 1552, /**/ 1551, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 0c9f56f5a0..5893e5ac0b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1147,7 +1147,10 @@ generate_NEWLIST(cctx_T *cctx, int count) isn->isn_arg.number = count; // get the member type from all the items on the stack. - member = get_member_type_from_stack( + if (count == 0) + member = &t_void; + else + member = get_member_type_from_stack( ((type_T **)stack->ga_data) + stack->ga_len, count, 1, cctx->ctx_type_list); type = get_list_type(member, cctx->ctx_type_list); @@ -1180,7 +1183,10 @@ generate_NEWDICT(cctx_T *cctx, int count) return FAIL; isn->isn_arg.number = count; - member = get_member_type_from_stack( + if (count == 0) + member = &t_void; + else + member = get_member_type_from_stack( ((type_T **)stack->ga_data) + stack->ga_len, count, 2, cctx->ctx_type_list); type = get_dict_type(member, cctx->ctx_type_list); diff --git a/src/viminfo.c b/src/viminfo.c index 74780c3d07..0ec9a13193 100644 --- a/src/viminfo.c +++ b/src/viminfo.c @@ -2183,7 +2183,8 @@ write_viminfo_filemarks(FILE *fp) xfmark_T *vi_fm; fm = idx >= 0 ? &curwin->w_jumplist[idx] : NULL; - vi_fm = vi_idx < vi_jumplist_len ? &vi_jumplist[vi_idx] : NULL; + vi_fm = (vi_jumplist != NULL && vi_idx < vi_jumplist_len) + ? &vi_jumplist[vi_idx] : NULL; if (fm == NULL && vi_fm == NULL) break; if (fm == NULL || (vi_fm != NULL && fm->time_set < vi_fm->time_set))