Merge remote-tracking branch 'vim/master'

This commit is contained in:
ichizok
2022-03-25 12:02:14 +09:00
63 changed files with 1033 additions and 510 deletions
+8
View File
@@ -3256,6 +3256,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
messages |:messages| suboptions
option options
packadd optional package |pack-add| names
scriptnames sourced script names |:scriptnames|
shellcmd Shell command
sign |:sign| suboptions
syntax syntax file names |'syntax'|
@@ -3273,6 +3274,13 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
is applied to filter the results. Otherwise all the matches
are returned. The 'wildignorecase' option always applies.
If the 'wildoptions' option contains 'fuzzy', then fuzzy
matching is used to get the completion matches. Otherwise
regular expression matching is used. Thus this function
follows the user preference, what happens on the command line.
If you do not want this you can make 'wildoptions' empty
before calling getcompletion() and restore it afterwards.
If {type} is "cmdline", then the |cmdline-completion| result is
returned. For example, to complete the possible values after
a ":call" command: >
+33 -8
View File
@@ -198,10 +198,35 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
start with a ":".
Triggers the |SourcePre| autocommand.
:[range]so[urce] Read Ex commands from the [range] of lines in the
current buffer. When sourcing commands from the
current buffer, the same script-ID |<SID>| is used
even if the buffer is sourced multiple times.
:[range]so[urce] [++clear]
Read Ex commands from the [range] of lines in the
current buffer.
When sourcing commands from the current buffer, the
same script-ID |<SID>| is used even if the buffer is
sourced multiple times. If a buffer is sourced more
than once, then the functions in the buffer are
defined again.
To source a range of lines that doesn't start with the
|:vim9script| command in Vim9 script context, the
|:vim9cmd| modifier can be used.
When a range of lines in a buffer is sourced in the
Vim9 script context, the previously defined
script-local variables and functions are not cleared.
This works like the range started with the
":vim9script noclear" command. The "++clear" argument
can be used to clear the script-local variables and
functions before sourcing the script. This works like
the range started with the |:vimscript| command
without the "noclear" argument. See |vim9-reload| for
more information.
Examples: >
:4,5source
:vim9cmd :'<,'>source
:10,18source ++clear
*:source!*
:so[urce]! {file} Read Vim commands from {file}. These are commands
@@ -425,10 +450,10 @@ An alternative is to put the commands in a file, and execute them with the
':source!' command. Useful for long command sequences. Can be combined with
the ':map' command to put complicated commands under a function key.
The ':source' command reads Ex commands from a file line by line. You will
have to type any needed keyboard input. The ':source!' command reads from a
script file character by character, interpreting each character as if you
typed it.
The ':source' command reads Ex commands from a file or a buffer line by line.
You will have to type any needed keyboard input. The ':source!' command reads
from a script file character by character, interpreting each character as if
you typed it.
Example: When you give the ":!ls" command you get the |hit-enter| prompt. If
you ':source' a file with the line "!ls" in it, you will have to type the
+14 -10
View File
@@ -5340,17 +5340,21 @@ ex_buffer_all(exarg_T *eap)
{
wpnext = wp->w_next;
if ((wp->w_buffer->b_nwindows > 1
|| ((cmdmod.cmod_split & WSP_VERT)
? wp->w_height + wp->w_status_height < Rows - p_ch
- tabline_height()
: wp->w_width != Columns)
|| (had_tab > 0 && wp != firstwin)) && !ONE_WINDOW
&& !(wp->w_closing || wp->w_buffer->b_locked > 0))
|| ((cmdmod.cmod_split & WSP_VERT)
? wp->w_height + wp->w_status_height < Rows - p_ch
- tabline_height()
: wp->w_width != Columns)
|| (had_tab > 0 && wp != firstwin))
&& !ONE_WINDOW
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)
&& !win_unlisted(wp))
{
win_close(wp, FALSE);
wpnext = firstwin; // just in case an autocommand does
// something strange with windows
tpnext = first_tabpage; // start all over...
if (win_close(wp, FALSE) == FAIL)
break;
// Just in case an autocommand does something strange with
// windows: start all over...
wpnext = firstwin;
tpnext = first_tabpage;
open_wins = 0;
}
else
+3 -3
View File
@@ -422,7 +422,7 @@ cmdsrv_main(
* For --remote-wait: Wait until the server did edit each
* file. Also detect that the server no longer runs.
*/
if (ret >= 0 && argtype == ARGTYPE_EDIT_WAIT)
if (argtype == ARGTYPE_EDIT_WAIT)
{
int numFiles = *argc - i - 1;
int j;
@@ -801,6 +801,7 @@ f_remote_expr(typval_T *argvars UNUSED, typval_T *rettv)
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
#ifdef FEAT_CLIENTSERVER
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| check_for_string_arg(argvars, 1) == FAIL
@@ -809,7 +810,6 @@ f_remote_expr(typval_T *argvars UNUSED, typval_T *rettv)
&& check_for_opt_number_arg(argvars, 3) == FAIL)))
return;
#ifdef FEAT_CLIENTSERVER
remote_common(argvars, rettv, TRUE);
#endif
}
@@ -956,13 +956,13 @@ f_remote_send(typval_T *argvars UNUSED, typval_T *rettv)
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
#ifdef FEAT_CLIENTSERVER
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
|| check_for_string_arg(argvars, 1) == FAIL
|| check_for_opt_string_arg(argvars, 2) == FAIL))
return;
#ifdef FEAT_CLIENTSERVER
remote_common(argvars, rettv, FALSE);
#endif
}
+64 -16
View File
@@ -1709,6 +1709,24 @@ set_context_in_breakadd_cmd(expand_T *xp, char_u *arg, cmdidx_T cmdidx)
return NULL;
}
static char_u *
set_context_in_scriptnames_cmd(expand_T *xp, char_u *arg)
{
char_u *p;
xp->xp_context = EXPAND_NOTHING;
xp->xp_pattern = NULL;
p = skipwhite(arg);
if (VIM_ISDIGIT(*p))
return NULL;
xp->xp_context = EXPAND_SCRIPTNAMES;
xp->xp_pattern = p;
return NULL;
}
#endif
/*
@@ -2081,6 +2099,9 @@ set_context_by_cmdname(
case CMD_profdel:
case CMD_breakdel:
return set_context_in_breakadd_cmd(xp, arg, cmdidx);
case CMD_scriptnames:
return set_context_in_scriptnames_cmd(xp, arg);
#endif
default:
@@ -2504,6 +2525,23 @@ get_breakadd_arg(expand_T *xp UNUSED, int idx)
}
return NULL;
}
/*
* Function given to ExpandGeneric() to obtain the possible arguments for the
* ":scriptnames" command.
*/
static char_u *
get_scriptnames_arg(expand_T *xp UNUSED, int idx)
{
scriptitem_T *si;
if (!SCRIPT_ID_VALID(idx + 1))
return NULL;
si = SCRIPT_ITEM(idx + 1);
home_replace(NULL, si->sn_name, NameBuff, MAXPATHL, TRUE);
return NameBuff;
}
#endif
/*
@@ -2593,6 +2631,7 @@ ExpandOther(
{EXPAND_ARGLIST, get_arglist_name, TRUE, FALSE},
#ifdef FEAT_EVAL
{EXPAND_BREAKPOINT, get_breakadd_arg, TRUE, TRUE},
{EXPAND_SCRIPTNAMES, get_scriptnames_arg, TRUE, FALSE},
#endif
#ifdef FEAT_GUI_MACVIM
{EXPAND_MACACTION, get_macaction_name, FALSE, FALSE},
@@ -2803,6 +2842,8 @@ ExpandGeneric(
int score = 0;
int fuzzy;
int match;
int sort_matches = FALSE;
int funcsort = FALSE;
fuzzy = cmdline_fuzzy_complete(pat);
*matches = NULL;
@@ -2890,14 +2931,25 @@ ExpandGeneric(
if (ga.ga_len == 0)
return OK;
// Sort the results. Keep menu's in the specified order.
// sort the matches when using regular expression matching and sorting
// applies to the completion context. Menus and scriptnames should be kept
// in the specified order.
if (!fuzzy && xp->xp_context != EXPAND_MENUNAMES
&& xp->xp_context != EXPAND_MENUS)
&& xp->xp_context != EXPAND_MENUS
&& xp->xp_context != EXPAND_SCRIPTNAMES)
sort_matches = TRUE;
// <SNR> functions should be sorted to the end.
if (xp->xp_context == EXPAND_EXPRESSION
|| xp->xp_context == EXPAND_FUNCTIONS
|| xp->xp_context == EXPAND_USER_FUNC
|| xp->xp_context == EXPAND_DISASSEMBLE)
funcsort = TRUE;
// Sort the matches.
if (sort_matches)
{
if (xp->xp_context == EXPAND_EXPRESSION
|| xp->xp_context == EXPAND_FUNCTIONS
|| xp->xp_context == EXPAND_USER_FUNC
|| xp->xp_context == EXPAND_DISASSEMBLE)
if (funcsort)
// <SNR> functions should be sorted to the end.
qsort((void *)ga.ga_data, (size_t)ga.ga_len, sizeof(char_u *),
sort_func_compare);
@@ -2912,15 +2964,6 @@ ExpandGeneric(
}
else
{
int funcsort = FALSE;
if (xp->xp_context == EXPAND_EXPRESSION
|| xp->xp_context == EXPAND_FUNCTIONS
|| xp->xp_context == EXPAND_USER_FUNC
|| xp->xp_context == EXPAND_DISASSEMBLE)
// <SNR> functions should be sorted to the end.
funcsort = TRUE;
if (fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len,
funcsort) == FAIL)
return FAIL;
@@ -3719,7 +3762,12 @@ f_getcompletion(typval_T *argvars, typval_T *rettv)
# endif
}
pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
if (cmdline_fuzzy_completion_supported(&xpc))
// when fuzzy matching, don't modify the search string
pat = vim_strsave(xpc.xp_pattern);
else
pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
if ((rettv_list_alloc(rettv) != FAIL) && (pat != NULL))
{
int i;
+2 -8
View File
@@ -945,8 +945,7 @@ win_line(
if (wp->w_p_cul && lnum == wp->w_cursor.lnum)
{
// Do not show the cursor line in the text when Visual mode is active,
// because it's not clear what is selected then. Do update
// w_last_cursorline.
// because it's not clear what is selected then.
if (!(wp == curwin && VIsual_active)
&& wp->w_p_culopt_flags != CULOPT_NBR)
{
@@ -971,18 +970,14 @@ win_line(
else
# endif
line_attr = cul_attr;
wp->w_last_cursorline = wp->w_cursor.lnum;
}
else
{
line_attr_save = line_attr;
wp->w_last_cursorline = 0;
margin_columns_win(wp, &left_curline_col, &right_curline_col);
}
area_highlighting = TRUE;
}
else
wp->w_last_cursorline = wp->w_cursor.lnum;
}
#endif
@@ -1226,8 +1221,7 @@ win_line(
{
draw_state = WL_BRI;
// if need_showbreak is set, breakindent also applies
if (wp->w_p_bri && n_extra == 0
&& (row != startrow || need_showbreak)
if (wp->w_p_bri && (row != startrow || need_showbreak)
# ifdef FEAT_DIFF
&& filler_lines == 0
# endif
+10 -8
View File
@@ -1468,9 +1468,6 @@ win_update(win_T *wp)
# define DID_FOLD 3 // updated a folded line
int did_update = DID_NONE;
linenr_T syntax_last_parsed = 0; // last parsed text line
// remember the current w_last_cursorline, it changes when drawing the new
// cursor line
linenr_T last_cursorline = wp->w_last_cursorline;
#endif
linenr_T mod_top = 0;
linenr_T mod_bot = 0;
@@ -1950,9 +1947,8 @@ win_update(win_T *wp)
if (VIsual_active)
{
if (VIsual_active
&& (VIsual_mode != wp->w_old_visual_mode
|| type == INVERTED_ALL))
if (VIsual_mode != wp->w_old_visual_mode
|| type == INVERTED_ALL)
{
// If the type of Visual selection changed, redraw the whole
// selection. Also when the ownership of the X selection is
@@ -2246,8 +2242,8 @@ win_update(win_T *wp)
#endif
))))
#ifdef FEAT_SYN_HL
|| (wp->w_p_cul && (lnum == wp->w_cursor.lnum
|| lnum == last_cursorline))
|| (wp->w_p_cul && lnum == wp->w_cursor.lnum)
|| lnum == wp->w_last_cursorline
#endif
)
{
@@ -2552,6 +2548,12 @@ win_update(win_T *wp)
// End of loop over all window lines.
#ifdef FEAT_SYN_HL
// Now that the window has been redrawn with the old and new cursor line,
// update w_last_cursorline.
wp->w_last_cursorline = wp->w_p_cul ? wp->w_cursor.lnum : 0;
#endif
#ifdef FEAT_VTP
// Rewrite the character at the end of the screen line.
// See the version that was fixed.
+1 -1
View File
@@ -2720,7 +2720,7 @@ EXTERN char e_cannot_use_scriptversion_after_vim9script[]
INIT(= N_("E1040: Cannot use :scriptversion after :vim9script"));
#ifdef FEAT_EVAL
EXTERN char e_redefining_script_item_str[]
INIT(= N_("E1041: Redefining script item %s"));
INIT(= N_("E1041: Redefining script item: \"%s\""));
EXTERN char e_export_can_only_be_used_in_vim9script[]
INIT(= N_("E1042: Export can only be used in vim9script"));
EXTERN char e_invalid_command_after_export[]
+1 -2
View File
@@ -2411,8 +2411,7 @@ getfile(
if (curbufIsChanged())
#endif
{
if (other)
--no_wait_return;
--no_wait_return;
no_write_message();
retval = GETFILE_NOT_WRITTEN; // file has been changed
goto theend;
+1 -1
View File
@@ -1362,7 +1362,7 @@ EXCMD(CMD_sbrewind, "sbrewind", ex_brewind,
EX_CMDARG|EX_TRLBAR,
ADDR_NONE),
EXCMD(CMD_scriptnames, "scriptnames", ex_scriptnames,
EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
EX_BANG|EX_FILES|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
ADDR_OTHER),
EXCMD(CMD_scriptencoding, "scriptencoding", ex_scriptencoding,
EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
+50 -31
View File
@@ -2281,7 +2281,7 @@ do_one_cmd(
*/
if ((ea.argt & EX_TRLBAR) && !ea.usefilter)
{
separate_nextcmd(&ea);
separate_nextcmd(&ea, FALSE);
}
else if (ea.cmdidx == CMD_bang
|| ea.cmdidx == CMD_terminal
@@ -2578,7 +2578,7 @@ do_one_cmd(
#ifdef FEAT_EVAL
// Set flag that any command was executed, used by ex_vim9script().
// Not if this was a command that wasn't executed or :endif.
if (getline_equal(ea.getline, ea.cookie, getsourceline)
if (sourcing_a_script(&ea)
&& current_sctx.sc_sid > 0
&& ea.cmdidx != CMD_endif
&& (cstack->cs_idx < 0
@@ -3426,6 +3426,38 @@ skip_option_env_lead(char_u *start)
}
#endif
/*
* Return TRUE and set "*idx" if "p" points to a one letter command.
* If not in Vim9 script:
* - The 'k' command can directly be followed by any character.
* - The 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
* but :sre[wind] is another command, as are :scr[iptnames],
* :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
*/
static int
one_letter_cmd(char_u *p, cmdidx_T *idx)
{
if (in_vim9script())
return FALSE;
if (*p == 'k')
{
*idx = CMD_k;
return TRUE;
}
if (p[0] == 's'
&& ((p[1] == 'c' && (p[2] == NUL || (p[2] != 's' && p[2] != 'r'
&& (p[3] == NUL || (p[3] != 'i' && p[4] != 'p')))))
|| p[1] == 'g'
|| (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
|| p[1] == 'I'
|| (p[1] == 'r' && p[2] != 'e')))
{
*idx = CMD_substitute;
return TRUE;
}
return FALSE;
}
/*
* Find an Ex command by its name, either built-in or user.
* Start of the name can be found at eap->cmd.
@@ -3660,30 +3692,10 @@ find_ex_command(
/*
* Isolate the command and search for it in the command table.
* Exceptions:
* - The 'k' command can directly be followed by any character.
* But it is not used in Vim9 script.
* - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
* but :sre[wind] is another command, as are :scr[iptnames],
* :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
* - the "d" command can directly be followed by 'l' or 'p' flag.
*/
p = eap->cmd;
if (!vim9 && *p == 'k')
if (one_letter_cmd(p, &eap->cmdidx))
{
eap->cmdidx = CMD_k;
++p;
}
else if (!vim9
&& p[0] == 's'
&& ((p[1] == 'c' && (p[2] == NUL || (p[2] != 's' && p[2] != 'r'
&& (p[3] == NUL || (p[3] != 'i' && p[4] != 'p')))))
|| p[1] == 'g'
|| (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
|| p[1] == 'I'
|| (p[1] == 'r' && p[2] != 'e')))
{
eap->cmdidx = CMD_substitute;
++p;
}
else
@@ -3708,6 +3720,8 @@ find_ex_command(
if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#}", *p) != NULL)
++p;
len = (int)(p - eap->cmd);
// The "d" command can directly be followed by 'l' or 'p' flag, when
// not in Vim9 script.
if (!vim9 && *eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p'))
{
// Check for ":dl", ":dell", etc. to ":deletel": that's
@@ -3961,10 +3975,11 @@ excmd_get_cmdidx(char_u *cmd, int len)
{
cmdidx_T idx;
for (idx = (cmdidx_T)0; (int)idx < (int)CMD_SIZE;
idx = (cmdidx_T)((int)idx + 1))
if (STRNCMP(cmdnames[(int)idx].cmd_name, cmd, (size_t)len) == 0)
break;
if (!one_letter_cmd(cmd, &idx))
for (idx = (cmdidx_T)0; (int)idx < (int)CMD_SIZE;
idx = (cmdidx_T)((int)idx + 1))
if (STRNCMP(cmdnames[(int)idx].cmd_name, cmd, (size_t)len) == 0)
break;
return idx;
}
@@ -5087,9 +5102,10 @@ repl_cmdline(
/*
* Check for '|' to separate commands and '"' to start comments.
* If "keep_backslash" is TRUE do not remove any backslash.
*/
void
separate_nextcmd(exarg_T *eap)
separate_nextcmd(exarg_T *eap, int keep_backslash)
{
char_u *p;
@@ -5103,7 +5119,7 @@ separate_nextcmd(exarg_T *eap)
{
if (*p == Ctrl_V)
{
if (eap->argt & (EX_CTRLV | EX_XFILE))
if ((eap->argt & (EX_CTRLV | EX_XFILE)) || keep_backslash)
++p; // skip CTRL-V and next char
else
// remove CTRL-V and skip next char
@@ -5150,8 +5166,11 @@ separate_nextcmd(exarg_T *eap)
if ((vim_strchr(p_cpo, CPO_BAR) == NULL
|| !(eap->argt & EX_CTRLV)) && *(p - 1) == '\\')
{
STRMOVE(p - 1, p); // remove the '\'
--p;
if (!keep_backslash)
{
STRMOVE(p - 1, p); // remove the '\'
--p;
}
}
else
{
+1 -1
View File
@@ -4974,7 +4974,7 @@ readdir_core(
break;
}
if (!ignore && checkitem != NULL)
if (checkitem != NULL)
{
int r = checkitem(context, item);
+3
View File
@@ -736,6 +736,9 @@ EXTERN win_T *popup_dragwin INIT(= NULL); // popup window being dragged
// Set to TRUE if there is any visible popup window.
EXTERN int popup_visible INIT(= FALSE);
// Set to TRUE if a visible popup window may use a MOUSE_MOVE event
EXTERN int popup_uses_mouse_move INIT(= FALSE);
EXTERN int text_prop_frozen INIT(= 0);
#endif
+1 -1
View File
@@ -5008,7 +5008,7 @@ gui_mouse_moved(int x, int y)
gui_mouse_focus(x, y);
#ifdef FEAT_PROP_POPUP
if (popup_visible)
if (popup_uses_mouse_move)
// Generate a mouse-moved event, so that the popup can perhaps be
// closed, just like in the terminal.
gui_send_mouse_event(MOUSE_MOVE, x, y, FALSE, 0);
+6 -6
View File
@@ -142,12 +142,12 @@ tabline_button_cb(
XtPointer client_data UNUSED,
XtPointer call_data UNUSED)
{
int cmd, tab_idx;
XtPointer cmd, tab_idx;
XtVaGetValues(w, XmNuserData, &cmd, NULL);
XtVaGetValues(tabLine_menu, XmNuserData, &tab_idx, NULL);
send_tabline_menu_event(tab_idx, cmd);
send_tabline_menu_event((int)(long)tab_idx, (int)(long)cmd);
}
/*
@@ -254,7 +254,7 @@ tabline_menu_cb(
XtVaGetValues(tab_w, XmNpageNumber, &tab_idx, NULL);
}
XtVaSetValues(tabLine_menu, XmNuserData, tab_idx, NULL);
XtVaSetValues(tabLine_menu, XmNuserData, (XtPointer)(long)tab_idx, NULL);
XtVaGetValues(tabLine_menu, XmNchildren, &children, XmNnumChildren,
&numChildren, NULL);
XtManageChildren(children, numChildren);
@@ -517,7 +517,7 @@ gui_x11_create_widgets(void)
// Add the buttons to the tabline popup menu
n = 0;
XtSetArg(args[n], XmNuserData, TABLINE_MENU_CLOSE); n++;
XtSetArg(args[n], XmNuserData, (XtPointer)TABLINE_MENU_CLOSE); n++;
xms = XmStringCreate((char *)"Close tab", STRING_TAG);
XtSetArg(args[n], XmNlabelString, xms); n++;
button = XmCreatePushButton(tabLine_menu, "Close", args, n);
@@ -526,7 +526,7 @@ gui_x11_create_widgets(void)
XmStringFree(xms);
n = 0;
XtSetArg(args[n], XmNuserData, TABLINE_MENU_NEW); n++;
XtSetArg(args[n], XmNuserData, (XtPointer)TABLINE_MENU_NEW); n++;
xms = XmStringCreate((char *)"New Tab", STRING_TAG);
XtSetArg(args[n], XmNlabelString, xms); n++;
button = XmCreatePushButton(tabLine_menu, "New Tab", args, n);
@@ -535,7 +535,7 @@ gui_x11_create_widgets(void)
XmStringFree(xms);
n = 0;
XtSetArg(args[n], XmNuserData, TABLINE_MENU_OPEN); n++;
XtSetArg(args[n], XmNuserData, (XtPointer)TABLINE_MENU_OPEN); n++;
xms = XmStringCreate((char *)"Open tab...", STRING_TAG);
XtSetArg(args[n], XmNlabelString, xms); n++;
button = XmCreatePushButton(tabLine_menu, "Open tab...", args, n);
+1 -1
View File
@@ -2261,7 +2261,7 @@ swapfile_info(char_u *fname)
* Return TRUE if the swap file looks OK and there are no changes, thus it can
* be safely deleted.
*/
static time_t
static int
swapfile_unchanged(char_u *fname)
{
stat_T st;
+1 -1
View File
@@ -1808,7 +1808,7 @@ str2special(
int len = (*mb_ptr2len)(str);
// For multi-byte characters check for an illegal byte.
if (has_mbyte && MB_BYTE2LEN(*str) > len)
if (MB_BYTE2LEN(*str) > len)
{
transchar_nonprint(curbuf, buf, c);
*sp = str + 1;
+1 -1
View File
@@ -596,7 +596,7 @@ check_cursor_col_win(win_T *win)
// Make sure that coladd is not more than the char width.
// Not for the last character, coladd is then used when the cursor
// is actually after the last character.
if (win->w_cursor.col + 1 < len && win->w_cursor.coladd > 0)
if (win->w_cursor.col + 1 < len)
{
int cs, ce;
+2 -26
View File
@@ -115,14 +115,6 @@ comp_botline(win_T *wp)
set_empty_rows(wp, done);
}
#ifdef FEAT_SYN_HL
void
reset_cursorline(void)
{
curwin->w_last_cursorline = 0;
}
#endif
/*
* Redraw when w_cline_row changes and 'relativenumber' or 'cursorline' is
* set.
@@ -138,24 +130,8 @@ redraw_for_cursorline(win_T *wp)
&& (wp->w_valid & VALID_CROW) == 0
&& !pum_visible())
{
if (wp->w_p_rnu)
// win_line() will redraw the number column only.
redraw_win_later(wp, VALID);
#ifdef FEAT_SYN_HL
if (wp->w_p_cul)
{
if (wp->w_redr_type <= VALID && wp->w_last_cursorline != 0)
{
// "w_last_cursorline" may be outdated, worst case we redraw
// too much. This is optimized for moving the cursor around in
// the current window.
redrawWinline(wp, wp->w_last_cursorline);
redrawWinline(wp, wp->w_cursor.lnum);
}
else
redraw_win_later(wp, SOME_VALID);
}
#endif
// win_line() will redraw the number column and cursorline only.
redraw_win_later(wp, VALID);
}
}
+1 -1
View File
@@ -1310,7 +1310,7 @@ op_tilde(oparg_T *oap)
changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1,
0L);
#ifdef FEAT_NETBEANS_INTG
if (netbeans_active() && did_change)
if (netbeans_active())
{
char_u *ptr;
int count;
-5
View File
@@ -2804,11 +2804,6 @@ set_bool_option(
p_lrm = !p_lnr;
#endif
#ifdef FEAT_SYN_HL
else if ((int *)varp == &curwin->w_p_cul && !value && old_value)
reset_cursorline();
#endif
#ifdef FEAT_PERSISTENT_UNDO
// 'undofile'
else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf)
+26 -1
View File
@@ -150,6 +150,29 @@ set_mousemoved_values(win_T *wp)
wp->w_popup_mouse_maxcol = mouse_col;
}
static void
update_popup_uses_mouse_move(void)
{
popup_uses_mouse_move = FALSE;
if (popup_visible)
{
win_T *wp;
FOR_ALL_POPUPWINS(wp)
if (wp->w_popup_mouse_row != 0)
{
popup_uses_mouse_move = TRUE;
return;
}
FOR_ALL_POPUPWINS_IN_TAB(curtab, wp)
if (wp->w_popup_mouse_row != 0)
{
popup_uses_mouse_move = TRUE;
return;
}
}
}
/*
* Used when popup options contain "moved" with "word" or "WORD".
*/
@@ -3586,7 +3609,7 @@ popup_need_position_adjust(win_T *wp)
/*
* Update "popup_mask" if needed.
* Also recomputes the popup size and positions.
* Also updates "popup_visible".
* Also updates "popup_visible" and "popup_uses_mouse_move".
* Also marks window lines for redrawing.
*/
void
@@ -3755,6 +3778,8 @@ may_update_popup_mask(int type)
vim_free(plines_cache);
}
update_popup_uses_mouse_move();
}
/*
+1 -1
View File
@@ -26,7 +26,7 @@ long excmd_get_argt(cmdidx_T idx);
char_u *skip_range(char_u *cmd_start, int skip_star, int *ctx);
void ex_ni(exarg_T *eap);
int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp);
void separate_nextcmd(exarg_T *eap);
void separate_nextcmd(exarg_T *eap, int keep_backslash);
char_u *skip_cmd_arg(char_u *p, int rembs);
int get_bad_opt(char_u *p, exarg_T *eap);
int ends_excmd(int c);
-1
View File
@@ -1,5 +1,4 @@
/* move.c */
void reset_cursorline(void);
void redraw_for_cursorline(win_T *wp);
void update_topline_redraw(void);
void update_topline(void);
+1 -1
View File
@@ -32,6 +32,7 @@ void free_scriptnames(void);
void free_autoload_scriptnames(void);
linenr_T get_sourced_lnum(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
char_u *getsourceline(int c, void *cookie, int indent, getline_opt_T options);
int sourcing_a_script(exarg_T *eap);
void ex_scriptencoding(exarg_T *eap);
void ex_scriptversion(exarg_T *eap);
void ex_finish(exarg_T *eap);
@@ -42,5 +43,4 @@ char_u *get_autoload_prefix(scriptitem_T *si);
char_u *may_prefix_autoload(char_u *name);
char_u *autoload_name(char_u *name);
int script_autoload(char_u *name, int reload);
int sourcing_a_script(exarg_T *eap);
/* vim: set ft=c : */
+1 -1
View File
@@ -38,7 +38,7 @@ int generate_OLDSCRIPT(cctx_T *cctx, isntype_T isn_type, char_u *name, int sid,
int generate_VIM9SCRIPT(cctx_T *cctx, isntype_T isn_type, int sid, int idx, type_T *type);
int generate_NEWLIST(cctx_T *cctx, int count);
int generate_NEWDICT(cctx_T *cctx, int count);
int generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc);
int generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc, isn_T **isnp);
int generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name);
int generate_DEF(cctx_T *cctx, char_u *name, size_t len);
int generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where);
+1
View File
@@ -2,6 +2,7 @@
int in_vim9script(void);
int in_old_script(int max_version);
int current_script_is_vim9(void);
void clear_vim9_scriptlocal_vars(int sid);
void ex_vim9script(exarg_T *eap);
int not_in_vim9(exarg_T *eap);
int vim9_bad_comment(char_u *p);
+1
View File
@@ -46,6 +46,7 @@ win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, int left, long count);
void win_enter(win_T *wp, int undo_sync);
win_T *buf_jump_open_win(buf_T *buf);
win_T *buf_jump_open_tab(buf_T *buf);
int win_unlisted(win_T *wp);
void win_free_popup(win_T *win);
void win_remove(win_T *wp, tabpage_T *tp);
int win_alloc_lines(win_T *wp);
+180 -296
View File
@@ -23,6 +23,8 @@ static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
static int last_current_SID_seq = 0;
#endif
static int do_source_ext(char_u *fname, int check_other, int is_vimrc, int *ret_sid, exarg_T *eap, int clearvars);
/*
* Initialize the execution stack.
*/
@@ -1079,254 +1081,23 @@ ExpandPackAddDir(
return OK;
}
/*
* Cookie used to source Ex commands from a buffer.
*/
typedef struct
{
garray_T lines_to_source;
int lnum;
linenr_T sourcing_lnum;
} bufline_cookie_T;
/*
* Concatenate a Vim script line if it starts with a line continuation into a
* growarray (excluding the continuation chars and leading whitespace).
* Growsize of the growarray may be changed to speed up concatenations!
*
* Returns TRUE if this line did begin with a continuation (the next line
* should also be considered, if it exists); FALSE otherwise.
*/
static int
concat_continued_line(
garray_T *ga,
int init_growsize,
char_u *nextline,
int options)
{
int comment_char = in_vim9script() ? '#' : '"';
char_u *p = skipwhite(nextline);
int contline;
int do_vim9_all = in_vim9script()
&& options == GETLINE_CONCAT_ALL;
int do_bar_cont = do_vim9_all
|| options == GETLINE_CONCAT_CONTBAR;
if (*p == NUL)
return FALSE;
// Concatenate the next line when it starts with a backslash.
/* Also check for a comment in between continuation lines: "\ */
// Also check for a Vim9 comment, empty line, line starting with '|',
// but not "||".
if ((p[0] == comment_char && p[1] == '\\' && p[2] == ' ')
|| (do_vim9_all && (*p == NUL
|| vim9_comment_start(p))))
return TRUE;
contline = (*p == '\\' || (do_bar_cont && p[0] == '|' && p[1] != '|'));
if (!contline)
return FALSE;
// Adjust the growsize to the current length to speed up concatenating many
// lines.
if (ga->ga_len > init_growsize)
ga->ga_growsize = ga->ga_len > 8000 ? 8000 : ga->ga_len;
if (*p == '\\')
ga_concat(ga, (char_u *)p + 1);
else if (*p == '|')
{
ga_concat(ga, (char_u *)" ");
ga_concat(ga, p);
}
return TRUE;
}
/*
* Get one full line from a sourced string (in-memory, no file).
* Called by do_cmdline() when it's called from source_using_linegetter().
*
* Returns a pointer to allocated line, or NULL for end-of-file.
*/
static char_u *
source_getbufline(
int c UNUSED,
void *cookie,
int indent UNUSED,
getline_opt_T opts)
{
bufline_cookie_T *p = cookie;
char_u *line;
garray_T ga;
SOURCING_LNUM = p->sourcing_lnum + 1;
if (p->lnum >= p->lines_to_source.ga_len)
return NULL;
line = ((char_u **)p->lines_to_source.ga_data)[p->lnum];
ga_init2(&ga, sizeof(char_u), 400);
ga_concat(&ga, (char_u *)line);
p->lnum++;
if ((opts != GETLINE_NONE) && vim_strchr(p_cpo, CPO_CONCAT) == NULL)
{
while (p->lnum < p->lines_to_source.ga_len)
{
line = ((char_u **)p->lines_to_source.ga_data)[p->lnum];
if (!concat_continued_line(&ga, 400, line, opts))
break;
p->sourcing_lnum++;
p->lnum++;
}
}
ga_append(&ga, NUL);
p->sourcing_lnum++;
return ga.ga_data;
}
/*
* Source Ex commands from the lines in 'cookie'.
*/
static int
do_sourcebuffer(
void *cookie,
char_u *scriptname)
{
char_u *save_sourcing_name = SOURCING_NAME;
linenr_T save_sourcing_lnum = SOURCING_LNUM;
char_u sourcing_name_buf[256];
sctx_T save_current_sctx;
#ifdef FEAT_EVAL
int sid;
funccal_entry_T funccalp_entry;
int save_estack_compiling = estack_compiling;
scriptitem_T *si = NULL;
#endif
int save_sticky_cmdmod_flags = sticky_cmdmod_flags;
int retval = FAIL;
ESTACK_CHECK_DECLARATION
if (save_sourcing_name == NULL)
SOURCING_NAME = (char_u *)scriptname;
else
{
vim_snprintf((char *)sourcing_name_buf, sizeof(sourcing_name_buf),
"%s called at %s:%ld", scriptname, save_sourcing_name,
save_sourcing_lnum);
SOURCING_NAME = sourcing_name_buf;
}
SOURCING_LNUM = 0;
// Keep the sourcing name/lnum, for recursive calls.
estack_push(ETYPE_SCRIPT, scriptname, 0);
ESTACK_CHECK_SETUP
// "legacy" does not apply to commands in the script
sticky_cmdmod_flags = 0;
save_current_sctx = current_sctx;
current_sctx.sc_version = 1; // default script version
#ifdef FEAT_EVAL
estack_compiling = FALSE;
// Always use a new sequence number.
current_sctx.sc_seq = ++last_current_SID_seq;
current_sctx.sc_lnum = save_sourcing_lnum;
save_funccal(&funccalp_entry);
sid = find_script_by_name(scriptname);
if (sid < 0)
{
int error = OK;
// First time sourcing this buffer, create a new script item.
sid = get_new_scriptitem(&error);
if (error == FAIL)
goto theend;
current_sctx.sc_sid = sid;
si = SCRIPT_ITEM(current_sctx.sc_sid);
si->sn_name = vim_strsave(scriptname);
si->sn_state = SN_STATE_NEW;
}
else
{
// the buffer was sourced previously, reuse the script ID.
current_sctx.sc_sid = sid;
si = SCRIPT_ITEM(current_sctx.sc_sid);
si->sn_state = SN_STATE_RELOAD;
}
#endif
retval = do_cmdline(NULL, source_getbufline, cookie,
DOCMD_VERBOSE | DOCMD_NOWAIT | DOCMD_REPEAT);
if (got_int)
emsg(_(e_interrupted));
#ifdef FEAT_EVAL
theend:
#endif
ESTACK_CHECK_NOW
estack_pop();
current_sctx = save_current_sctx;
SOURCING_LNUM = save_sourcing_lnum;
SOURCING_NAME = save_sourcing_name;
sticky_cmdmod_flags = save_sticky_cmdmod_flags;
#ifdef FEAT_EVAL
restore_funccal();
estack_compiling = save_estack_compiling;
#endif
return retval;
}
/*
* :source Ex commands from the current buffer
*/
static void
cmd_source_buffer(exarg_T *eap)
{
char_u *line = NULL;
linenr_T curr_lnum;
bufline_cookie_T cp;
char_u sname[32];
if (curbuf == NULL)
return;
// Use ":source buffer=<num>" as the script name
vim_snprintf((char *)sname, sizeof(sname), ":source buffer=%d",
curbuf->b_fnum);
ga_init2(&cp.lines_to_source, sizeof(char_u *), 100);
// Copy the lines from the buffer into a grow array
for (curr_lnum = eap->line1; curr_lnum <= eap->line2; curr_lnum++)
{
line = vim_strsave(ml_get(curr_lnum));
if (line == NULL)
goto errret;
if (ga_add_string(&cp.lines_to_source, line) == FAIL)
goto errret;
line = NULL;
}
cp.sourcing_lnum = 0;
cp.lnum = 0;
// Execute the Ex commands
do_sourcebuffer((void *)&cp, (char_u *)sname);
errret:
vim_free(line);
ga_clear_strings(&cp.lines_to_source);
}
static void
cmd_source(char_u *fname, exarg_T *eap)
{
int clearvars = FALSE;
if (*fname != NUL && STRNCMP(fname, "++clear", 7) == 0)
{
// ++clear argument is supplied
clearvars = TRUE;
fname = fname + 7;
if (*fname != NUL)
{
semsg(_(e_invalid_argument_str), eap->arg);
return;
}
}
if (*fname != NUL && eap != NULL && eap->addr_count > 0)
{
// if a filename is specified to :source, then a range is not allowed
@@ -1341,7 +1112,7 @@ cmd_source(char_u *fname, exarg_T *eap)
emsg(_(e_argument_required));
else
// source ex commands from the current buffer
cmd_source_buffer(eap);
do_source_ext(NULL, FALSE, FALSE, NULL, eap, clearvars);
}
else if (eap != NULL && eap->forceit)
// ":source!": read Normal mode commands
@@ -1480,21 +1251,78 @@ fopen_noinh_readbin(char *filename)
#endif
/*
* do_source: Read the file "fname" and execute its lines as EX commands.
* Initialization for sourcing lines from the current buffer. Reads all the
* lines from the buffer and stores it in the cookie grow array.
* Returns a pointer to the name ":source buffer=<n>" on success and NULL on
* failure.
*/
static char_u *
do_source_buffer_init(source_cookie_T *sp, exarg_T *eap)
{
linenr_T curr_lnum;
char_u *line = NULL;
char_u *fname;
CLEAR_FIELD(*sp);
if (curbuf == NULL)
return NULL;
// Use ":source buffer=<num>" as the script name
vim_snprintf((char *)IObuff, IOSIZE, ":source buffer=%d", curbuf->b_fnum);
fname = vim_strsave(IObuff);
if (fname == NULL)
return NULL;
ga_init2(&sp->buflines, sizeof(char_u *), 100);
// Copy the lines from the buffer into a grow array
for (curr_lnum = eap->line1; curr_lnum <= eap->line2; curr_lnum++)
{
line = vim_strsave(ml_get(curr_lnum));
if (line == NULL)
goto errret;
if (ga_add_string(&sp->buflines, line) == FAIL)
goto errret;
line = NULL;
}
sp->buf_lnum = 0;
sp->source_from_buf = TRUE;
return fname;
errret:
vim_free(fname);
vim_free(line);
ga_clear_strings(&sp->buflines);
return NULL;
}
/*
* Read the file "fname" and execute its lines as EX commands.
* When "ret_sid" is not NULL and we loaded the script before, don't load it
* again.
*
* The 'eap' argument is used when sourcing lines from a buffer instead of a
* file.
*
* If 'clearvars' is TRUE, then for scripts which are loaded more than
* once, clear all the functions and variables previously defined in that
* script.
*
* This function may be called recursively!
*
* Return FAIL if file could not be opened, OK otherwise.
* If a scriptitem_T was found or created "*ret_sid" is set to the SID.
*/
int
do_source(
static int
do_source_ext(
char_u *fname,
int check_other, // check for .vimrc and _vimrc
int is_vimrc, // DOSO_ value
int *ret_sid UNUSED)
int *ret_sid UNUSED,
exarg_T *eap,
int clearvars UNUSED)
{
source_cookie_T cookie;
char_u *p;
@@ -1520,17 +1348,28 @@ do_source(
int trigger_source_post = FALSE;
ESTACK_CHECK_DECLARATION
p = expand_env_save(fname);
if (p == NULL)
return retval;
fname_exp = fix_fname(p);
vim_free(p);
if (fname_exp == NULL)
return retval;
if (mch_isdir(fname_exp))
CLEAR_FIELD(cookie);
if (fname == NULL)
{
smsg(_("Cannot source a directory: \"%s\""), fname);
goto theend;
// sourcing lines from a buffer
fname_exp = do_source_buffer_init(&cookie, eap);
if (fname_exp == NULL)
return FAIL;
}
else
{
p = expand_env_save(fname);
if (p == NULL)
return retval;
fname_exp = fix_fname(p);
vim_free(p);
if (fname_exp == NULL)
return retval;
if (mch_isdir(fname_exp))
{
smsg(_("Cannot source a directory: \"%s\""), fname);
goto theend;
}
}
#ifdef FEAT_EVAL
estack_compiling = FALSE;
@@ -1567,11 +1406,14 @@ do_source(
// Apply SourcePre autocommands, they may get the file.
apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
if (!cookie.source_from_buf)
{
#ifdef USE_FOPEN_NOINH
cookie.fp = fopen_noinh_readbin((char *)fname_exp);
cookie.fp = fopen_noinh_readbin((char *)fname_exp);
#else
cookie.fp = mch_fopen((char *)fname_exp, READBIN);
cookie.fp = mch_fopen((char *)fname_exp, READBIN);
#endif
}
if (cookie.fp == NULL && check_other)
{
// Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
@@ -1594,7 +1436,7 @@ do_source(
}
}
if (cookie.fp == NULL)
if (cookie.fp == NULL && !cookie.source_from_buf)
{
if (p_verbose > 0)
{
@@ -1632,12 +1474,14 @@ do_source(
cookie.fileformat = EOL_DOS;
else
cookie.fileformat = EOL_UNKNOWN;
cookie.error = FALSE;
#endif
cookie.nextline = NULL;
cookie.sourcing_lnum = 0;
cookie.finished = FALSE;
if (fname == NULL)
// When sourcing a range of lines from a buffer, use the buffer line
// number.
cookie.sourcing_lnum = eap->line1 - 1;
else
cookie.sourcing_lnum = 0;
#ifdef FEAT_EVAL
// Check if this script has a breakpoint.
@@ -1661,7 +1505,12 @@ do_source(
sticky_cmdmod_flags = 0;
save_current_sctx = current_sctx;
current_sctx.sc_version = 1; // default script version
if (cmdmod.cmod_flags & CMOD_VIM9CMD)
// When the ":vim9cmd" command modifier is used, source the script as a
// Vim9 script.
current_sctx.sc_version = SCRIPT_VERSION_VIM9;
else
current_sctx.sc_version = 1; // default script version
#ifdef FEAT_EVAL
# ifdef FEAT_PROFILE
@@ -1697,20 +1546,25 @@ do_source(
{
si->sn_state = SN_STATE_RELOAD;
// Script-local variables remain but "const" can be set again.
// In Vim9 script variables will be cleared when "vim9script" is
// encountered without the "noclear" argument.
ht = &SCRIPT_VARS(sid);
todo = (int)ht->ht_used;
for (hi = ht->ht_array; todo > 0; ++hi)
if (!HASHITEM_EMPTY(hi))
{
--todo;
di = HI2DI(hi);
di->di_flags |= DI_FLAGS_RELOAD;
}
// imports can be redefined once
mark_imports_for_reload(sid);
if (!clearvars)
{
// Script-local variables remain but "const" can be set again.
// In Vim9 script variables will be cleared when "vim9script"
// is encountered without the "noclear" argument.
ht = &SCRIPT_VARS(sid);
todo = (int)ht->ht_used;
for (hi = ht->ht_array; todo > 0; ++hi)
if (!HASHITEM_EMPTY(hi))
{
--todo;
di = HI2DI(hi);
di->di_flags |= DI_FLAGS_RELOAD;
}
// imports can be redefined once
mark_imports_for_reload(sid);
}
else
clear_vim9_scriptlocal_vars(sid);
// reset version, "vim9script" may have been added or removed.
si->sn_version = 1;
@@ -1874,7 +1728,10 @@ almosttheend:
#endif
current_sctx = save_current_sctx;
fclose(cookie.fp);
if (cookie.fp != NULL)
fclose(cookie.fp);
if (cookie.source_from_buf)
ga_clear_strings(&cookie.buflines);
vim_free(cookie.nextline);
vim_free(firstline);
convert_setup(&cookie.conv, NULL, NULL);
@@ -1891,6 +1748,17 @@ theend:
return retval;
}
int
do_source(
char_u *fname,
int check_other, // check for .vimrc and _vimrc
int is_vimrc, // DOSO_ value
int *ret_sid UNUSED)
{
return do_source_ext(fname, check_other, is_vimrc, ret_sid, NULL, FALSE);
}
#if defined(FEAT_EVAL) || defined(PROTO)
/*
@@ -1901,14 +1769,20 @@ ex_scriptnames(exarg_T *eap)
{
int i;
if (eap->addr_count > 0)
if (eap->addr_count > 0 || *eap->arg != NUL)
{
// :script {scriptId}: edit the script
if (!SCRIPT_ID_VALID(eap->line2))
if (eap->addr_count > 0 && !SCRIPT_ID_VALID(eap->line2))
emsg(_(e_invalid_argument));
else
{
eap->arg = SCRIPT_ITEM(eap->line2)->sn_name;
if (eap->addr_count > 0)
eap->arg = SCRIPT_ITEM(eap->line2)->sn_name;
else
{
expand_env(eap->arg, NameBuff, MAXPATHL);
eap->arg = NameBuff;
}
do_exedit(eap, NULL);
}
return;
@@ -2038,11 +1912,21 @@ get_one_sourceline(source_cookie_T *sp)
// make room to read at least 120 (more) characters
if (ga_grow(&ga, 120) == FAIL)
break;
buf = (char_u *)ga.ga_data;
if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
sp->fp) == NULL)
break;
if (sp->source_from_buf)
{
if (sp->buf_lnum >= sp->buflines.ga_len)
break; // all the lines are processed
ga_concat(&ga, ((char_u **)sp->buflines.ga_data)[sp->buf_lnum]);
sp->buf_lnum++;
buf = (char_u *)ga.ga_data;
}
else
{
buf = (char_u *)ga.ga_data;
if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
sp->fp) == NULL)
break;
}
len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
#ifdef USE_CRNL
// Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
@@ -2145,7 +2029,7 @@ getsourceline(
#ifdef FEAT_EVAL
// If breakpoints have been added/deleted need to check for it.
if (sp->dbg_tick < debug_tick)
if ((sp->dbg_tick < debug_tick) && !sp->source_from_buf)
{
sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, SOURCING_LNUM);
sp->dbg_tick = debug_tick;
@@ -2161,7 +2045,7 @@ getsourceline(
// Get current line. If there is a read-ahead line, use it, otherwise get
// one now. "fp" is NULL if actually using a string.
if (sp->finished || sp->fp == NULL)
if (sp->finished || (!sp->source_from_buf && sp->fp == NULL))
line = NULL;
else if (sp->nextline == NULL)
line = get_one_sourceline(sp);
@@ -2265,7 +2149,8 @@ getsourceline(
#ifdef FEAT_EVAL
// Did we encounter a breakpoint?
if (sp->breakpoint != 0 && sp->breakpoint <= SOURCING_LNUM)
if (!sp->source_from_buf && sp->breakpoint != 0
&& sp->breakpoint <= SOURCING_LNUM)
{
dbg_breakpoint(sp->fname, SOURCING_LNUM);
// Find next breakpoint.
@@ -2284,8 +2169,7 @@ getsourceline(
int
sourcing_a_script(exarg_T *eap)
{
return (getline_equal(eap->getline, eap->cookie, getsourceline)
|| getline_equal(eap->getline, eap->cookie, source_getbufline));
return (getline_equal(eap->getline, eap->cookie, getsourceline));
}
/*
+1 -1
View File
@@ -847,7 +847,7 @@ sign_mark_adjust(
if (sign->se_lnum < line1)
continue;
new_lnum = sign->se_lnum;
if (sign->se_lnum >= line1 && sign->se_lnum <= line2)
if (sign->se_lnum <= line2)
{
if (amount != MAXLNUM)
new_lnum += amount;
+3 -4
View File
@@ -1371,11 +1371,10 @@ spell_move_to(
// the cursor.
if (dir == BACKWARD
|| lnum != wp->w_cursor.lnum
|| (lnum == wp->w_cursor.lnum
&& (wrapped
|| (colnr_T)(curline ? p - buf + len
|| (wrapped
|| (colnr_T)(curline ? p - buf + len
: p - buf)
> wp->w_cursor.col)))
> wp->w_cursor.col))
{
#ifdef FEAT_SYN_HL
if (has_syntax)
+3
View File
@@ -4445,6 +4445,9 @@ typedef struct {
char_u *nextline; // if not NULL: line that was read ahead
linenr_T sourcing_lnum; // line number of the source file
int finished; // ":finish" used
int source_from_buf;// TRUE if sourcing from current buffer
int buf_lnum; // line number in the current buffer
garray_T buflines; // lines in the current buffer
#ifdef USE_CRNL
int fileformat; // EOL_UNKNOWN, EOL_UNIX or EOL_DOS
int error; // TRUE if LF found after CR-LF
+1 -1
View File
@@ -4764,7 +4764,7 @@ syn_cmd_include(exarg_T *eap, int syncing UNUSED)
* filename to include.
*/
eap->argt |= (EX_XFILE | EX_NOSPC);
separate_nextcmd(eap);
separate_nextcmd(eap, FALSE);
if (*eap->arg == '<' || *eap->arg == '$' || mch_isFullName(eap->arg))
{
// For an absolute path, "$VIM/..." or "<sfile>.." we ":source" the
+15
View File
@@ -3,6 +3,7 @@
source shared.vim
source check.vim
source term_util.vim
import './vim9.vim' as v9
func s:cleanup_buffers() abort
for bnr in range(1, bufnr('$'))
@@ -2975,4 +2976,18 @@ func Test_Changed_ChangedI()
bw!
endfunc
func Test_closing_autocmd_window()
let lines =<< trim END
edit Xa.txt
tabnew Xb.txt
autocmd BufEnter Xa.txt unhide 1
doautoall BufEnter
END
call v9.CheckScriptFailure(lines, 'E814:')
au! BufEnter
only!
bwipe Xa.txt
bwipe Xb.txt
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+1 -1
View File
@@ -731,7 +731,7 @@ func Test_breakindent20_list()
\ "shall make no law ",
\ ]
call s:compare_lines(expect, lines)
" set mininum indent
" set minimum indent
setl briopt=min:5
redraw!
let lines = s:screen_lines2(1, 6, 20)
+43
View File
@@ -552,6 +552,22 @@ func Test_getcompletion()
call assert_fails('call getcompletion("abc", [])', 'E475:')
endfunc
" Test for getcompletion() with "fuzzy" in 'wildoptions'
func Test_getcompletion_wildoptions()
let save_wildoptions = &wildoptions
set wildoptions&
let l = getcompletion('space', 'option')
call assert_equal([], l)
let l = getcompletion('ier', 'command')
call assert_equal([], l)
set wildoptions=fuzzy
let l = getcompletion('space', 'option')
call assert_true(index(l, 'backspace') >= 0)
let l = getcompletion('ier', 'command')
call assert_true(index(l, 'compiler') >= 0)
let &wildoptions = save_wildoptions
endfunc
func Test_complete_autoload_error()
let save_rtp = &rtp
let lines =<< trim END
@@ -3241,4 +3257,31 @@ func Test_cmdline_complete_breakdel()
call assert_equal("\"breakdel here ", @:)
endfunc
" Test for :scriptnames argument completion
func Test_cmdline_complete_scriptnames()
set wildmenu
call writefile(['let a = 1'], 'Xa1b2c3.vim')
source Xa1b2c3.vim
call feedkeys(":script \<Tab>\<Left>\<Left>\<C-B>\"\<CR>", 'tx')
call assert_match("\"script .*Xa1b2c3.vim$", @:)
call feedkeys(":script \<Tab>\<Left>\<Left>\<C-B>\"\<CR>", 'tx')
call assert_match("\"script .*Xa1b2c3.vim$", @:)
call feedkeys(":script b2c3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"script b2c3", @:)
call feedkeys(":script 2\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match("\"script 2\<Tab>$", @:)
call feedkeys(":script \<Tab>\<Left>\<Left> \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match("\"script .*Xa1b2c3.vim $", @:)
call feedkeys(":script \<Tab>\<Left>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"script ", @:)
call assert_match('Xa1b2c3.vim$', getcompletion('.*Xa1b2.*', 'scriptnames')[0])
call assert_equal([], getcompletion('Xa1b2', 'scriptnames'))
new
call feedkeys(":script \<Tab>\<Left>\<Left>\<CR>", 'tx')
call assert_equal('Xa1b2c3.vim', fnamemodify(@%, ':t'))
bw!
call delete('Xa1b2c3.vim')
set wildmenu&
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+1 -1
View File
@@ -172,7 +172,7 @@ func Test_uncrypt_xchacha20_2()
call assert_equal(range(1, 4000)->map( {_, v -> string(v)}), getline(1,'$'))
set key=
w! ++ff=unix
" enryption removed (on MS-Windows the .* matches [unix])
" encryption removed (on MS-Windows the .* matches [unix])
call assert_match('"Xcrypt_sodium.txt".*4000L, 18893B written', execute(':message'))
bw!
call delete('Xcrypt_sodium.txt')
+1 -1
View File
@@ -162,7 +162,7 @@ func Test_cursorline_screenline()
call term_sendkeys(buf, "gj")
call VerifyScreenDump(buf, 'Test_'. filename. '_12', {})
if exists("+foldcolumn") && exists("+signcolumn") && exists("+breakindent")
" test with set foldcolumn signcoloumn and breakindent
" test with set foldcolumn signcolumn and breakindent
call term_sendkeys(buf, "gg0")
call term_sendkeys(buf, ":set breakindent foldcolumn=2 signcolumn=yes\<cr>")
call VerifyScreenDump(buf, 'Test_'. filename. '_13', {})
+1 -1
View File
@@ -51,7 +51,7 @@ func Test_digraphs()
call Put_Dig("'e")
call Put_Dig("b'") " not defined
call assert_equal(["á", "é", "'"], getline(line('.')-2,line('.')))
" Cicumflex
" Circumflex
call Put_Dig("a>")
call Put_Dig(">e")
call Put_Dig("b>") " not defined
+6 -6
View File
@@ -274,7 +274,7 @@ func Test_set_balloonexpr()
" Multiline balloon using NL
new
func MyBalloonFuncForMultilineUsingNL()
return "Multiline\nSuppported\nBalloon\nusing NL"
return "Multiline\nSupported\nBalloon\nusing NL"
endfunc
setl balloonexpr=MyBalloonFuncForMultilineUsingNL()
setl ballooneval
@@ -289,7 +289,7 @@ func Test_set_balloonexpr()
" Multiline balloon using List
new
func MyBalloonFuncForMultilineUsingList()
return [ 'Multiline', 'Suppported', 'Balloon', 'using List' ]
return [ 'Multiline', 'Supported', 'Balloon', 'using List' ]
endfunc
setl balloonexpr=MyBalloonFuncForMultilineUsingList()
setl ballooneval
@@ -1458,25 +1458,25 @@ func Test_gui_findrepl()
call test_gui_event('findrepl', args)
call assert_equal(['ONE TWO ONE', 'Twoo ONE TWO ONEo'], getline(1, '$'))
" Find next occurance of a string (in a find dialog)
" Find next occurrence of a string (in a find dialog)
call cursor(1, 11)
let args = #{find_text: 'TWO', repl_text: '', flags: 0x11, forward: 1}
call test_gui_event('findrepl', args)
call assert_equal([2, 10], [line('.'), col('.')])
" Find previous occurances of a string (in a find dialog)
" Find previous occurrences of a string (in a find dialog)
call cursor(1, 11)
let args = #{find_text: 'TWO', repl_text: '', flags: 0x11, forward: 0}
call test_gui_event('findrepl', args)
call assert_equal([1, 5], [line('.'), col('.')])
" Find next occurance of a string (in a replace dialog)
" Find next occurrence of a string (in a replace dialog)
call cursor(1, 1)
let args = #{find_text: 'Twoo', repl_text: '', flags: 0x2, forward: 1}
call test_gui_event('findrepl', args)
call assert_equal([2, 1], [line('.'), col('.')])
" Replace only the next occurance of a string (once)
" Replace only the next occurrence of a string (once)
call cursor(1, 5)
let args = #{find_text: 'TWO', repl_text: 'two', flags: 0x3, forward: 1}
call test_gui_event('findrepl', args)
+11 -1
View File
@@ -1208,11 +1208,21 @@ func Test_lua_debug()
call WaitForAssert({-> assert_equal('42', term_getline(buf, 9))})
call WaitForAssert({-> assert_equal('lua_debug> ', term_getline(buf, 10))})
call term_sendkeys(buf, "-\n")
call WaitForAssert({-> assert_equal("(debug command):1: unexpected symbol near '-'",
\ term_getline(buf, 9))})
call WaitForAssert({-> assert_equal('lua_debug> ', term_getline(buf, 10))})
call term_sendkeys(buf, "cont\n")
call WaitForAssert({-> assert_match(' All$', term_getline(buf, 10))})
" Entering an empty line also exits the debugger.
call term_sendkeys(buf, ":lua debug.debug()\n")
call WaitForAssert({-> assert_equal('lua_debug> ', term_getline(buf, 10))})
call term_sendkeys(buf, "\n")
call WaitForAssert({-> assert_match(' All$', term_getline(buf, 10))})
call StopVimInTerminal(buf)
call delete('XtestLuaDebug.vim')
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+35
View File
@@ -6202,4 +6202,39 @@ func Test_getqflist_wiped_out_buffer()
%bw!
endfunc
" Test for the status message that is displayed when opening a new quickfix
" list
func Test_qflist_statusmsg()
cexpr "1\n2"
cexpr "1\n2\n3\ntest_quickfix.vim:1:msg"
call assert_equal('(4 of 4): msg', v:statusmsg)
call setqflist([], 'f')
%bw!
" When creating a new quickfix list, if an autocmd changes the quickfix list
" in the stack, then an error message should be displayed.
augroup QF_Test
au!
au BufEnter test_quickfix.vim colder
augroup END
cexpr "1\n2"
call assert_fails('cexpr "1\n2\n3\ntest_quickfix.vim:1:msg"', 'E925:')
call setqflist([], 'f')
augroup QF_Test
au!
augroup END
%bw!
augroup QF_Test
au!
au BufEnter test_quickfix.vim caddexpr "4"
augroup END
call assert_fails('cexpr "1\n2\n3\ntest_quickfix.vim:1:msg"', 'E925:')
call setqflist([], 'f')
augroup QF_Test
au!
augroup END
%bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+1 -1
View File
@@ -799,7 +799,7 @@ func Test_matchstr_with_ze()
bwipe!
endfunc
" Check a pattern with a look beind crossing a line boundary
" Check a pattern with a look behind crossing a line boundary
func Test_lookbehind_across_line()
new
call append(0, ['Behind:', 'asdfasd<yyy', 'xxstart1', 'asdfasd<yy',
+2 -2
View File
@@ -99,8 +99,8 @@ func Test_signal_INT()
call term_sendkeys(buf, ":while 1 | endwhile\n")
call WaitForAssert({-> assert_equal(':while 1 | endwhile', term_getline(buf, 6))})
exe 'silent !kill -s INT ' .. pid_vim
call term_sendkeys(buf, ":call setline(1, 'INTERUPTED')\n")
call WaitForAssert({-> assert_equal('INTERUPTED', term_getline(buf, 1))})
call term_sendkeys(buf, ":call setline(1, 'INTERRUPTED')\n")
call WaitForAssert({-> assert_equal('INTERRUPTED', term_getline(buf, 1))})
call StopVimInTerminal(buf)
endfunc
+294
View File
@@ -146,6 +146,23 @@ func Test_source_buffer()
2,3source
call assert_equal(90, g:a)
" Make sure the script line number is correct when sourcing a range of
" lines.
%d _
let lines =<< trim END
Line 1
Line 2
func Xtestfunc()
return expand("<sflnum>")
endfunc
Line 3
Line 4
END
call setline(1, lines)
3,5source
call assert_equal('4', Xtestfunc())
delfunc Xtestfunc
" Source a script with line continuation lines
%d _
let lines =<< trim END
@@ -327,6 +344,63 @@ func Test_source_buffer()
call assert_equal("three", Xtestfunc())
delfunc Xtestfunc
" test for using try/catch
%d _
let lines =<< trim END
let Trace = '1'
try
let a1 = b1
catch
let Trace ..= '2'
finally
let Trace ..= '3'
endtry
END
call setline(1, lines)
source
call assert_equal("123", g:Trace)
" test with the finish command
%d _
let lines =<< trim END
let g:Color = 'blue'
finish
let g:Color = 'green'
END
call setline(1, lines)
source
call assert_equal('blue', g:Color)
" Test for the SourcePre and SourcePost autocmds
augroup Xtest
au!
au SourcePre * let g:XsourcePre=4
\ | let g:XsourcePreFile = expand("<afile>")
au SourcePost * let g:XsourcePost=6
\ | let g:XsourcePostFile = expand("<afile>")
augroup END
%d _
let lines =<< trim END
let a = 1
END
call setline(1, lines)
source
call assert_equal(4, g:XsourcePre)
call assert_equal(6, g:XsourcePost)
call assert_equal(':source buffer=' .. bufnr(), g:XsourcePreFile)
call assert_equal(':source buffer=' .. bufnr(), g:XsourcePostFile)
augroup Xtest
au!
augroup END
augroup! Xtest
%bw!
endfunc
" Test for sourcing a Vim9 script from the current buffer
func Test_source_buffer_vim9()
new
" test for sourcing a Vim9 script
%d _
let lines =<< trim END
@@ -342,6 +416,226 @@ func Test_source_buffer()
source
call assert_equal(10, Xtestfunc())
" test for sourcing a vim9 script with line continuation
%d _
let lines =<< trim END
vim9script
g:Str1 = "hello "
.. "world"
.. ", how are you?"
g:Colors = [
'red',
# comment
'blue'
]
g:Dict = {
a: 22,
# comment
b: 33
}
# calling a function with line continuation
def Sum(...values: list<number>): number
var sum: number = 0
for v in values
sum += v
endfor
return sum
enddef
g:Total1 = Sum(10,
20,
30)
var i: number = 0
while i < 10
# while loop
i +=
1
endwhile
g:Count1 = i
# for loop
g:Count2 = 0
for j in range(10, 20)
g:Count2 +=
i
endfor
g:Total2 = 10 +
20 -
5
g:Result1 = g:Total2 > 1
? 'red'
: 'blue'
g:Str2 = 'x'
->repeat(10)
->trim()
->strpart(4)
g:Result2 = g:Dict
.a
augroup Test
au!
au BufNewFile Xfile g:readFile = 1
| g:readExtra = 2
augroup END
g:readFile = 0
g:readExtra = 0
new Xfile
bwipe!
augroup Test
au!
augroup END
END
call setline(1, lines)
source
call assert_equal("hello world, how are you?", g:Str1)
call assert_equal(['red', 'blue'], g:Colors)
call assert_equal(#{a: 22, b: 33}, g:Dict)
call assert_equal(60, g:Total1)
call assert_equal(10, g:Count1)
call assert_equal(110, g:Count2)
call assert_equal(25, g:Total2)
call assert_equal('red', g:Result1)
call assert_equal('xxxxxx', g:Str2)
call assert_equal(22, g:Result2)
call assert_equal(1, g:readFile)
call assert_equal(2, g:readExtra)
" test for sourcing the same buffer multiple times after changing a function
%d _
let lines =<< trim END
vim9script
def g:Xtestfunc(): string
return "one"
enddef
END
call setline(1, lines)
source
call assert_equal("one", Xtestfunc())
call setline(3, ' return "two"')
source
call assert_equal("two", Xtestfunc())
call setline(3, ' return "three"')
source
call assert_equal("three", Xtestfunc())
delfunc Xtestfunc
" Test for sourcing a range of lines. Make sure the script line number is
" correct.
%d _
let lines =<< trim END
Line 1
Line 2
vim9script
def g:Xtestfunc(): string
return expand("<sflnum>")
enddef
Line 3
Line 4
END
call setline(1, lines)
3,6source
call assert_equal('5', Xtestfunc())
delfunc Xtestfunc
" test for sourcing a heredoc
%d _
let lines =<< trim END
vim9script
var a = 1
g:heredoc =<< trim DATA
red
green
blue
DATA
var b = 2
END
call setline(1, lines)
source
call assert_equal(['red', ' green', 'blue'], g:heredoc)
" test for using the :vim9cmd modifier
%d _
let lines =<< trim END
first line
g:Math = {
pi: 3.12,
e: 2.71828
}
g:Editors = [
'vim',
# comment
'nano'
]
last line
END
call setline(1, lines)
vim9cmd :2,10source
call assert_equal(#{pi: 3.12, e: 2.71828}, g:Math)
call assert_equal(['vim', 'nano'], g:Editors)
" test for using try/catch
%d _
let lines =<< trim END
vim9script
g:Trace = '1'
try
a1 = b1
catch
g:Trace ..= '2'
finally
g:Trace ..= '3'
endtry
END
call setline(1, lines)
source
call assert_equal('123', g:Trace)
" test with the finish command
%d _
let lines =<< trim END
vim9script
g:Color = 'red'
finish
g:Color = 'blue'
END
call setline(1, lines)
source
call assert_equal('red', g:Color)
" test for ++clear argument to clear all the functions/variables
%d _
let lines =<< trim END
g:ScriptVarFound = exists("color")
g:MyFuncFound = exists('*Myfunc')
if g:MyFuncFound
finish
endif
var color = 'blue'
def Myfunc()
enddef
END
call setline(1, lines)
vim9cmd source
call assert_false(g:MyFuncFound)
call assert_false(g:ScriptVarFound)
vim9cmd source
call assert_true(g:MyFuncFound)
call assert_true(g:ScriptVarFound)
vim9cmd source ++clear
call assert_false(g:MyFuncFound)
call assert_false(g:ScriptVarFound)
vim9cmd source ++clear
call assert_false(g:MyFuncFound)
call assert_false(g:ScriptVarFound)
call assert_fails('vim9cmd source ++clearx', 'E475:')
call assert_fails('vim9cmd source ++abcde', 'E484:')
%bw!
endfunc
+1 -1
View File
@@ -417,7 +417,7 @@ func Test_spellsuggest_option_expr()
bwipe!
endfunc
" Test for 'spellsuggest' expr errrors
" Test for 'spellsuggest' expr errors
func Test_spellsuggest_expr_errors()
" 'spellsuggest'
func MySuggest()
+1 -1
View File
@@ -260,7 +260,7 @@ func Test_statusline()
call assert_match('^vimLineComment\s*$', s:get_statusline())
syntax off
"%{%expr%}: evaluates enxpressions present in result of expr
"%{%expr%}: evaluates expressions present in result of expr
func! Inner_eval()
return '%n some other text'
endfunc
+36
View File
@@ -798,4 +798,40 @@ func Test_multibyte_in_usercmd()
delcommand SubJapanesePeriodToDot
endfunc
" Declaring a variable in a {} uses Vim9 script rules, even when defined in a
" legacy script.
func Test_block_declaration_legacy_script()
let lines =<< trim END
command -range Rename {
var save = @a
@a = 'something'
g:someExpr = @a
@a = save
}
END
call writefile(lines, 'Xlegacy')
source Xlegacy
let lines =<< trim END
let @a = 'saved'
Rename
call assert_equal('something', g:someExpr)
call assert_equal('saved', @a)
let g:someExpr = 'xxx'
let @a = 'also'
Rename
call assert_equal('something', g:someExpr)
call assert_equal('also', @a)
END
call writefile(lines, 'Xother')
source Xother
unlet g:someExpr
call delete('Xlegacy')
call delete('Xother')
delcommand Rename
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+13 -2
View File
@@ -1178,8 +1178,19 @@ def Test_map_command()
nnoremap <F3> :echo 'hit F3 #'<CR>
assert_equal(":echo 'hit F3 #'<CR>", maparg("<F3>", "n"))
END
v9.CheckDefSuccess(lines)
v9.CheckScriptSuccess(['vim9script'] + lines)
v9.CheckDefAndScriptSuccess(lines)
# backslash before bar is not removed
lines =<< trim END
vim9script
def Init()
noremap <buffer> <F5> <ScriptCmd>MyFunc('a') \| MyFunc('b')<CR>
enddef
Init()
unmap <buffer> <F5>
END
v9.CheckScriptSuccess(lines)
enddef
def Test_normal_command()
+1 -1
View File
@@ -2004,7 +2004,7 @@ def s:FalsyOp()
echo "" ?? "empty string"
enddef
def Test_dsassemble_falsy_op()
def Test_disassemble_falsy_op()
var res = execute('disass s:FalsyOp')
assert_match('\<SNR>\d*_FalsyOp\_s*' ..
'echo g:flag ?? "yes"\_s*' ..
+10 -10
View File
@@ -563,7 +563,7 @@ let ablob = 0z01ab
let alist = [2, 3, 4]
let adict = #{aaa: 2, bbb: 8}
" test == comperator
" test == comparator
def Test_expr4_equal()
var lines =<< trim END
var trueVar = true
@@ -902,7 +902,7 @@ def Test_expr4_wrong_type()
'echo n < true'], 'E1072:', 2)
enddef
" test != comperator
" test != comparator
def Test_expr4_notequal()
var lines =<< trim END
var trueVar = true
@@ -987,7 +987,7 @@ def Test_expr4_notequal()
v9.CheckDefAndScriptSuccess(lines)
enddef
" test > comperator
" test > comparator
def Test_expr4_greater()
var lines =<< trim END
assert_true(2 > 0)
@@ -1013,7 +1013,7 @@ def Test_expr4_greater()
v9.CheckDefAndScriptSuccess(lines)
enddef
" test >= comperator
" test >= comparator
def Test_expr4_greaterequal()
var lines =<< trim END
assert_true(2 >= 0)
@@ -1034,7 +1034,7 @@ def Test_expr4_greaterequal()
v9.CheckDefAndScriptSuccess(lines)
enddef
" test < comperator
" test < comparator
def Test_expr4_smaller()
var lines =<< trim END
assert_false(2 < 0)
@@ -1056,7 +1056,7 @@ def Test_expr4_smaller()
v9.CheckDefAndScriptSuccess(lines)
enddef
" test <= comperator
" test <= comparator
def Test_expr4_smallerequal()
var lines =<< trim END
assert_false(2 <= 0)
@@ -1081,7 +1081,7 @@ def Test_expr4_smallerequal()
v9.CheckDefAndScriptSuccess(lines)
enddef
" test =~ comperator
" test =~ comparator
def Test_expr4_match()
var lines =<< trim END
assert_equal(false, '2' =~ '0')
@@ -1098,7 +1098,7 @@ def Test_expr4_match()
v9.CheckDefAndScriptSuccess(lines)
enddef
" test !~ comperator
" test !~ comparator
def Test_expr4_nomatch()
var lines =<< trim END
assert_equal(true, '2' !~ '0')
@@ -1110,7 +1110,7 @@ def Test_expr4_nomatch()
v9.CheckDefAndScriptSuccess(lines)
enddef
" test is comperator
" test is comparator
def Test_expr4_is()
var lines =<< trim END
var mylist = [2]
@@ -1128,7 +1128,7 @@ def Test_expr4_is()
v9.CheckDefAndScriptSuccess(lines)
enddef
" test isnot comperator
" test isnot comparator
def Test_expr4_isnot()
var lines =<< trim END
var mylist = [2]
+19
View File
@@ -876,6 +876,25 @@ def Test_nested_function()
END
v9.CheckScriptSuccess(lines)
# nested function with recursive call
lines =<< trim END
vim9script
def MyFunc(): number
def Fib(n: number): number
if n < 2
return 1
endif
return Fib(n - 2) + Fib(n - 1)
enddef
return Fib(5)
enddef
assert_equal(8, MyFunc())
END
v9.CheckScriptSuccess(lines)
lines =<< trim END
vim9script
def Outer()
+2 -2
View File
@@ -2156,7 +2156,7 @@ def Test_vim9script_autoload_duplicate()
export var Func = 'asdf'
END
writefile(lines, 'Xdir/autoload/dup3func.vim')
assert_fails('source Xdir/autoload/dup3func.vim', 'E1041: Redefining script item Func')
assert_fails('source Xdir/autoload/dup3func.vim', 'E1041: Redefining script item: "Func"')
lines =<< trim END
vim9script
@@ -2189,7 +2189,7 @@ def Test_vim9script_autoload_duplicate()
var Func = 'asdf'
END
writefile(lines, 'Xdir/autoload/dup6func.vim')
assert_fails('source Xdir/autoload/dup6func.vim', 'E1041: Redefining script item Func')
assert_fails('source Xdir/autoload/dup6func.vim', 'E1041: Redefining script item: "Func"')
delete('Xdir', 'rf')
enddef
+1 -1
View File
@@ -3631,7 +3631,7 @@ endfunc
" exceptions.
"-------------------------------------------------------------------------------
func Test_execption_info_for_error()
func Test_exception_info_for_error()
CheckEnglish
let test =<< trim [CODE]
+21
View File
@@ -22,6 +22,7 @@ typedef struct ucmd
int uc_compl; // completion type
cmd_addr_T uc_addr_type; // The command's address type
sctx_T uc_script_ctx; // SCTX where the command was defined
int uc_flags; // some UC_ flags
# ifdef FEAT_EVAL
char_u *uc_compl_arg; // completion argument if any
# endif
@@ -92,6 +93,7 @@ static struct
{EXPAND_USER_VARS, "var"},
#if defined(FEAT_EVAL)
{EXPAND_BREAKPOINT, "breakpoint"},
{EXPAND_SCRIPTNAMES, "scriptnames"},
#endif
{0, NULL}
};
@@ -1038,6 +1040,7 @@ uc_add_command(
cmd->uc_script_ctx = current_sctx;
if (flags & UC_VIM9)
cmd->uc_script_ctx.sc_version = SCRIPT_VERSION_VIM9;
cmd->uc_flags = flags & UC_VIM9;
#ifdef FEAT_EVAL
cmd->uc_script_ctx.sc_lnum += SOURCING_LNUM;
cmd->uc_compl_arg = compl_arg;
@@ -1725,6 +1728,9 @@ do_ucmd(exarg_T *eap)
ucmd_T *cmd;
sctx_T save_current_sctx;
int restore_current_sctx = FALSE;
#ifdef FEAT_EVAL
int restore_script_version = 0;
#endif
if (eap->cmdidx == CMD_USER)
cmd = USER_CMD(eap->useridx);
@@ -1830,6 +1836,14 @@ do_ucmd(exarg_T *eap)
current_sctx.sc_version = cmd->uc_script_ctx.sc_version;
#ifdef FEAT_EVAL
current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid;
if (cmd->uc_flags & UC_VIM9)
{
// In a {} block variables use Vim9 script rules, even in a legacy
// script.
restore_script_version =
SCRIPT_ITEM(current_sctx.sc_sid)->sn_version;
SCRIPT_ITEM(current_sctx.sc_sid)->sn_version = SCRIPT_VERSION_VIM9;
}
#endif
}
@@ -1839,7 +1853,14 @@ do_ucmd(exarg_T *eap)
// Careful: Do not use "cmd" here, it may have become invalid if a user
// command was added.
if (restore_current_sctx)
{
#ifdef FEAT_EVAL
if (restore_script_version != 0)
SCRIPT_ITEM(current_sctx.sc_sid)->sn_version =
restore_script_version;
#endif
current_sctx = save_current_sctx;
}
vim_free(buf);
vim_free(split_buf);
}
+38
View File
@@ -765,6 +765,44 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4621,
/**/
4620,
/**/
4619,
/**/
4618,
/**/
4617,
/**/
4616,
/**/
4615,
/**/
4614,
/**/
4613,
/**/
4612,
/**/
4611,
/**/
4610,
/**/
4609,
/**/
4608,
/**/
4607,
/**/
4606,
/**/
4605,
/**/
4604,
/**/
4603,
/**/
4602,
/**/
+2 -1
View File
@@ -809,7 +809,8 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define EXPAND_DIFF_BUFFERS 49
#define EXPAND_DISASSEMBLE 50
#define EXPAND_BREAKPOINT 51
#define EXPAND_MACACTION 52
#define EXPAND_SCRIPTNAMES 52
#define EXPAND_MACACTION 53
// Values for exmode_active (0 is no exmode)
#define EXMODE_NORMAL 1
+2 -3
View File
@@ -1613,8 +1613,7 @@ compile_endtry(char_u *arg, cctx_T *cctx)
// End :catch or :finally scope: set instruction index in ISN_TRY
// instruction
try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
if (cctx->ctx_skip != SKIP_YES
&& generate_instr(cctx, ISN_ENDTRY) == NULL)
if (generate_instr(cctx, ISN_ENDTRY) == NULL)
return NULL;
#ifdef FEAT_PROFILE
if (cctx->ctx_compile_type == CT_PROFILE)
@@ -1849,7 +1848,7 @@ compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
if ((argt & EX_TRLBAR) && !usefilter)
{
eap->argt = argt;
separate_nextcmd(eap);
separate_nextcmd(eap, TRUE);
if (eap->nextcmd != NULL)
nextcmd = eap->nextcmd;
}
+25 -18
View File
@@ -818,6 +818,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
ufunc_T *ufunc;
int r = FAIL;
compiletype_T compile_type;
isn_T *funcref_isn = NULL;
if (eap->forceit)
{
@@ -913,6 +914,27 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
}
}
// Define the funcref before compiling, so that it is found by any
// recursive call.
if (is_global)
{
r = generate_NEWFUNC(cctx, lambda_name, func_name);
func_name = NULL;
lambda_name = NULL;
}
else
{
// Define a local variable for the function reference.
lvar_T *lvar = reserve_local(cctx, func_name, name_end - name_start,
TRUE, ufunc->uf_func_type);
if (lvar == NULL)
goto theend;
if (generate_FUNCREF(cctx, ufunc, &funcref_isn) == FAIL)
goto theend;
r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
}
compile_type = get_compile_type(ufunc);
#ifdef FEAT_PROFILE
// If the outer function is profiled, also compile the nested function for
@@ -934,24 +956,9 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
compile_def_function(ufunc, FALSE, CT_NONE, cctx);
#endif
if (is_global)
{
r = generate_NEWFUNC(cctx, lambda_name, func_name);
func_name = NULL;
lambda_name = NULL;
}
else
{
// Define a local variable for the function reference.
lvar_T *lvar = reserve_local(cctx, func_name, name_end - name_start,
TRUE, ufunc->uf_func_type);
if (lvar == NULL)
goto theend;
if (generate_FUNCREF(cctx, ufunc) == FAIL)
goto theend;
r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
}
// If a FUNCREF instruction was generated, set the index after compiling.
if (funcref_isn != NULL && ufunc->uf_def_status == UF_COMPILED)
funcref_isn->isn_arg.funcref.fr_dfunc_idx = ufunc->uf_dfunc_idx;
theend:
vim_free(lambda_name);
+1 -1
View File
@@ -1040,7 +1040,7 @@ compile_lambda(char_u **arg, cctx_T *cctx)
// The function reference count will be 1. When the ISN_FUNCREF
// instruction is deleted the reference count is decremented and the
// function is freed.
return generate_FUNCREF(cctx, ufunc);
return generate_FUNCREF(cctx, ufunc, NULL);
}
func_ptr_unref(ufunc);
+4 -1
View File
@@ -1172,9 +1172,10 @@ generate_NEWDICT(cctx_T *cctx, int count)
/*
* Generate an ISN_FUNCREF instruction.
* "isnp" is set to the instruction, so that fr_dfunc_idx can be set later.
*/
int
generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc)
generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc, isn_T **isnp)
{
isn_T *isn;
type_T *type;
@@ -1182,6 +1183,8 @@ generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc)
RETURN_OK_IF_SKIP(cctx);
if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
return FAIL;
if (isnp != NULL)
*isnp = isn;
if (ufunc->uf_def_status == UF_NOT_COMPILED)
isn->isn_arg.funcref.fr_func_name = vim_strsave(ufunc->uf_name);
else
+19 -10
View File
@@ -59,6 +59,24 @@ current_script_is_vim9(void)
}
#endif
#ifdef FEAT_EVAL
/*
* Clear Vim9 script-local variables and functions.
*/
void
clear_vim9_scriptlocal_vars(int sid)
{
hashtab_T *ht = &SCRIPT_VARS(sid);
hashtab_free_contents(ht);
hash_init(ht);
delete_script_functions(sid);
// old imports and script variables are no longer valid
free_imports_and_script_vars(sid);
}
#endif
/*
* ":vim9script".
*/
@@ -103,18 +121,9 @@ ex_vim9script(exarg_T *eap UNUSED)
}
if (si->sn_state == SN_STATE_RELOAD && !found_noclear)
{
hashtab_T *ht = &SCRIPT_VARS(sid);
// Reloading a script without the "noclear" argument: clear
// script-local variables and functions.
hashtab_free_contents(ht);
hash_init(ht);
delete_script_functions(sid);
// old imports and script variables are no longer valid
free_imports_and_script_vars(sid);
}
clear_vim9_scriptlocal_vars(sid);
si->sn_state = SN_STATE_HAD_COMMAND;
// Store the prefix with the script, it is used to find exported functions.
+3 -6
View File
@@ -43,7 +43,6 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin);
static int may_open_tabpage(void);
static int win_enter_ext(win_T *wp, int flags);
static void win_free(win_T *wp, tabpage_T *tp);
static int win_unlisted(win_T *wp);
static void win_append(win_T *after, win_T *wp);
static void frame_append(frame_T *after, frame_T *frp);
static void frame_insert(frame_T *before, frame_T *frp);
@@ -5238,7 +5237,7 @@ win_free(
* Return TRUE if "wp" is not in the list of windows: the autocmd window or a
* popup window.
*/
static int
int
win_unlisted(win_T *wp)
{
return wp == aucmd_win || WIN_IS_POPUP(wp);
@@ -5697,8 +5696,7 @@ frame_setheight(frame_T *curfrp, int height)
break;
if (run == 2 || curfrp->fr_width == Columns)
{
if (height > room + room_cmdline)
height = room + room_cmdline;
height = room + room_cmdline;
break;
}
frame_setheight(curfrp->fr_parent, height
@@ -5882,8 +5880,7 @@ frame_setwidth(frame_T *curfrp, int width)
break;
if (run == 2 || curfrp->fr_height >= ROWS_AVAIL)
{
if (width > room)
width = room;
width = room;
break;
}
frame_setwidth(curfrp->fr_parent, width