Patch 8.2.1800

6 views
Skip to first unread message

Bram Moolenaar

unread,
Oct 24, 2020, 5:09:38 PM10/24/20
to vim...@googlegroups.com

Patch 8.2.1900
Problem: Vim9: command modifiers do not work.
Solution: Make most command modifiers work.
Files: src/vim9.h, src/vim9compile.c, src/vim9execute.c,
src/usercmd.c, src/proto/usercmd.pro, src/scriptfile.c,
src/testdir/test_vim9_disassemble.vim


*** ../vim-8.2.1899/src/vim9.h 2020-10-23 18:02:28.707453763 +0200
--- src/vim9.h 2020-10-24 21:37:25.489883302 +0200
***************
*** 142,149 ****

ISN_PUT, // ":put", uses isn_arg.put

! ISN_SILENT, // set msg_silent or emsg_silent if arg_number is non-zero
! ISN_UNSILENT, // undo ISN_SILENT

ISN_SHUFFLE, // move item on stack up or down
ISN_DROP // pop stack and discard value
--- 142,149 ----

ISN_PUT, // ":put", uses isn_arg.put

! ISN_CMDMOD, // set cmdmod
! ISN_CMDMOD_REV, // undo ISN_CMDMOD

ISN_SHUFFLE, // move item on stack up or down
ISN_DROP // pop stack and discard value
***************
*** 278,283 ****
--- 278,288 ----
linenr_T put_lnum; // line number to put below
} put_T;

+ // arguments to ISN_CMDMOD
+ typedef struct {
+ cmdmod_T *cf_cmdmod; // allocated
+ } cmod_T;
+
/*
* Instruction
*/
***************
*** 314,319 ****
--- 319,325 ----
checklen_T checklen;
shuffle_T shuffle;
put_T put;
+ cmod_T cmdmod;
} isn_arg;
};

*** ../vim-8.2.1899/src/vim9compile.c 2020-10-24 20:49:37.502683026 +0200
--- src/vim9compile.c 2020-10-24 22:05:17.881470884 +0200
***************
*** 142,148 ****
garray_T ctx_type_stack; // type of each item on the stack
garray_T *ctx_type_list; // list of pointers to allocated types

! int ctx_silent; // set when ISN_SILENT was generated
};

static void delete_def_function_contents(dfunc_T *dfunc);
--- 142,148 ----
garray_T ctx_type_stack; // type of each item on the stack
garray_T *ctx_type_list; // list of pointers to allocated types

! int ctx_has_cmdmod; // ISN_CMDMOD was generated
};

static void delete_def_function_contents(dfunc_T *dfunc);
***************
*** 1823,1858 ****
}

/*
! * Generate any instructions for side effects of "cmdmod".
*/
static int
generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod)
{
isn_T *isn;

! // TODO: use more modifiers in the command
! if (cmod->cmod_flags & (CMOD_SILENT | CMOD_ERRSILENT))
{
! if ((isn = generate_instr(cctx, ISN_SILENT)) == NULL)
return FAIL;
! isn->isn_arg.number = (cmod->cmod_flags & CMOD_ERRSILENT) != 0;
! cctx->ctx_silent = (cmod->cmod_flags & CMOD_ERRSILENT) ? 2 : 1;
}
return OK;
}

static int
! generate_restore_cmdmods(cctx_T *cctx)
{
isn_T *isn;

! if (cctx->ctx_silent > 0)
{
! if ((isn = generate_instr(cctx, ISN_UNSILENT)) == NULL)
return FAIL;
- isn->isn_arg.number = cctx->ctx_silent == 2;
- cctx->ctx_silent = 0;
}
return OK;
}

--- 1823,1867 ----
}

/*
! * Generate an instruction for any command modifiers.
*/
static int
generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod)
{
isn_T *isn;

! if (cmod->cmod_flags != 0
! || cmod->cmod_split != 0
! || cmod->cmod_verbose != 0
! || cmod->cmod_tab != 0
! || cmod->cmod_filter_regmatch.regprog != NULL)
{
! cctx->ctx_has_cmdmod = TRUE;
!
! if ((isn = generate_instr(cctx, ISN_CMDMOD)) == NULL)
! return FAIL;
! isn->isn_arg.cmdmod.cf_cmdmod = ALLOC_ONE(cmdmod_T);
! if (isn->isn_arg.cmdmod.cf_cmdmod == NULL)
return FAIL;
! mch_memmove(isn->isn_arg.cmdmod.cf_cmdmod, cmod, sizeof(cmdmod_T));
! // filter progam now belongs to the instruction
! cmod->cmod_filter_regmatch.regprog = NULL;
}
+
return OK;
}

