aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/api/vim.c50
-rw-r--r--src/nvim/eval.c3
-rw-r--r--src/nvim/eval.h3
-rw-r--r--test/functional/api/vim_spec.lua9
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'))