aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c101
1 files changed, 75 insertions, 26 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 9be4cea059..21c7cdee7d 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -12,7 +12,9 @@
#include <string.h>
#include "auto/config.h"
+#include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
@@ -947,38 +949,42 @@ int skip_expr(char **pp, evalarg_T *const evalarg)
return res;
}
+/// Convert "tv" to a string.
+///
+/// @param convert when true convert a List into a sequence of lines.
+///
+/// @return an allocated string.
+static char *typval2string(typval_T *tv, bool convert)
+{
+ if (convert && tv->v_type == VAR_LIST) {
+ garray_T ga;
+ ga_init(&ga, (int)sizeof(char), 80);
+ if (tv->vval.v_list != NULL) {
+ tv_list_join(&ga, tv->vval.v_list, "\n");
+ if (tv_list_len(tv->vval.v_list) > 0) {
+ ga_append(&ga, NL);
+ }
+ }
+ ga_append(&ga, NUL);
+ return (char *)ga.ga_data;
+ }
+ return xstrdup(tv_get_string(tv));
+}
+
/// Top level evaluation function, returning a string.
///
-/// @param convert when true convert a List into a sequence of lines and convert
-/// a Float to a String.
+/// @param convert when true convert a List into a sequence of lines.
///
-/// @return pointer to allocated memory, or NULL for failure.
+/// @return pointer to allocated memory, or NULL for failure.
char *eval_to_string(char *arg, bool convert)
{
typval_T tv;
char *retval;
- garray_T ga;
if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) {
retval = NULL;
} else {
- if (convert && tv.v_type == VAR_LIST) {
- ga_init(&ga, (int)sizeof(char), 80);
- if (tv.vval.v_list != NULL) {
- tv_list_join(&ga, tv.vval.v_list, "\n");
- if (tv_list_len(tv.vval.v_list) > 0) {
- ga_append(&ga, NL);
- }
- }
- ga_append(&ga, NUL);
- retval = (char *)ga.ga_data;
- } else if (convert && tv.v_type == VAR_FLOAT) {
- char numbuf[NUMBUFLEN];
- vim_snprintf(numbuf, NUMBUFLEN, "%g", tv.vval.v_float);
- retval = xstrdup(numbuf);
- } else {
- retval = xstrdup(tv_get_string(&tv));
- }
+ retval = typval2string(&tv, convert);
tv_clear(&tv);
}
clear_evalarg(&EVALARG_EVALUATE, NULL);
@@ -990,7 +996,7 @@ char *eval_to_string(char *arg, bool convert)
/// textlock.
///
/// @param use_sandbox when true, use the sandbox.
-char *eval_to_string_safe(char *arg, int use_sandbox)
+char *eval_to_string_safe(char *arg, const bool use_sandbox)
{
char *retval;
funccal_entry_T funccal_entry;
@@ -1263,11 +1269,13 @@ void *call_func_retlist(const char *func, int argc, typval_T *argv)
/// Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
/// it in "*cp". Doesn't give error messages.
-int eval_foldexpr(char *arg, int *cp)
+int eval_foldexpr(win_T *wp, int *cp)
{
- typval_T tv;
- varnumber_T retval;
- int use_sandbox = was_set_insecurely(curwin, "foldexpr", OPT_LOCAL);
+ const sctx_T saved_sctx = current_sctx;
+ const bool use_sandbox = was_set_insecurely(wp, "foldexpr", OPT_LOCAL);
+
+ char *arg = wp->w_p_fde;
+ current_sctx = wp->w_p_script_ctx[WV_FDE].script_ctx;
emsg_off++;
if (use_sandbox) {
@@ -1275,6 +1283,9 @@ int eval_foldexpr(char *arg, int *cp)
}
textlock++;
*cp = NUL;
+
+ typval_T tv;
+ varnumber_T retval;
if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) {
retval = 0;
} else {
@@ -1294,16 +1305,54 @@ int eval_foldexpr(char *arg, int *cp)
}
tv_clear(&tv);
}
+
emsg_off--;
if (use_sandbox) {
sandbox--;
}
textlock--;
clear_evalarg(&EVALARG_EVALUATE, NULL);
+ current_sctx = saved_sctx;
return (int)retval;
}
+/// Evaluate 'foldtext', returning an Array or a String (NULL_STRING on failure).
+Object eval_foldtext(win_T *wp)
+{
+ const bool use_sandbox = was_set_insecurely(wp, "foldtext", OPT_LOCAL);
+ char *arg = wp->w_p_fdt;
+ funccal_entry_T funccal_entry;
+
+ save_funccal(&funccal_entry);
+ if (use_sandbox) {
+ sandbox++;
+ }
+ textlock++;
+
+ typval_T tv;
+ Object retval;
+ if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) {
+ retval = STRING_OBJ(NULL_STRING);
+ } else {
+ if (tv.v_type == VAR_LIST) {
+ retval = vim_to_object(&tv);
+ } else {
+ retval = STRING_OBJ(cstr_to_string(tv_get_string(&tv)));
+ }
+ tv_clear(&tv);
+ }
+ clear_evalarg(&EVALARG_EVALUATE, NULL);
+
+ if (use_sandbox) {
+ sandbox--;
+ }
+ textlock--;
+ restore_funccal();
+
+ return retval;
+}
+
/// Get an lvalue
///
/// Lvalue may be