static int
! generate_undo_cmdmods(cctx_T *cctx)
{
isn_T *isn;

! if (cctx->ctx_has_cmdmod)
{
! if ((isn = generate_instr(cctx, ISN_CMDMOD_REV)) == NULL)
return FAIL;
}
+
return OK;
}

***************
*** 7092,7100 ****
for (;;)
{
exarg_T ea;
- cmdmod_T local_cmdmod;
int starts_with_colon = FALSE;
char_u *cmd;

// Bail out on the first error to avoid a flood of errors and report
// the right line number when inside try/catch.
--- 7101,7109 ----
for (;;)
{
exarg_T ea;
int starts_with_colon = FALSE;
char_u *cmd;
+ cmdmod_T local_cmdmod;

// Bail out on the first error to avoid a flood of errors and report
// the right line number when inside try/catch.
***************
*** 7175,7181 ****
/*
* COMMAND MODIFIERS
*/
! CLEAR_FIELD(local_cmdmod);
if (parse_command_modifiers(&ea, &errormsg, &local_cmdmod, FALSE)
== FAIL)
{
--- 7184,7190 ----
/*
* COMMAND MODIFIERS
*/
! cctx.ctx_has_cmdmod = FALSE;
if (parse_command_modifiers(&ea, &errormsg, &local_cmdmod, FALSE)
== FAIL)
{
***************
*** 7497,7503 ****
line = skipwhite(line);

// Undo any command modifiers.
! generate_restore_cmdmods(&cctx);

if (cctx.ctx_type_stack.ga_len < 0)
{
--- 7506,7512 ----
line = skipwhite(line);

// Undo any command modifiers.
! generate_undo_cmdmods(&cctx);

if (cctx.ctx_type_stack.ga_len < 0)
{
***************
*** 7742,7747 ****
--- 7751,7762 ----
free_type(isn->isn_arg.type.ct_type);
break;

+ case ISN_CMDMOD:
+ vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
+ ->cmod_filter_regmatch.regprog);
+ vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
+ break;
+
case ISN_2BOOL:
case ISN_2STRING:
case ISN_2STRING_ANY:
***************
*** 7754,7759 ****
--- 7769,7775 ----
case ISN_CATCH:
case ISN_CHECKLEN:
case ISN_CHECKNR:
+ case ISN_CMDMOD_REV:
case ISN_COMPAREANY:
case ISN_COMPAREBLOB:
case ISN_COMPAREBOOL:
***************
*** 7805,7811 ****
case ISN_PUT:
case ISN_RETURN:
case ISN_SHUFFLE:
- case ISN_SILENT:
case ISN_SLICE:
case ISN_STORE:
case ISN_STOREDICT:
--- 7821,7826 ----
***************
*** 7819,7825 ****
case ISN_STRSLICE:
case ISN_THROW:
case ISN_TRY:
- case ISN_UNSILENT:
// nothing allocated
break;
}
--- 7834,7839 ----
*** ../vim-8.2.1899/src/vim9execute.c 2020-10-23 18:02:28.711453754 +0200
--- src/vim9execute.c 2020-10-24 22:32:19.873366315 +0200
***************
*** 832,839 ****
int save_suppress_errthrow = suppress_errthrow;
msglist_T **saved_msg_list = NULL;
msglist_T *private_msg_list = NULL;
! int save_msg_silent = -1;
! int save_emsg_silent = -1;

// Get pointer to item in the stack.
#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
--- 832,839 ----
int save_suppress_errthrow = suppress_errthrow;
msglist_T **saved_msg_list = NULL;
msglist_T *private_msg_list = NULL;
! cmdmod_T save_cmdmod;
! int restore_cmdmod = FALSE;

// Get pointer to item in the stack.
#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
***************
*** 2816,2837 ****
}
break;

! case ISN_SILENT:
! if (save_msg_silent == -1)
! save_msg_silent = msg_silent;
! ++msg_silent;
! if (iptr->isn_arg.number)
! {
! if (save_emsg_silent == -1)
! save_emsg_silent = emsg_silent;
! ++emsg_silent;
! }
break;

! case ISN_UNSILENT:
! --msg_silent;
! if (iptr->isn_arg.number)
! --emsg_silent;
break;

case ISN_SHUFFLE:
--- 2816,2834 ----
}
break;

! case ISN_CMDMOD:
! save_cmdmod = cmdmod;
! restore_cmdmod = TRUE;
! cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod;
! apply_cmdmod(&cmdmod);
break;

! case ISN_CMDMOD_REV:
! // filter regprog is owned by the instruction, don't free it
! cmdmod.cmod_filter_regmatch.regprog = NULL;
! undo_cmdmod(&cmdmod);
! cmdmod = save_cmdmod;
! restore_cmdmod = FALSE;
break;

case ISN_SHUFFLE:
***************
*** 2905,2914 ****
}
msg_list = saved_msg_list;

! if (save_msg_silent != -1)
! msg_silent = save_msg_silent;
! if (save_emsg_silent != -1)
! emsg_silent = save_emsg_silent;

failed_early:
// Free all local variables, but not arguments.
--- 2902,2913 ----
}
msg_list = saved_msg_list;

