mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 9.0.0379: cleaning up after writefile() is a hassle
Problem: Cleaning up after writefile() is a hassle. Solution: Add the 'D' flag to defer deleting the written file. Very useful in tests.
This commit is contained in:
@@ -845,41 +845,71 @@ set_ref_in_funcstacks(int copyID)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Ugly static to avoid passing the execution context around through many
|
||||
// layers.
|
||||
static ectx_T *current_ectx = NULL;
|
||||
|
||||
/*
|
||||
* Handle ISN_DEFER. Stack has a function reference and "argcount" arguments.
|
||||
* The local variable that lists deferred functions is "var_idx".
|
||||
* Returns OK or FAIL.
|
||||
* Return TRUE if currently executing a :def function.
|
||||
* Can be used by builtin functions only.
|
||||
*/
|
||||
static int
|
||||
add_defer_func(int var_idx, int argcount, ectx_T *ectx)
|
||||
int
|
||||
in_def_function(void)
|
||||
{
|
||||
return current_ectx != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an entry for a deferred function call to the currently executing
|
||||
* function.
|
||||
* Return the list or NULL when failed.
|
||||
*/
|
||||
static list_T *
|
||||
add_defer_item(int var_idx, int argcount, ectx_T *ectx)
|
||||
{
|
||||
typval_T *defer_tv = STACK_TV_VAR(var_idx);
|
||||
list_T *defer_l;
|
||||
typval_T *func_tv;
|
||||
list_T *l;
|
||||
int i;
|
||||
typval_T listval;
|
||||
|
||||
if (defer_tv->v_type != VAR_LIST)
|
||||
{
|
||||
// first time, allocate the list
|
||||
if (rettv_list_alloc(defer_tv) == FAIL)
|
||||
return FAIL;
|
||||
return NULL;
|
||||
}
|
||||
defer_l = defer_tv->vval.v_list;
|
||||
|
||||
l = list_alloc_with_items(argcount + 1);
|
||||
if (l == NULL)
|
||||
return FAIL;
|
||||
return NULL;
|
||||
listval.v_type = VAR_LIST;
|
||||
listval.vval.v_list = l;
|
||||
listval.v_lock = 0;
|
||||
if (list_insert_tv(defer_l, &listval, defer_l->lv_first) == FAIL)
|
||||
{
|
||||
vim_free(l);
|
||||
return FAIL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle ISN_DEFER. Stack has a function reference and "argcount" arguments.
|
||||
* The local variable that lists deferred functions is "var_idx".
|
||||
* Returns OK or FAIL.
|
||||
*/
|
||||
static int
|
||||
defer_command(int var_idx, int argcount, ectx_T *ectx)
|
||||
{
|
||||
list_T *l = add_defer_item(var_idx, argcount, ectx);
|
||||
int i;
|
||||
typval_T *func_tv;
|
||||
|
||||
if (l == NULL)
|
||||
return FAIL;
|
||||
|
||||
func_tv = STACK_TV_BOT(-argcount - 1);
|
||||
// TODO: check type is a funcref
|
||||
list_set_item(l, 0, func_tv);
|
||||
@@ -890,6 +920,43 @@ add_defer_func(int var_idx, int argcount, ectx_T *ectx)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a deferred function "name" with one argument "arg_tv".
|
||||
* Consumes "name", also on failure.
|
||||
* Only to be called when in_def_function() returns TRUE.
|
||||
*/
|
||||
int
|
||||
add_defer_function(char_u *name, int argcount, typval_T *argvars)
|
||||
{
|
||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||
+ current_ectx->ec_dfunc_idx;
|
||||
list_T *l;
|
||||
typval_T func_tv;
|
||||
int i;
|
||||
|
||||
if (dfunc->df_defer_var_idx == 0)
|
||||
{
|
||||
iemsg("df_defer_var_idx is zero");
|
||||
vim_free(func_tv.vval.v_string);
|
||||
return FAIL;
|
||||
}
|
||||
func_tv.v_type = VAR_FUNC;
|
||||
func_tv.v_lock = 0;
|
||||
func_tv.vval.v_string = name;
|
||||
|
||||
l = add_defer_item(dfunc->df_defer_var_idx - 1, 1, current_ectx);
|
||||
if (l == NULL)
|
||||
{
|
||||
vim_free(func_tv.vval.v_string);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
list_set_item(l, 0, &func_tv);
|
||||
for (i = 0; i < argcount; ++i)
|
||||
list_set_item(l, i + 1, argvars + i);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked when returning from a function: Invoke any deferred calls.
|
||||
*/
|
||||
@@ -1068,10 +1135,6 @@ call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
|
||||
return OK;
|
||||
}
|
||||
|
||||
// Ugly global to avoid passing the execution context around through many
|
||||
// layers.
|
||||
static ectx_T *current_ectx = NULL;
|
||||
|
||||
/*
|
||||
* Call a builtin function by index.
|
||||
*/
|
||||
@@ -3748,7 +3811,7 @@ exec_instructions(ectx_T *ectx)
|
||||
|
||||
// :defer func(arg)
|
||||
case ISN_DEFER:
|
||||
if (add_defer_func(iptr->isn_arg.defer.defer_var_idx,
|
||||
if (defer_command(iptr->isn_arg.defer.defer_var_idx,
|
||||
iptr->isn_arg.defer.defer_argcount, ectx) == FAIL)
|
||||
goto on_error;
|
||||
break;
|
||||
@@ -5121,7 +5184,7 @@ theend:
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the instructions from a VAR_INSTR typeval and put the result in
|
||||
* Execute the instructions from a VAR_INSTR typval and put the result in
|
||||
* "rettv".
|
||||
* Return OK or FAIL.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user