diff options
Diffstat (limited to 'src/nvim/eval/funcs.c')
-rw-r--r-- | src/nvim/eval/funcs.c | 143 |
1 files changed, 132 insertions, 11 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 60229e1ebc..650b4e3882 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -117,8 +117,12 @@ char_u *get_function_name(expand_T *xp, int idx) intidx = -1; if (intidx < 0) { name = get_user_func_name(xp, idx); - if (name != NULL) + if (name != NULL) { + if (*name != '<' && STRNCMP("g:", xp->xp_pattern, 2) == 0) { + return cat_prefix_varname('g', name); + } return name; + } } while ((size_t)++intidx < ARRAY_SIZE(functions) && functions[intidx].name[0] == '\0') { @@ -3976,6 +3980,87 @@ static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1); } +// +// Move the window wp into a new split of targetwin in a given direction +// +static void win_move_into_split(win_T *wp, win_T *targetwin, + int size, int flags) +{ + int dir; + int height = wp->w_height; + win_T *oldwin = curwin; + + if (wp == targetwin) { + return; + } + + // Jump to the target window + if (curwin != targetwin) { + win_goto(targetwin); + } + + // Remove the old window and frame from the tree of frames + (void)winframe_remove(wp, &dir, NULL); + win_remove(wp, NULL); + last_status(false); // may need to remove last status line + (void)win_comp_pos(); // recompute window positions + + // Split a window on the desired side and put the old window there + (void)win_split_ins(size, flags, wp, dir); + + // If splitting horizontally, try to preserve height + if (size == 0 && !(flags & WSP_VERT)) { + win_setheight_win(height, wp); + if (p_ea) { + win_equal(wp, true, 'v'); + } + } + + if (oldwin != curwin) { + win_goto(oldwin); + } +} + +// "win_splitmove()" function +static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + win_T *wp; + win_T *targetwin; + int flags = 0, size = 0; + + wp = find_win_by_nr_or_id(&argvars[0]); + targetwin = find_win_by_nr_or_id(&argvars[1]); + + if (wp == NULL || targetwin == NULL || wp == targetwin + || !win_valid(wp) || !win_valid(targetwin) + || win_valid_floating(wp) || win_valid_floating(targetwin)) { + EMSG(_(e_invalwindow)); + rettv->vval.v_number = -1; + return; + } + + if (argvars[2].v_type != VAR_UNKNOWN) { + dict_T *d; + dictitem_T *di; + + if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL) { + EMSG(_(e_invarg)); + return; + } + + d = argvars[2].vval.v_dict; + if (tv_dict_get_number(d, "vertical")) { + flags |= WSP_VERT; + } + if ((di = tv_dict_find(d, "rightbelow", -1)) != NULL) { + flags |= tv_get_number(&di->di_tv) ? WSP_BELOW : WSP_ABOVE; + } + size = tv_dict_get_number(d, "size"); + } + + win_move_into_split(wp, targetwin, size, flags); +} + // "getwinpos({timeout})" function static void f_getwinpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -8724,8 +8809,6 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (set_tagstack(wp, d, action) == OK) { rettv->vval.v_number = 0; - } else { - EMSG(_(e_listreq)); } } @@ -10106,6 +10189,38 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len); } +// "strptime({format}, {timestring})" function +static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + char fmt_buf[NUMBUFLEN]; + char str_buf[NUMBUFLEN]; + + struct tm tmval = { + .tm_isdst = -1, + }; + char *fmt = (char *)tv_get_string_buf(&argvars[0], fmt_buf); + char *str = (char *)tv_get_string_buf(&argvars[1], str_buf); + + vimconv_T conv = { + .vc_type = CONV_NONE, + }; + char_u *enc = enc_locale(); + convert_setup(&conv, p_enc, enc); + if (conv.vc_type != CONV_NONE) { + fmt = (char *)string_convert(&conv, (char_u *)fmt, NULL); + } + if (fmt == NULL + || os_strptime(str, fmt, &tmval) == NULL + || (rettv->vval.v_number = mktime(&tmval)) == -1) { + rettv->vval.v_number = 0; + } + if (conv.vc_type != CONV_NONE) { + xfree(fmt); + } + convert_setup(&conv, NULL, NULL); + xfree(enc); +} + /* * "strridx()" function */ @@ -10731,7 +10846,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) INTEGER_OBJ(pid), false, false, &err); api_clear_error(&err); - channel_terminal_open(chan); + channel_terminal_open(curbuf, chan); channel_create_event(chan, NULL); } @@ -11293,17 +11408,23 @@ static void f_winnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int winnr = 1; garray_T ga; char_u buf[50]; ga_init(&ga, (int)sizeof(char), 70); - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height); - ga_concat(&ga, buf); - sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width); - ga_concat(&ga, buf); - ++winnr; + + // Do this twice to handle some window layouts properly. + for (int i = 0; i < 2; i++) { + int winnr = 1; + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + snprintf((char *)buf, sizeof(buf), "%dresize %d|", winnr, + wp->w_height); + ga_concat(&ga, buf); + snprintf((char *)buf, sizeof(buf), "vert %dresize %d|", winnr, + wp->w_width); + ga_concat(&ga, buf); + winnr++; + } } ga_append(&ga, NUL); |