! if (restore_cmdmod)
! {
! cmdmod.cmod_filter_regmatch.regprog = NULL;
! undo_cmdmod(&cmdmod);
! cmdmod = save_cmdmod;
! }

failed_early:
// Free all local variables, but not arguments.
***************
*** 3527,3536 ****
(long)iptr->isn_arg.put.put_lnum);
break;

! case ISN_SILENT: smsg("%4d SILENT%s", current,
! iptr->isn_arg.number ? "!" : ""); break;
! case ISN_UNSILENT: smsg("%4d UNSILENT%s", current,
! iptr->isn_arg.number ? "!" : ""); break;

case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current,
iptr->isn_arg.shuffle.shfl_item,
--- 3526,3549 ----
(long)iptr->isn_arg.put.put_lnum);
break;

! // TODO: summarize modifiers
! case ISN_CMDMOD:
! {
! char_u *buf;
! int len = produce_cmdmods(
! NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
!
! buf = alloc(len + 1);
! if (buf != NULL)
! {
! (void)produce_cmdmods(
! buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
! smsg("%4d CMDMOD %s", current, buf);
! vim_free(buf);
! }
! break;
! }
! case ISN_CMDMOD_REV: smsg("%4d CMDMOD_REV", current); break;

case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current,
iptr->isn_arg.shuffle.shfl_item,
*** ../vim-8.2.1899/src/usercmd.c 2020-10-24 20:49:37.502683026 +0200
--- src/usercmd.c 2020-10-24 22:27:14.546124437 +0200
***************
*** 1235,1271 ****
}

/*
! * Add modifiers from "cmdmod.cmod_split" to "buf". Set "multi_mods" when one
* was added. Return the number of bytes added.
*/
size_t
! add_win_cmd_modifers(char_u *buf, int *multi_mods)
{
size_t result = 0;

// :aboveleft and :leftabove
! if (cmdmod.cmod_split & WSP_ABOVE)
result += add_cmd_modifier(buf, "aboveleft", multi_mods);
// :belowright and :rightbelow
! if (cmdmod.cmod_split & WSP_BELOW)
result += add_cmd_modifier(buf, "belowright", multi_mods);
// :botright
! if (cmdmod.cmod_split & WSP_BOT)
result += add_cmd_modifier(buf, "botright", multi_mods);

// :tab
! if (cmdmod.cmod_tab > 0)
result += add_cmd_modifier(buf, "tab", multi_mods);
// :topleft
! if (cmdmod.cmod_split & WSP_TOP)
result += add_cmd_modifier(buf, "topleft", multi_mods);
// :vertical
! if (cmdmod.cmod_split & WSP_VERT)
result += add_cmd_modifier(buf, "vertical", multi_mods);
return result;
}

/*
* Check for a <> code in a user command.
* "code" points to the '<'. "len" the length of the <> (inclusive).
* "buf" is where the result is to be added.
--- 1235,1338 ----
}

/*
! * Add modifiers from "cmod->cmod_split" to "buf". Set "multi_mods" when one
* was added. Return the number of bytes added.
*/
size_t
! add_win_cmd_modifers(char_u *buf, cmdmod_T *cmod, int *multi_mods)
{
size_t result = 0;

// :aboveleft and :leftabove
! if (cmod->cmod_split & WSP_ABOVE)
result += add_cmd_modifier(buf, "aboveleft", multi_mods);
// :belowright and :rightbelow
! if (cmod->cmod_split & WSP_BELOW)
result += add_cmd_modifier(buf, "belowright", multi_mods);
// :botright
! if (cmod->cmod_split & WSP_BOT)
result += add_cmd_modifier(buf, "botright", multi_mods);

// :tab
! if (cmod->cmod_tab > 0)
result += add_cmd_modifier(buf, "tab", multi_mods);
// :topleft
! if (cmod->cmod_split & WSP_TOP)
result += add_cmd_modifier(buf, "topleft", multi_mods);
// :vertical
! if (cmod->cmod_split & WSP_VERT)
result += add_cmd_modifier(buf, "vertical", multi_mods);
return result;
}

/*
+ * Generate text for the "cmod" command modifiers.
+ * If "buf" is NULL just return the length.
+ */
+ int
+ produce_cmdmods(char_u *buf, cmdmod_T *cmod, int quote)
+ {
+ int result = 0;
+ int multi_mods = 0;
+ int i;
+ typedef struct {
+ int flag;
+ char *name;
+ } mod_entry_T;
+ static mod_entry_T mod_entries[] = {
+ #ifdef FEAT_BROWSE_CMD
+ {CMOD_BROWSE, "browse"},
+ #endif
+ #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ {CMOD_CONFIRM, "confirm"},
+ #endif
+ {CMOD_HIDE, "hide"},
+ {CMOD_KEEPALT, "keepalt"},
+ {CMOD_KEEPJUMPS, "keepjumps"},
+ {CMOD_KEEPMARKS, "keepmarks"},
+ {CMOD_KEEPPATTERNS, "keeppatterns"},
+ {CMOD_LOCKMARKS, "lockmarks"},
+ {CMOD_NOSWAPFILE, "noswapfile"},
+ {CMOD_UNSILENT, "unsilent"},
+ {CMOD_NOAUTOCMD, "noautocmd"},
+ #ifdef HAVE_SANDBOX
+ {CMOD_SANDBOX, "sandbox"},
+ #endif
+ {0, NULL}
+ };
+
+ result = quote ? 2 : 0;
+ if (buf != NULL)
+ {
+ if (quote)
+ *buf++ = '"';
+ *buf = '\0';
+ }
+
+ // the modifiers that are simple flags
+ for (i = 0; mod_entries[i].name != NULL; ++i)
+ if (cmod->cmod_flags & mod_entries[i].flag)
+ result += add_cmd_modifier(buf, mod_entries[i].name, &multi_mods);
+
+ // :silent
+ if (cmod->cmod_flags & CMOD_SILENT)
+ result += add_cmd_modifier(buf,
+ (cmod->cmod_flags & CMOD_ERRSILENT) ? "silent!"
+ : "silent", &multi_mods);
+ // :verbose
+ if (p_verbose > 0)
+ result += add_cmd_modifier(buf, "verbose", &multi_mods);
+ // flags from cmod->cmod_split
+ result += add_win_cmd_modifers(buf, cmod, &multi_mods);
+ if (quote && buf != NULL)
+ {
+ buf += result - 2;
+ *buf = '"';
+ }
+ return result;
+ }
+
+ /*
* Check for a <> code in a user command.
* "code" points to the '<'. "len" the length of the <> (inclusive).
* "buf" is where the result is to be added.
***************
*** 1452,1513 ****

case ct_MODS:
{
! int multi_mods = 0;
! typedef struct {
! int flag;
! char *name;
! } mod_entry_T;
! static mod_entry_T mod_entries[] = {
! #ifdef FEAT_BROWSE_CMD
! {CMOD_BROWSE, "browse"},
! #endif
! #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
! {CMOD_CONFIRM, "confirm"},
! #endif
! {CMOD_HIDE, "hide"},
! {CMOD_KEEPALT, "keepalt"},
! {CMOD_KEEPJUMPS, "keepjumps"},
! {CMOD_KEEPMARKS, "keepmarks"},
! {CMOD_KEEPPATTERNS, "keeppatterns"},
! {CMOD_LOCKMARKS, "lockmarks"},
! {CMOD_NOSWAPFILE, "noswapfile"},
! {0, NULL}
! };
! int i;
!
! result = quote ? 2 : 0;
! if (buf != NULL)
! {
! if (quote)
! *buf++ = '"';
! *buf = '\0';
! }
!
! // the modifiers that are simple flags
! for (i = 0; mod_entries[i].name != NULL; ++i)
! if (cmdmod.cmod_flags & mod_entries[i].flag)
! result += add_cmd_modifier(buf, mod_entries[i].name,
! &multi_mods);
!
! // TODO: How to support :noautocmd?
! #ifdef HAVE_SANDBOX
! // TODO: How to support :sandbox?
! #endif
! // :silent
! if (msg_silent > 0)
! result += add_cmd_modifier(buf,
! emsg_silent > 0 ? "silent!" : "silent", &multi_mods);
! // TODO: How to support :unsilent?
! // :verbose
! if (p_verbose > 0)
! result += add_cmd_modifier(buf, "verbose", &multi_mods);
! // flags from cmdmod.cmod_split
! result += add_win_cmd_modifers(buf, &multi_mods);
! if (quote && buf != NULL)
! {
! buf += result - 2;
! *buf = '"';
! }
break;
}

--- 1519,1525 ----

case ct_MODS:
{
! result = produce_cmdmods(buf, &cmdmod, quote);
break;
}

*** ../vim-8.2.1899/src/proto/usercmd.pro 2020-04-13 21:16:18.039292270 +0200
--- src/proto/usercmd.pro 2020-10-24 22:27:17.942115967 +0200
***************
*** 14,19 ****
void ex_comclear(exarg_T *eap);
void uc_clear(garray_T *gap);
void ex_delcommand(exarg_T *eap);
! size_t add_win_cmd_modifers(char_u *buf, int *multi_mods);
void do_ucmd(exarg_T *eap);
/* vim: set ft=c : */
--- 14,20 ----
void ex_comclear(exarg_T *eap);
void uc_clear(garray_T *gap);
void ex_delcommand(exarg_T *eap);
! size_t add_win_cmd_modifers(char_u *buf, cmdmod_T *cmod, int *multi_mods);
! int produce_cmdmods(char_u *buf, cmdmod_T *cmod, int quote);
void do_ucmd(exarg_T *eap);
/* vim: set ft=c : */
*** ../vim-8.2.1899/src/scriptfile.c 2020-10-24 20:49:37.502683026 +0200
--- src/scriptfile.c 2020-10-24 22:25:13.686426083 +0200
***************
*** 1009,1015 ****
int multi_mods = 0;

buf[0] = NUL;
! (void)add_win_cmd_modifers(buf, &multi_mods);

vim_setenv((char_u *)"OPTWIN_CMD", buf);
cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
--- 1009,1015 ----
int multi_mods = 0;

buf[0] = NUL;
! (void)add_win_cmd_modifers(buf, &cmdmod, &multi_mods);

vim_setenv((char_u *)"OPTWIN_CMD", buf);
cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
*** ../vim-8.2.1899/src/testdir/test_vim9_disassemble.vim 2020-10-23 18:02:28.711453754 +0200
--- src/testdir/test_vim9_disassemble.vim 2020-10-24 22:33:12.893235083 +0200
***************
*** 1627,1641 ****
var res = execute('disass s:SilentMessage')
assert_match('<SNR>\d*_SilentMessage\_s*' ..
'silent echomsg "text"\_s*' ..
! '\d SILENT\_s*' ..
'\d PUSHS "text"\_s*' ..
'\d ECHOMSG 1\_s*' ..
! '\d UNSILENT\_s*' ..
'silent! echoerr "error"\_s*' ..
! '\d SILENT!\_s*' ..
'\d PUSHS "error"\_s*' ..
'\d ECHOERR 1\_s*' ..
! '\d UNSILENT!\_s*' ..
'\d PUSHNR 0\_s*' ..
'\d RETURN',
res)
--- 1627,1641 ----
var res = execute('disass s:SilentMessage')
assert_match('<SNR>\d*_SilentMessage\_s*' ..
'silent echomsg "text"\_s*' ..
! '\d CMDMOD silent\_s*' ..
'\d PUSHS "text"\_s*' ..
'\d ECHOMSG 1\_s*' ..
! '\d CMDMOD_REV\_s*' ..
'silent! echoerr "error"\_s*' ..
! '\d CMDMOD silent!\_s*' ..
'\d PUSHS "error"\_s*' ..
'\d ECHOERR 1\_s*' ..
! '\d CMDMOD_REV\_s*' ..
'\d PUSHNR 0\_s*' ..
'\d RETURN',
res)
*** ../vim-8.2.1899/src/version.c 2020-10-24 20:58:02.533121768 +0200
--- src/version.c 2020-10-24 23:06:40.563791658 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 1900,
/**/

--
I have a watch cat! Just break in and she'll watch.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages