From fcb79ffc40b93d5e0d165e1d001d073c83b8617e Mon Sep 17 00:00:00 2001 From: Sebastian Witte Date: Wed, 8 Jul 2015 07:40:28 +0200 Subject: [PATCH] Implement API function to call functions #2979 Remove static modifier from func_call Move MAX_FUNC_ARGS definnition from eval.c to eval.h --- src/nvim/api/vim.c | 50 ++++++++++++++++++++++++++++++++ src/nvim/eval.c | 3 +- src/nvim/eval.h | 3 ++ test/functional/api/vim_spec.lua | 9 ++++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 22bdbc2ee5..f5dadb00ea 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -164,6 +164,56 @@ Object vim_eval(String str, Error *err) return rv; } +/// Call the given function with the given arguments stored in an array. +/// +/// @param fname Function to call +/// @param args Functions arguments packed in an Array +/// @param[out] err Details of an error that may have occurred +/// @return Result of the function call +Object vim_call_function(String fname, Array args, Error *err) + FUNC_ATTR_DEFERRED +{ + Object rv = OBJECT_INIT; + if (args.size > MAX_FUNC_ARGS) { + api_set_error(err, Validation, + _("Function called with too many arguments.")); + return rv; + } + + // Convert the arguments in args from Object to typval_T values + typval_T vim_args[MAX_FUNC_ARGS + 1]; + size_t i = 0; // also used for freeing the variables + for (; i < args.size; i++) { + if (!object_to_vim(args.items[i], &vim_args[i], err)) { + goto free_vim_args; + } + } + + try_start(); + // Call the function + typval_T rettv; + int dummy; + int r = call_func((char_u *) fname.data, (int) fname.size, + &rettv, (int) args.size, vim_args, + curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, + true, + NULL); + if (r == FAIL) { + api_set_error(err, Exception, _("Error calling function.")); + } + if (!try_end(err)) { + rv = vim_to_object(&rettv); + } + clear_tv(&rettv); + +free_vim_args: + while (i > 0) { + clear_tv(&vim_args[--i]); + } + + return rv; +} + /// Calculates the number of display cells `str` occupies, tab is counted as /// one cell. /// diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9957643c8d..b45428e7e7 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -290,7 +290,6 @@ static ufunc_T dumuf; #define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j] #define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] -#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */ #define VAR_SHORT_LEN 20 /* short variable name length */ #define FIXVAR_CNT 12 /* number of fixed variables */ @@ -6867,7 +6866,7 @@ get_func_tv ( * Return FAIL when the function can't be called, OK otherwise. * Also returns OK when an error was encountered while executing the function. */ -static int +int call_func ( char_u *funcname, /* name of the function */ int len, /* length of "name" */ diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 75e3b247f3..bf48bc74b8 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -68,6 +68,9 @@ enum { VV_LEN, /* number of v: vars */ }; +/// Maximum number of function arguments +#define MAX_FUNC_ARGS 20 + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.h.generated.h" #endif diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index c158c26341..9e880a4f04 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -34,6 +34,15 @@ describe('vim_* functions', function() end) end) + describe('call_function', function() + it('works', function() + nvim('call_function', 'setqflist', {{{ filename = 'something', lnum = 17}}, 'r'}) + eq(17, nvim('call_function', 'getqflist', {})[1].lnum) + eq(17, nvim('call_function', 'eval', {17})) + eq('foo', nvim('call_function', 'simplify', {'this/./is//redundant/../../../foo'})) + end) + end) + describe('strwidth', function() it('works', function() eq(3, nvim('strwidth', 'abc'))