diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval/funcs.c | 21 | ||||
-rw-r--r-- | src/nvim/eval/userfunc.c | 24 |
2 files changed, 34 insertions, 11 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 99e511a7a4..66fd663e5e 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -9296,6 +9296,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) bool binary = false; bool append = false; + bool defer = false; bool do_fsync = !!p_fs; bool mkdir_p = false; if (argvars[2].v_type != VAR_UNKNOWN) { @@ -9309,6 +9310,8 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) binary = true; break; case 'a': append = true; break; + case 'D': + defer = true; break; case 's': do_fsync = true; break; case 'S': @@ -9328,6 +9331,12 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (fname == NULL) { return; } + + if (defer && get_current_funccal() == NULL) { + semsg(_(e_str_not_inside_function), "defer"); + return; + } + FileDescriptor fp; int error; if (*fname == NUL) { @@ -9336,9 +9345,17 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ((append ? kFileAppend : kFileTruncate) | (mkdir_p ? kFileMkDir : kFileCreate) | kFileCreate), 0666)) != 0) { - semsg(_("E482: Can't open file %s for writing: %s"), - fname, os_strerror(error)); + semsg(_("E482: Can't open file %s for writing: %s"), fname, os_strerror(error)); } else { + if (defer) { + typval_T tv = { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = xstrdup(fname), + }; + add_defer("delete", 1, &tv); + } + bool write_ok; if (argvars[0].v_type == VAR_BLOB) { write_ok = write_blob(&fp, argvars[0].vval.v_blob); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 9853622ee0..4b9bc1fdec 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -478,6 +478,7 @@ void emsg_funcname(const char *errmsg, const char *name) /// Get function arguments at "*arg" and advance it. /// Return them in "*argvars[MAX_FUNC_ARGS + 1]" and the count in "argcount". +/// On failure FAIL is returned but the "argvars[argcount]" are still set. static int get_func_arguments(char **arg, evalarg_T *const evalarg, int partial_argc, typval_T *argvars, int *argcount) { @@ -3119,16 +3120,28 @@ static int ex_defer_inner(char *name, char **arg, evalarg_T *const evalarg) { typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments int argcount = 0; // number of arguments found - int ret = FAIL; if (current_funccal == NULL) { semsg(_(e_str_not_inside_function), "defer"); return FAIL; } if (get_func_arguments(arg, evalarg, false, argvars, &argcount) == FAIL) { - goto theend; + while (--argcount >= 0) { + tv_clear(&argvars[argcount]); + } + return FAIL; } + add_defer(name, argcount, argvars); + return OK; +} + +/// Add a deferred call for "name" with arguments "argvars[argcount]". +/// Consumes "argvars[]". +/// Caller must check that current_funccal is not NULL. +void add_defer(char *name, int argcount_arg, typval_T *argvars) +{ char *saved_name = xstrdup(name); + int argcount = argcount_arg; if (current_funccal->fc_defer.ga_itemsize == 0) { ga_init(¤t_funccal->fc_defer, sizeof(defer_T), 10); @@ -3140,13 +3153,6 @@ static int ex_defer_inner(char *name, char **arg, evalarg_T *const evalarg) argcount--; dr->dr_argvars[argcount] = argvars[argcount]; } - ret = OK; - -theend: - while (--argcount >= 0) { - tv_clear(&argvars[argcount]); - } - return ret; } /// Invoked after a function has finished: invoke ":defer" functions. |