diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 6e9f89bbb5..96c008b0e0 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6877,6 +6877,7 @@ static struct fst { { "setbufvar", 3, 3, f_setbufvar }, { "setcharsearch", 1, 1, f_setcharsearch }, { "setcmdpos", 1, 1, f_setcmdpos }, + { "setfperm", 2, 2, f_setfperm }, { "setline", 2, 2, f_setline }, { "setloclist", 2, 4, f_setloclist }, { "setmatches", 1, 1, f_setmatches }, @@ -10684,6 +10685,7 @@ static void f_has(typval_T *argvars, typval_T *rettv) "tablineat", "tag_binary", "tag_old_static", + "termguicolors", "termresponse", "textobjects", "title", @@ -14445,6 +14447,38 @@ static void f_setcmdpos(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = set_cmdline_pos(pos); } + +/// "setfperm({fname}, {mode})" function +static void f_setfperm(typval_T *argvars, typval_T *rettv) +{ + rettv->vval.v_number = 0; + + char_u *fname = get_tv_string_chk(&argvars[0]); + if (fname == NULL) { + return; + } + + char_u modebuf[NUMBUFLEN]; + char_u *mode_str = get_tv_string_buf_chk(&argvars[1], modebuf); + if (mode_str == NULL) { + return; + } + if (STRLEN(mode_str) != 9) { + EMSG2(_(e_invarg2), mode_str); + return; + } + + int mask = 1; + int mode = 0; + for (int i = 8; i >= 0; i--) { + if (mode_str[i] != '-') { + mode |= mask; + } + mask = mask << 1; + } + rettv->vval.v_number = os_setperm(fname, mode) == OK; +} + /* * "setline()" function */ @@ -18122,6 +18156,25 @@ static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, in return HI2DI(hi); } +// Get function call environment based on backtrace debug level +static funccall_T *get_funccal(void) +{ + funccall_T *funccal = current_funccal; + if (debug_backtrace_level > 0) { + for (int i = 0; i < debug_backtrace_level; i++) { + funccall_T *temp_funccal = funccal->caller; + if (temp_funccal) { + funccal = temp_funccal; + } else { + // backtrace level overflow. reset to max + debug_backtrace_level = i; + } + } + } + + return funccal; +} + // Find the dict and hashtable used for a variable name. Set "varname" to the // start of name without ':'. static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) @@ -18146,7 +18199,11 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) return &compat_hashtab; } - *d = current_funccal ? ¤t_funccal->l_vars : &globvardict; + if (current_funccal == NULL) { + *d = &globvardict; + } else { + *d = &get_funccal()->l_vars; // l: variable + } goto end; } @@ -18168,9 +18225,9 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) } else if (*name == 'v') { // v: variable *d = &vimvardict; } else if (*name == 'a' && current_funccal != NULL) { // function argument - *d = ¤t_funccal->l_avars; + *d = &get_funccal()->l_avars; } else if (*name == 'l' && current_funccal != NULL) { // local variable - *d = ¤t_funccal->l_vars; + *d = &get_funccal()->l_vars; } else if (*name == 's' // script variable && current_SID > 0 && current_SID <= ga_scripts.ga_len) { *d = &SCRIPT_SV(current_SID)->sv_dict; @@ -21700,6 +21757,18 @@ static void term_resize(uint16_t width, uint16_t height, void *d) pty_process_resize(&data->proc.pty, width, height); } +static inline void term_delayed_free(void **argv) +{ + TerminalJobData *j = argv[0]; + if (j->in.pending_reqs || j->out.pending_reqs || j->err.pending_reqs) { + queue_put(j->events, term_delayed_free, 1, j); + return; + } + + terminal_destroy(j->term); + term_job_data_decref(j); +} + static void term_close(void *d) { TerminalJobData *data = d; @@ -21707,8 +21776,7 @@ static void term_close(void *d) data->exited = true; process_stop((Process *)&data->proc); } - terminal_destroy(data->term); - term_job_data_decref(d); + queue_put(data->events, term_delayed_free, 1, data); } static void term_job_data_decref(TerminalJobData *data) |