changeset 17620:072efa9ca875 v8.1.1807

patch 8.1.1807: more functions can be used as a method commit https://github.com/vim/vim/commit/25e42231d3ee27feec2568fa4be2aa2bfba82ae5 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Aug 4 15:04:10 2019 +0200 patch 8.1.1807: more functions can be used as a method Problem: More functions can be used as a method. Solution: Add append(), appendbufline(), assert_equal(), etc. Also add the :eval command.
author Bram Moolenaar <Bram@vim.org>
date Sun, 04 Aug 2019 15:15:06 +0200
parents f9976baad617
children b5fcb04abf6a
files runtime/doc/eval.txt runtime/doc/testing.txt src/evalfunc.c src/ex_cmdidxs.h src/ex_cmds.h src/ex_eval.c src/proto/ex_eval.pro src/testdir/test_method.vim src/version.c
diffstat 9 files changed, 690 insertions(+), 576 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*	For Vim version 8.1.  Last change: 2019 Jul 30
+*eval.txt*	For Vim version 8.1.  Last change: 2019 Aug 04
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -840,12 +840,14 @@ Expression syntax summary, from least to
 	expr8[expr1 : expr1]	substring of a String or sublist of a |List|
 	expr8.name		entry in a |Dictionary|
 	expr8(expr1, ...)	function call with |Funcref| variable
+	expr8->name(expr1, ...)	|method| call
 
 |expr9|	number			number constant
 	"string"		string constant, backslash is special
 	'string'		string constant, ' is doubled
 	[expr1, ...]		|List|
 	{expr1: expr1, ...}	|Dictionary|
+	#{key: expr1, ...}	|Dictionary|
 	&option			option value
 	(expr1)			nested expression
 	variable		internal variable
@@ -1111,10 +1113,10 @@ expr8							*expr8*
 -----
 This expression is either |expr9| or a sequence of the alternatives below,
 in any order.  E.g., these are all possible:
-	expr9[expr1].name
-	expr9.name[expr1]
-	expr9(expr1, ...)[expr1].name
-	expr9->(expr1, ...)[expr1]
+	expr8[expr1].name
+	expr8.name[expr1]
+	expr8(expr1, ...)[expr1].name
+	expr8->(expr1, ...)[expr1]
 Evaluation is always from left to right.
 
 
@@ -1217,10 +1219,17 @@ When expr8 is a |Funcref| type variable,
 
 expr8->name([args])	method call			*method*
 
-For global methods this is the same as: >
+For methods that are also available as global functions this is the same as: >
 	name(expr8 [, args])
 There can also be methods specifically for the type of "expr8".
 
+"->name(" must not contain white space.  There can be white space before "->"
+and after the "(".
+
+This allows for chaining, using the type that the method returns: >
+	mylist->filter(filterexpr)->map(mapexpr)->sort()->join()
+<
+
 							*expr9*
 number
 ------
@@ -2906,6 +2915,10 @@ append({lnum}, {text})					*append()*
 			:let failed = append(line('$'), "# THE END")
 			:let failed = append(0, ["Chapter 1", "the beginning"])
 
+<		Can also be used as a |method| after a List: >
+			mylist->append(lnum)
+
+
 appendbufline({expr}, {lnum}, {text})			*appendbufline()*
 		Like |append()| but append the text in buffer {expr}.
 
@@ -2921,8 +2934,11 @@ appendbufline({expr}, {lnum}, {text})			
 		error message is given. Example: >
 			:let failed = appendbufline(13, 0, "# THE START")
 <
-							*argc()*
-argc([{winid}])
+		Can also be used as a |method| after a List: >
+			mylist->appendbufline(buf, lnum)
+
+
+argc([{winid}])					*argc()*
 		The result is the number of files in the argument list.  See
 		|arglist|.
 		If {winid} is not supplied, the argument list of the current
@@ -3762,6 +3778,9 @@ eval({string})	Evaluate {string} and ret
 		of them.  Also works for |Funcref|s that refer to existing
 		functions.
 
+		Can also be used as a |method|: >
+			argv->join()->eval()
+
 eventhandler()						*eventhandler()*
 		Returns 1 when inside an event handler.  That is that Vim got
 		interrupted while waiting for the user to type a character,
@@ -4115,7 +4134,12 @@ filereadable({file})					*filereadable()
 		expression, which is used as a String.
 		If you don't care about the file being readable you can use
 		|glob()|.
-							*file_readable()*
+		{file} is used as-is, you may want to expand wildcards first: >
+			echo filereadable('~/.vimrc')
+			0
+			echo filereadable(expand('~/.vimrc'))
+			1
+<							*file_readable()*
 		Obsolete name: file_readable().
 
 
@@ -7998,9 +8022,9 @@ sha256({string})						*sha256()*
 
 shellescape({string} [, {special}])			*shellescape()*
 		Escape {string} for use as a shell command argument.
-		On MS-Windows and MS-DOS, when 'shellslash' is not set, it
-		will enclose {string} in double quotes and double all double
-		quotes within {string}.
+		On MS-Windows, when 'shellslash' is not set, it will enclose
+		{string} in double quotes and double all double quotes within
+		{string}.
 		Otherwise it will enclose {string} in single quotes and
 		replace all "'" with "'\''".
 
@@ -10047,6 +10071,10 @@ This function can then be called with: >
 The recursiveness of user functions is restricted with the |'maxfuncdepth'|
 option.
 
+It is also possible to use `:eval`.  It does not support a range, but does
+allow for method chaining, e.g.: >
+	eval GetList()->Filter()->append('$')
+
 
 AUTOMATICALLY LOADING FUNCTIONS ~
 							*autoload-functions*
@@ -10498,6 +10526,20 @@ text...
 			Unlock the internal variable {name}.  Does the
 			opposite of |:lockvar|.
 
+							*:eval*
+:eval {expr}		Evaluate {expr} and discard the result.  Example: >
+				:eval Getlist()->Filter()->append('$')
+
+<			The expression is supposed to have a side effect,
+			since the resulting value is not used.  In the example
+			the `append()` call appends the List with text to the
+			buffer.  This is similar to `:call` but works with any
+			expression.
+
+			The command can be shortened to `:ev` or `:eva`, but
+			these are hard to recognize and therefore not to be
+			used.
+
 
 :if {expr1}			*:if* *:end* *:endif* *:en* *E171* *E579* *E580*
 :en[dif]		Execute the commands until the next matching ":else"
--- a/runtime/doc/testing.txt
+++ b/runtime/doc/testing.txt
@@ -1,4 +1,4 @@
-*testing.txt*	For Vim version 8.1.  Last change: 2019 Jul 28
+*testing.txt*	For Vim version 8.1.  Last change: 2019 Aug 04
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -222,7 +222,11 @@ assert_equal({expected}, {actual} [, {ms
 <		Will result in a string to be added to |v:errors|:
 	test.vim line 12: Expected 'foo' but got 'bar' ~
 
-							*assert_equalfile()*
+		Can also be used as a |method|: >
+			mylist->assert_equal([1, 2, 3])
+
+
+<							*assert_equalfile()*
 assert_equalfile({fname-one}, {fname-two})
 		When the files {fname-one} and {fname-two} do not contain
 		exactly the same text an error message is added to |v:errors|.
@@ -294,7 +298,10 @@ assert_notequal({expected}, {actual} [, 
 		|v:errors| when {expected} and {actual} are equal.
 		Also see |assert-return|.
 
-							*assert_notmatch()*
+		Can also be used as a |method|: >
+			mylist->assert_notequal([1, 2, 3])
+
+<							*assert_notmatch()*
 assert_notmatch({pattern}, {actual} [, {msg}])
 		The opposite of `assert_match()`: add an error message to
 		|v:errors| when {pattern} matches {actual}.
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -414,610 +414,620 @@ static void f_xor(typval_T *argvars, typ
  */
 typedef struct
 {
-    char	*f_name;	/* function name */
-    char	f_min_argc;	/* minimal number of arguments */
-    char	f_max_argc;	/* maximal number of arguments */
+    char	*f_name;	// function name
+    char	f_min_argc;	// minimal number of arguments
+    char	f_max_argc;	// maximal number of arguments
+    char	f_argtype;	// for method: FEARG_ values
     void	(*f_func)(typval_T *args, typval_T *rvar);
-				/* implementation of function */
+				// implementation of function
 } funcentry_T;
 
 static funcentry_T global_functions[] =
 {
 #ifdef FEAT_FLOAT
-    {"abs",		1, 1, f_abs},
-    {"acos",		1, 1, f_acos},	/* WJMc */
-#endif
-    {"add",		2, 2, f_add},
-    {"and",		2, 2, f_and},
-    {"append",		2, 2, f_append},
-    {"appendbufline",	3, 3, f_appendbufline},
-    {"argc",		0, 1, f_argc},
-    {"argidx",		0, 0, f_argidx},
-    {"arglistid",	0, 2, f_arglistid},
-    {"argv",		0, 2, f_argv},
+    {"abs",		1, 1, 0, f_abs},
+    {"acos",		1, 1, 0, f_acos},	// WJMc
+#endif
+    {"add",		2, 2, 0, f_add},
+    {"and",		2, 2, 0, f_and},
+    {"append",		2, 2, 0, f_append},
+    {"appendbufline",	3, 3, 0, f_appendbufline},
+    {"argc",		0, 1, 0, f_argc},
+    {"argidx",		0, 0, 0, f_argidx},
+    {"arglistid",	0, 2, 0, f_arglistid},
+    {"argv",		0, 2, 0, f_argv},
 #ifdef FEAT_FLOAT
-    {"asin",		1, 1, f_asin},	/* WJMc */
-#endif
-    {"assert_beeps",	1, 2, f_assert_beeps},
-    {"assert_equal",	2, 3, f_assert_equal},
-    {"assert_equalfile", 2, 2, f_assert_equalfile},
-    {"assert_exception", 1, 2, f_assert_exception},
-    {"assert_fails",	1, 3, f_assert_fails},
-    {"assert_false",	1, 2, f_assert_false},
-    {"assert_inrange",	3, 4, f_assert_inrange},
-    {"assert_match",	2, 3, f_assert_match},
-    {"assert_notequal",	2, 3, f_assert_notequal},
-    {"assert_notmatch",	2, 3, f_assert_notmatch},
-    {"assert_report",	1, 1, f_assert_report},
-    {"assert_true",	1, 2, f_assert_true},
+    {"asin",		1, 1, 0, f_asin},	// WJMc
+#endif
+    {"assert_beeps",	1, 2, 0, f_assert_beeps},
+    {"assert_equal",	2, 3, 0, f_assert_equal},
+    {"assert_equalfile", 2, 2, 0, f_assert_equalfile},
+    {"assert_exception", 1, 2, 0, f_assert_exception},
+    {"assert_fails",	1, 3, 0, f_assert_fails},
+    {"assert_false",	1, 2, 0, f_assert_false},
+    {"assert_inrange",	3, 4, 0, f_assert_inrange},
+    {"assert_match",	2, 3, 0, f_assert_match},
+    {"assert_notequal",	2, 3, 0, f_assert_notequal},
+    {"assert_notmatch",	2, 3, 0, f_assert_notmatch},
+    {"assert_report",	1, 1, 0, f_assert_report},
+    {"assert_true",	1, 2, 0, f_assert_true},
 #ifdef FEAT_FLOAT
-    {"atan",		1, 1, f_atan},
-    {"atan2",		2, 2, f_atan2},
+    {"atan",		1, 1, 0, f_atan},
+    {"atan2",		2, 2, 0, f_atan2},
 #endif
 #ifdef FEAT_BEVAL
-    {"balloon_gettext",	0, 0, f_balloon_gettext},
-    {"balloon_show",	1, 1, f_balloon_show},
+    {"balloon_gettext",	0, 0, 0, f_balloon_gettext},
+    {"balloon_show",	1, 1, 0, f_balloon_show},
 # if defined(FEAT_BEVAL_TERM)
-    {"balloon_split",	1, 1, f_balloon_split},
+    {"balloon_split",	1, 1, 0, f_balloon_split},
 # endif
 #endif
-    {"browse",		4, 4, f_browse},
-    {"browsedir",	2, 2, f_browsedir},
-    {"bufadd",		1, 1, f_bufadd},
-    {"bufexists",	1, 1, f_bufexists},
-    {"buffer_exists",	1, 1, f_bufexists},	/* obsolete */
-    {"buffer_name",	1, 1, f_bufname},	/* obsolete */
-    {"buffer_number",	1, 1, f_bufnr},		/* obsolete */
-    {"buflisted",	1, 1, f_buflisted},
-    {"bufload",		1, 1, f_bufload},
-    {"bufloaded",	1, 1, f_bufloaded},
-    {"bufname",		1, 1, f_bufname},
-    {"bufnr",		1, 2, f_bufnr},
-    {"bufwinid",	1, 1, f_bufwinid},
-    {"bufwinnr",	1, 1, f_bufwinnr},
-    {"byte2line",	1, 1, f_byte2line},
-    {"byteidx",		2, 2, f_byteidx},
-    {"byteidxcomp",	2, 2, f_byteidxcomp},
-    {"call",		2, 3, f_call},
+    {"browse",		4, 4, 0, f_browse},
+    {"browsedir",	2, 2, 0, f_browsedir},
+    {"bufadd",		1, 1, 0, f_bufadd},
+    {"bufexists",	1, 1, 0, f_bufexists},
+    {"buffer_exists",	1, 1, 0, f_bufexists},	// obsolete
+    {"buffer_name",	1, 1, 0, f_bufname},	// obsolete
+    {"buffer_number",	1, 1, 0, f_bufnr},	// obsolete
+    {"buflisted",	1, 1, 0, f_buflisted},
+    {"bufload",		1, 1, 0, f_bufload},
+    {"bufloaded",	1, 1, 0, f_bufloaded},
+    {"bufname",		1, 1, 0, f_bufname},
+    {"bufnr",		1, 2, 0, f_bufnr},
+    {"bufwinid",	1, 1, 0, f_bufwinid},
+    {"bufwinnr",	1, 1, 0, f_bufwinnr},
+    {"byte2line",	1, 1, 0, f_byte2line},
+    {"byteidx",		2, 2, 0, f_byteidx},
+    {"byteidxcomp",	2, 2, 0, f_byteidxcomp},
+    {"call",		2, 3, 0, f_call},
 #ifdef FEAT_FLOAT
-    {"ceil",		1, 1, f_ceil},
+    {"ceil",		1, 1, 0, f_ceil},
 #endif
 #ifdef FEAT_JOB_CHANNEL
-    {"ch_canread",	1, 1, f_ch_canread},
-    {"ch_close",	1, 1, f_ch_close},
-    {"ch_close_in",	1, 1, f_ch_close_in},
-    {"ch_evalexpr",	2, 3, f_ch_evalexpr},
-    {"ch_evalraw",	2, 3, f_ch_evalraw},
-    {"ch_getbufnr",	2, 2, f_ch_getbufnr},
-    {"ch_getjob",	1, 1, f_ch_getjob},
-    {"ch_info",		1, 1, f_ch_info},
-    {"ch_log",		1, 2, f_ch_log},
-    {"ch_logfile",	1, 2, f_ch_logfile},
-    {"ch_open",		1, 2, f_ch_open},
-    {"ch_read",		1, 2, f_ch_read},
-    {"ch_readblob",	1, 2, f_ch_readblob},
-    {"ch_readraw",	1, 2, f_ch_readraw},
-    {"ch_sendexpr",	2, 3, f_ch_sendexpr},
-    {"ch_sendraw",	2, 3, f_ch_sendraw},
-    {"ch_setoptions",	2, 2, f_ch_setoptions},
-    {"ch_status",	1, 2, f_ch_status},
-#endif
-    {"changenr",	0, 0, f_changenr},
-    {"char2nr",		1, 2, f_char2nr},
-    {"chdir",		1, 1, f_chdir},
-    {"cindent",		1, 1, f_cindent},
-    {"clearmatches",	0, 1, f_clearmatches},
-    {"col",		1, 1, f_col},
+    {"ch_canread",	1, 1, 0, f_ch_canread},
+    {"ch_close",	1, 1, 0, f_ch_close},
+    {"ch_close_in",	1, 1, 0, f_ch_close_in},
+    {"ch_evalexpr",	2, 3, 0, f_ch_evalexpr},
+    {"ch_evalraw",	2, 3, 0, f_ch_evalraw},
+    {"ch_getbufnr",	2, 2, 0, f_ch_getbufnr},
+    {"ch_getjob",	1, 1, 0, f_ch_getjob},
+    {"ch_info",		1, 1, 0, f_ch_info},
+    {"ch_log",		1, 2, 0, f_ch_log},
+    {"ch_logfile",	1, 2, 0, f_ch_logfile},
+    {"ch_open",		1, 2, 0, f_ch_open},
+    {"ch_read",		1, 2, 0, f_ch_read},
+    {"ch_readblob",	1, 2, 0, f_ch_readblob},
+    {"ch_readraw",	1, 2, 0, f_ch_readraw},
+    {"ch_sendexpr",	2, 3, 0, f_ch_sendexpr},
+    {"ch_sendraw",	2, 3, 0, f_ch_sendraw},
+    {"ch_setoptions",	2, 2, 0, f_ch_setoptions},
+    {"ch_status",	1, 2, 0, f_ch_status},
+#endif
+    {"changenr",	0, 0, 0, f_changenr},
+    {"char2nr",		1, 2, 0, f_char2nr},
+    {"chdir",		1, 1, 0, f_chdir},
+    {"cindent",		1, 1, 0, f_cindent},
+    {"clearmatches",	0, 1, 0, f_clearmatches},
+    {"col",		1, 1, 0, f_col},
 #if defined(FEAT_INS_EXPAND)
-    {"complete",	2, 2, f_complete},
-    {"complete_add",	1, 1, f_complete_add},
-    {"complete_check",	0, 0, f_complete_check},
-    {"complete_info",	0, 1, f_complete_info},
-#endif
-    {"confirm",		1, 4, f_confirm},
-    {"copy",		1, 1, f_copy},
+    {"complete",	2, 2, 0, f_complete},
+    {"complete_add",	1, 1, 0, f_complete_add},
+    {"complete_check",	0, 0, 0, f_complete_check},
+    {"complete_info",	0, 1, 0, f_complete_info},
+#endif
+    {"confirm",		1, 4, 0, f_confirm},
+    {"copy",		1, 1, 0, f_copy},
 #ifdef FEAT_FLOAT
-    {"cos",		1, 1, f_cos},
-    {"cosh",		1, 1, f_cosh},
-#endif
-    {"count",		2, 4, f_count},
-    {"cscope_connection",0,3, f_cscope_connection},
-    {"cursor",		1, 3, f_cursor},
+    {"cos",		1, 1, 0, f_cos},
+    {"cosh",		1, 1, 0, f_cosh},
+#endif
+    {"count",		2, 4, 0, f_count},
+    {"cscope_connection",0,3, 0, f_cscope_connection},
+    {"cursor",		1, 3, 0, f_cursor},
 #ifdef MSWIN
-    {"debugbreak",	1, 1, f_debugbreak},
-#endif
-    {"deepcopy",	1, 2, f_deepcopy},
-    {"delete",		1, 2, f_delete},
-    {"deletebufline",	2, 3, f_deletebufline},
-    {"did_filetype",	0, 0, f_did_filetype},
-    {"diff_filler",	1, 1, f_diff_filler},
-    {"diff_hlID",	2, 2, f_diff_hlID},
-    {"empty",		1, 1, f_empty},
-    {"environ",		0, 0, f_environ},
-    {"escape",		2, 2, f_escape},
-    {"eval",		1, 1, f_eval},
-    {"eventhandler",	0, 0, f_eventhandler},
-    {"executable",	1, 1, f_executable},
-    {"execute",		1, 2, f_execute},
-    {"exepath",		1, 1, f_exepath},
-    {"exists",		1, 1, f_exists},
+    {"debugbreak",	1, 1, 0, f_debugbreak},
+#endif
+    {"deepcopy",	1, 2, 0, f_deepcopy},
+    {"delete",		1, 2, 0, f_delete},
+    {"deletebufline",	2, 3, 0, f_deletebufline},
+    {"did_filetype",	0, 0, 0, f_did_filetype},
+    {"diff_filler",	1, 1, 0, f_diff_filler},
+    {"diff_hlID",	2, 2, 0, f_diff_hlID},
+    {"empty",		1, 1, 0, f_empty},
+    {"environ",		0, 0, 0, f_environ},
+    {"escape",		2, 2, 0, f_escape},
+    {"eval",		1, 1, 0, f_eval},
+    {"eventhandler",	0, 0, 0, f_eventhandler},
+    {"executable",	1, 1, 0, f_executable},
+    {"execute",		1, 2, 0, f_execute},
+    {"exepath",		1, 1, 0, f_exepath},
+    {"exists",		1, 1, 0, f_exists},
 #ifdef FEAT_FLOAT
-    {"exp",		1, 1, f_exp},
-#endif
-    {"expand",		1, 3, f_expand},
-    {"expandcmd",	1, 1, f_expandcmd},
-    {"extend",		2, 3, f_extend},
-    {"feedkeys",	1, 2, f_feedkeys},
-    {"file_readable",	1, 1, f_filereadable},	/* obsolete */
-    {"filereadable",	1, 1, f_filereadable},
-    {"filewritable",	1, 1, f_filewritable},
-    {"filter",		2, 2, f_filter},
-    {"finddir",		1, 3, f_finddir},
-    {"findfile",	1, 3, f_findfile},
+    {"exp",		1, 1, 0, f_exp},
+#endif
+    {"expand",		1, 3, 0, f_expand},
+    {"expandcmd",	1, 1, 0, f_expandcmd},
+    {"extend",		2, 3, 0, f_extend},
+    {"feedkeys",	1, 2, 0, f_feedkeys},
+    {"file_readable",	1, 1, 0, f_filereadable},	// obsolete
+    {"filereadable",	1, 1, 0, f_filereadable},
+    {"filewritable",	1, 1, 0, f_filewritable},
+    {"filter",		2, 2, 0, f_filter},
+    {"finddir",		1, 3, 0, f_finddir},
+    {"findfile",	1, 3, 0, f_findfile},
 #ifdef FEAT_FLOAT
-    {"float2nr",	1, 1, f_float2nr},
-    {"floor",		1, 1, f_floor},
-    {"fmod",		2, 2, f_fmod},
-#endif
-    {"fnameescape",	1, 1, f_fnameescape},
-    {"fnamemodify",	2, 2, f_fnamemodify},
-    {"foldclosed",	1, 1, f_foldclosed},
-    {"foldclosedend",	1, 1, f_foldclosedend},
-    {"foldlevel",	1, 1, f_foldlevel},
-    {"foldtext",	0, 0, f_foldtext},
-    {"foldtextresult",	1, 1, f_foldtextresult},
-    {"foreground",	0, 0, f_foreground},
-    {"funcref",		1, 3, f_funcref},
-    {"function",	1, 3, f_function},
-    {"garbagecollect",	0, 1, f_garbagecollect},
-    {"get",		2, 3, f_get},
-    {"getbufinfo",	0, 1, f_getbufinfo},
-    {"getbufline",	2, 3, f_getbufline},
-    {"getbufvar",	2, 3, f_getbufvar},
-    {"getchangelist",	1, 1, f_getchangelist},
-    {"getchar",		0, 1, f_getchar},
-    {"getcharmod",	0, 0, f_getcharmod},
-    {"getcharsearch",	0, 0, f_getcharsearch},
-    {"getcmdline",	0, 0, f_getcmdline},
-    {"getcmdpos",	0, 0, f_getcmdpos},
-    {"getcmdtype",	0, 0, f_getcmdtype},
-    {"getcmdwintype",	0, 0, f_getcmdwintype},
+    {"float2nr",	1, 1, 0, f_float2nr},
+    {"floor",		1, 1, 0, f_floor},
+    {"fmod",		2, 2, 0, f_fmod},
+#endif
+    {"fnameescape",	1, 1, 0, f_fnameescape},
+    {"fnamemodify",	2, 2, 0, f_fnamemodify},
+    {"foldclosed",	1, 1, 0, f_foldclosed},
+    {"foldclosedend",	1, 1, 0, f_foldclosedend},
+    {"foldlevel",	1, 1, 0, f_foldlevel},
+    {"foldtext",	0, 0, 0, f_foldtext},
+    {"foldtextresult",	1, 1, 0, f_foldtextresult},
+    {"foreground",	0, 0, 0, f_foreground},
+    {"funcref",		1, 3, 0, f_funcref},
+    {"function",	1, 3, 0, f_function},
+    {"garbagecollect",	0, 1, 0, f_garbagecollect},
+    {"get",		2, 3, 0, f_get},
+    {"getbufinfo",	0, 1, 0, f_getbufinfo},
+    {"getbufline",	2, 3, 0, f_getbufline},
+    {"getbufvar",	2, 3, 0, f_getbufvar},
+    {"getchangelist",	1, 1, 0, f_getchangelist},
+    {"getchar",		0, 1, 0, f_getchar},
+    {"getcharmod",	0, 0, 0, f_getcharmod},
+    {"getcharsearch",	0, 0, 0, f_getcharsearch},
+    {"getcmdline",	0, 0, 0, f_getcmdline},
+    {"getcmdpos",	0, 0, 0, f_getcmdpos},
+    {"getcmdtype",	0, 0, 0, f_getcmdtype},
+    {"getcmdwintype",	0, 0, 0, f_getcmdwintype},
 #if defined(FEAT_CMDL_COMPL)
-    {"getcompletion",	2, 3, f_getcompletion},
-#endif
-    {"getcurpos",	0, 0, f_getcurpos},
-    {"getcwd",		0, 2, f_getcwd},
-    {"getenv",		1, 1, f_getenv},
-    {"getfontname",	0, 1, f_getfontname},
-    {"getfperm",	1, 1, f_getfperm},
-    {"getfsize",	1, 1, f_getfsize},
-    {"getftime",	1, 1, f_getftime},
-    {"getftype",	1, 1, f_getftype},
-    {"getjumplist",	0, 2, f_getjumplist},
-    {"getline",		1, 2, f_getline},
-    {"getloclist",	1, 2, f_getloclist},
-    {"getmatches",	0, 1, f_getmatches},
-    {"getpid",		0, 0, f_getpid},
-    {"getpos",		1, 1, f_getpos},
-    {"getqflist",	0, 1, f_getqflist},
-    {"getreg",		0, 3, f_getreg},
-    {"getregtype",	0, 1, f_getregtype},
-    {"gettabinfo",	0, 1, f_gettabinfo},
-    {"gettabvar",	2, 3, f_gettabvar},
-    {"gettabwinvar",	3, 4, f_gettabwinvar},
-    {"gettagstack",	0, 1, f_gettagstack},
-    {"getwininfo",	0, 1, f_getwininfo},
-    {"getwinpos",	0, 1, f_getwinpos},
-    {"getwinposx",	0, 0, f_getwinposx},
-    {"getwinposy",	0, 0, f_getwinposy},
-    {"getwinvar",	2, 3, f_getwinvar},
-    {"glob",		1, 4, f_glob},
-    {"glob2regpat",	1, 1, f_glob2regpat},
-    {"globpath",	2, 5, f_globpath},
-    {"has",		1, 1, f_has},
-    {"has_key",		2, 2, f_has_key},
-    {"haslocaldir",	0, 2, f_haslocaldir},
-    {"hasmapto",	1, 3, f_hasmapto},
-    {"highlightID",	1, 1, f_hlID},		/* obsolete */
-    {"highlight_exists",1, 1, f_hlexists},	/* obsolete */
-    {"histadd",		2, 2, f_histadd},
-    {"histdel",		1, 2, f_histdel},
-    {"histget",		1, 2, f_histget},
-    {"histnr",		1, 1, f_histnr},
-    {"hlID",		1, 1, f_hlID},
-    {"hlexists",	1, 1, f_hlexists},
-    {"hostname",	0, 0, f_hostname},
-    {"iconv",		3, 3, f_iconv},
-    {"indent",		1, 1, f_indent},
-    {"index",		2, 4, f_index},
-    {"input",		1, 3, f_input},
-    {"inputdialog",	1, 3, f_inputdialog},
-    {"inputlist",	1, 1, f_inputlist},
-    {"inputrestore",	0, 0, f_inputrestore},
-    {"inputsave",	0, 0, f_inputsave},
-    {"inputsecret",	1, 2, f_inputsecret},
-    {"insert",		2, 3, f_insert},
-    {"invert",		1, 1, f_invert},
-    {"isdirectory",	1, 1, f_isdirectory},
+    {"getcompletion",	2, 3, 0, f_getcompletion},
+#endif
+    {"getcurpos",	0, 0, 0, f_getcurpos},
+    {"getcwd",		0, 2, 0, f_getcwd},
+    {"getenv",		1, 1, 0, f_getenv},
+    {"getfontname",	0, 1, 0, f_getfontname},
+    {"getfperm",	1, 1, 0, f_getfperm},
+    {"getfsize",	1, 1, 0, f_getfsize},
+    {"getftime",	1, 1, 0, f_getftime},
+    {"getftype",	1, 1, 0, f_getftype},
+    {"getjumplist",	0, 2, 0, f_getjumplist},
+    {"getline",		1, 2, 0, f_getline},
+    {"getloclist",	1, 2, 0, f_getloclist},
+    {"getmatches",	0, 1, 0, f_getmatches},
+    {"getpid",		0, 0, 0, f_getpid},
+    {"getpos",		1, 1, 0, f_getpos},
+    {"getqflist",	0, 1, 0, f_getqflist},
+    {"getreg",		0, 3, 0, f_getreg},
+    {"getregtype",	0, 1, 0, f_getregtype},
+    {"gettabinfo",	0, 1, 0, f_gettabinfo},
+    {"gettabvar",	2, 3, 0, f_gettabvar},
+    {"gettabwinvar",	3, 4, 0, f_gettabwinvar},
+    {"gettagstack",	0, 1, 0, f_gettagstack},
+    {"getwininfo",	0, 1, 0, f_getwininfo},
+    {"getwinpos",	0, 1, 0, f_getwinpos},
+    {"getwinposx",	0, 0, 0, f_getwinposx},
+    {"getwinposy",	0, 0, 0, f_getwinposy},
+    {"getwinvar",	2, 3, 0, f_getwinvar},
+    {"glob",		1, 4, 0, f_glob},
+    {"glob2regpat",	1, 1, 0, f_glob2regpat},
+    {"globpath",	2, 5, 0, f_globpath},
+    {"has",		1, 1, 0, f_has},
+    {"has_key",		2, 2, 0, f_has_key},
+    {"haslocaldir",	0, 2, 0, f_haslocaldir},
+    {"hasmapto",	1, 3, 0, f_hasmapto},
+    {"highlightID",	1, 1, 0, f_hlID},	// obsolete
+    {"highlight_exists",1, 1, 0, f_hlexists},	// obsolete
+    {"histadd",		2, 2, 0, f_histadd},
+    {"histdel",		1, 2, 0, f_histdel},
+    {"histget",		1, 2, 0, f_histget},
+    {"histnr",		1, 1, 0, f_histnr},
+    {"hlID",		1, 1, 0, f_hlID},
+    {"hlexists",	1, 1, 0, f_hlexists},
+    {"hostname",	0, 0, 0, f_hostname},
+    {"iconv",		3, 3, 0, f_iconv},
+    {"indent",		1, 1, 0, f_indent},
+    {"index",		2, 4, 0, f_index},
+    {"input",		1, 3, 0, f_input},
+    {"inputdialog",	1, 3, 0, f_inputdialog},
+    {"inputlist",	1, 1, 0, f_inputlist},
+    {"inputrestore",	0, 0, 0, f_inputrestore},
+    {"inputsave",	0, 0, 0, f_inputsave},
+    {"inputsecret",	1, 2, 0, f_inputsecret},
+    {"insert",		2, 3, 0, f_insert},
+    {"invert",		1, 1, 0, f_invert},
+    {"isdirectory",	1, 1, 0, f_isdirectory},
 #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
-    {"isinf",		1, 1, f_isinf},
-#endif
-    {"islocked",	1, 1, f_islocked},
+    {"isinf",		1, 1, 0, f_isinf},
+#endif
+    {"islocked",	1, 1, 0, f_islocked},
 #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
-    {"isnan",		1, 1, f_isnan},
-#endif
-    {"items",		1, 1, f_items},
+    {"isnan",		1, 1, 0, f_isnan},
+#endif
+    {"items",		1, 1, 0, f_items},
 #ifdef FEAT_JOB_CHANNEL
-    {"job_getchannel",	1, 1, f_job_getchannel},
-    {"job_info",	0, 1, f_job_info},
-    {"job_setoptions",	2, 2, f_job_setoptions},
-    {"job_start",	1, 2, f_job_start},
-    {"job_status",	1, 1, f_job_status},
-    {"job_stop",	1, 2, f_job_stop},
-#endif
-    {"join",		1, 2, f_join},
-    {"js_decode",	1, 1, f_js_decode},
-    {"js_encode",	1, 1, f_js_encode},
-    {"json_decode",	1, 1, f_json_decode},
-    {"json_encode",	1, 1, f_json_encode},
-    {"keys",		1, 1, f_keys},
-    {"last_buffer_nr",	0, 0, f_last_buffer_nr},/* obsolete */
-    {"len",		1, 1, f_len},
-    {"libcall",		3, 3, f_libcall},
-    {"libcallnr",	3, 3, f_libcallnr},
-    {"line",		1, 1, f_line},
-    {"line2byte",	1, 1, f_line2byte},
-    {"lispindent",	1, 1, f_lispindent},
-    {"list2str",	1, 2, f_list2str},
-    {"listener_add",	1, 2, f_listener_add},
-    {"listener_flush",	0, 1, f_listener_flush},
-    {"listener_remove",	1, 1, f_listener_remove},
-    {"localtime",	0, 0, f_localtime},
+    {"job_getchannel",	1, 1, 0, f_job_getchannel},
+    {"job_info",	0, 1, 0, f_job_info},
+    {"job_setoptions",	2, 2, 0, f_job_setoptions},
+    {"job_start",	1, 2, 0, f_job_start},
+    {"job_status",	1, 1, 0, f_job_status},
+    {"job_stop",	1, 2, 0, f_job_stop},
+#endif
+    {"join",		1, 2, 0, f_join},
+    {"js_decode",	1, 1, 0, f_js_decode},
+    {"js_encode",	1, 1, 0, f_js_encode},
+    {"json_decode",	1, 1, 0, f_json_decode},
+    {"json_encode",	1, 1, 0, f_json_encode},
+    {"keys",		1, 1, 0, f_keys},
+    {"last_buffer_nr",	0, 0, 0, f_last_buffer_nr}, // obsolete
+    {"len",		1, 1, 0, f_len},
+    {"libcall",		3, 3, 0, f_libcall},
+    {"libcallnr",	3, 3, 0, f_libcallnr},
+    {"line",		1, 1, 0, f_line},
+    {"line2byte",	1, 1, 0, f_line2byte},
+    {"lispindent",	1, 1, 0, f_lispindent},
+    {"list2str",	1, 2, 0, f_list2str},
+    {"listener_add",	1, 2, 0, f_listener_add},
+    {"listener_flush",	0, 1, 0, f_listener_flush},
+    {"listener_remove",	1, 1, 0, f_listener_remove},
+    {"localtime",	0, 0, 0, f_localtime},
 #ifdef FEAT_FLOAT
-    {"log",		1, 1, f_log},
-    {"log10",		1, 1, f_log10},
+    {"log",		1, 1, 0, f_log},
+    {"log10",		1, 1, 0, f_log10},
 #endif
 #ifdef FEAT_LUA
-    {"luaeval",		1, 2, f_luaeval},
-#endif
-    {"map",		2, 2, f_map},
-    {"maparg",		1, 4, f_maparg},
-    {"mapcheck",	1, 3, f_mapcheck},
-    {"match",		2, 4, f_match},
-    {"matchadd",	2, 5, f_matchadd},
-    {"matchaddpos",	2, 5, f_matchaddpos},
-    {"matcharg",	1, 1, f_matcharg},
-    {"matchdelete",	1, 2, f_matchdelete},
-    {"matchend",	2, 4, f_matchend},
-    {"matchlist",	2, 4, f_matchlist},
-    {"matchstr",	2, 4, f_matchstr},
-    {"matchstrpos",	2, 4, f_matchstrpos},
-    {"max",		1, 1, f_max},
-    {"min",		1, 1, f_min},
-    {"mkdir",		1, 3, f_mkdir},
-    {"mode",		0, 1, f_mode},
+    {"luaeval",		1, 2, 0, f_luaeval},
+#endif
+    {"map",		2, 2, 0, f_map},
+    {"maparg",		1, 4, 0, f_maparg},
+    {"mapcheck",	1, 3, 0, f_mapcheck},
+    {"match",		2, 4, 0, f_match},
+    {"matchadd",	2, 5, 0, f_matchadd},
+    {"matchaddpos",	2, 5, 0, f_matchaddpos},
+    {"matcharg",	1, 1, 0, f_matcharg},
+    {"matchdelete",	1, 2, 0, f_matchdelete},
+    {"matchend",	2, 4, 0, f_matchend},
+    {"matchlist",	2, 4, 0, f_matchlist},
+    {"matchstr",	2, 4, 0, f_matchstr},
+    {"matchstrpos",	2, 4, 0, f_matchstrpos},
+    {"max",		1, 1, 0, f_max},
+    {"min",		1, 1, 0, f_min},
+    {"mkdir",		1, 3, 0, f_mkdir},
+    {"mode",		0, 1, 0, f_mode},
 #ifdef FEAT_MZSCHEME
-    {"mzeval",		1, 1, f_mzeval},
-#endif
-    {"nextnonblank",	1, 1, f_nextnonblank},
-    {"nr2char",		1, 2, f_nr2char},
-    {"or",		2, 2, f_or},
-    {"pathshorten",	1, 1, f_pathshorten},
+    {"mzeval",		1, 1, 0, f_mzeval},
+#endif
+    {"nextnonblank",	1, 1, 0, f_nextnonblank},
+    {"nr2char",		1, 2, 0, f_nr2char},
+    {"or",		2, 2, 0, f_or},
+    {"pathshorten",	1, 1, 0, f_pathshorten},
 #ifdef FEAT_PERL
-    {"perleval",	1, 1, f_perleval},
+    {"perleval",	1, 1, 0, f_perleval},
 #endif
 #ifdef FEAT_TEXT_PROP
-    {"popup_atcursor",	2, 2, f_popup_atcursor},
-    {"popup_beval",	2, 2, f_popup_beval},
-    {"popup_clear",	0, 0, f_popup_clear},
-    {"popup_close",	1, 2, f_popup_close},
-    {"popup_create",	2, 2, f_popup_create},
-    {"popup_dialog",	2, 2, f_popup_dialog},
-    {"popup_filter_menu", 2, 2, f_popup_filter_menu},
-    {"popup_filter_yesno", 2, 2, f_popup_filter_yesno},
-    {"popup_getoptions", 1, 1, f_popup_getoptions},
-    {"popup_getpos",	1, 1, f_popup_getpos},
-    {"popup_getpreview", 0, 0, f_popup_getpreview},
-    {"popup_hide",	1, 1, f_popup_hide},
-    {"popup_locate",	2, 2, f_popup_locate},
-    {"popup_menu",	2, 2, f_popup_menu},
-    {"popup_move",	2, 2, f_popup_move},
-    {"popup_notification", 2, 2, f_popup_notification},
-    {"popup_setoptions", 2, 2, f_popup_setoptions},
-    {"popup_settext",	2, 2, f_popup_settext},
-    {"popup_show",	1, 1, f_popup_show},
+    {"popup_atcursor",	2, 2, 0, f_popup_atcursor},
+    {"popup_beval",	2, 2, 0, f_popup_beval},
+    {"popup_clear",	0, 0, 0, f_popup_clear},
+    {"popup_close",	1, 2, 0, f_popup_close},
+    {"popup_create",	2, 2, 0, f_popup_create},
+    {"popup_dialog",	2, 2, 0, f_popup_dialog},
+    {"popup_filter_menu", 2, 2, 0, f_popup_filter_menu},
+    {"popup_filter_yesno", 2, 2, 0, f_popup_filter_yesno},
+    {"popup_getoptions", 1, 1, 0, f_popup_getoptions},
+    {"popup_getpos",	1, 1, 0, f_popup_getpos},
+    {"popup_getpreview", 0, 0, 0, f_popup_getpreview},
+    {"popup_hide",	1, 1, 0, f_popup_hide},
+    {"popup_locate",	2, 2, 0, f_popup_locate},
+    {"popup_menu",	2, 2, 0, f_popup_menu},
+    {"popup_move",	2, 2, 0, f_popup_move},
+    {"popup_notification", 2, 2, 0, f_popup_notification},
+    {"popup_setoptions", 2, 2, 0, f_popup_setoptions},
+    {"popup_settext",	2, 2, 0, f_popup_settext},
+    {"popup_show",	1, 1, 0, f_popup_show},
 #endif
 #ifdef FEAT_FLOAT
-    {"pow",		2, 2, f_pow},
-#endif
-    {"prevnonblank",	1, 1, f_prevnonblank},
-    {"printf",		1, 19, f_printf},
+    {"pow",		2, 2, 0, f_pow},
+#endif
+    {"prevnonblank",	1, 1, 0, f_prevnonblank},
+    {"printf",		1, 19, 0, f_printf},
 #ifdef FEAT_JOB_CHANNEL
-    {"prompt_setcallback", 2, 2, f_prompt_setcallback},
-    {"prompt_setinterrupt", 2, 2, f_prompt_setinterrupt},
-    {"prompt_setprompt", 2, 2, f_prompt_setprompt},
+    {"prompt_setcallback", 2, 2, 0, f_prompt_setcallback},
+    {"prompt_setinterrupt", 2, 2, 0, f_prompt_setinterrupt},
+    {"prompt_setprompt", 2, 2, 0, f_prompt_setprompt},
 #endif
 #ifdef FEAT_TEXT_PROP
-    {"prop_add",	3, 3, f_prop_add},
-    {"prop_clear",	1, 3, f_prop_clear},
-    {"prop_list",	1, 2, f_prop_list},
-    {"prop_remove",	1, 3, f_prop_remove},
-    {"prop_type_add",	2, 2, f_prop_type_add},
-    {"prop_type_change", 2, 2, f_prop_type_change},
-    {"prop_type_delete", 1, 2, f_prop_type_delete},
-    {"prop_type_get",	1, 2, f_prop_type_get},
-    {"prop_type_list",	0, 1, f_prop_type_list},
-#endif
-    {"pumvisible",	0, 0, f_pumvisible},
+    {"prop_add",	3, 3, 0, f_prop_add},
+    {"prop_clear",	1, 3, 0, f_prop_clear},
+    {"prop_list",	1, 2, 0, f_prop_list},
+    {"prop_remove",	1, 3, 0, f_prop_remove},
+    {"prop_type_add",	2, 2, 0, f_prop_type_add},
+    {"prop_type_change", 2, 2, 0, f_prop_type_change},
+    {"prop_type_delete", 1, 2, 0, f_prop_type_delete},
+    {"prop_type_get",	1, 2, 0, f_prop_type_get},
+    {"prop_type_list",	0, 1, 0, f_prop_type_list},
+#endif
+    {"pumvisible",	0, 0, 0, f_pumvisible},
 #ifdef FEAT_PYTHON3
-    {"py3eval",		1, 1, f_py3eval},
+    {"py3eval",		1, 1, 0, f_py3eval},
 #endif
 #ifdef FEAT_PYTHON
-    {"pyeval",		1, 1, f_pyeval},
+    {"pyeval",		1, 1, 0, f_pyeval},
 #endif
 #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
-    {"pyxeval",		1, 1, f_pyxeval},
-#endif
-    {"range",		1, 3, f_range},
-    {"readdir",		1, 2, f_readdir},
-    {"readfile",	1, 3, f_readfile},
-    {"reg_executing",	0, 0, f_reg_executing},
-    {"reg_recording",	0, 0, f_reg_recording},
-    {"reltime",		0, 2, f_reltime},
+    {"pyxeval",		1, 1, 0, f_pyxeval},
+#endif
+    {"range",		1, 3, 0, f_range},
+    {"readdir",		1, 2, 0, f_readdir},
+    {"readfile",	1, 3, 0, f_readfile},
+    {"reg_executing",	0, 0, 0, f_reg_executing},
+    {"reg_recording",	0, 0, 0, f_reg_recording},
+    {"reltime",		0, 2, 0, f_reltime},
 #ifdef FEAT_FLOAT
-    {"reltimefloat",	1, 1, f_reltimefloat},
-#endif
-    {"reltimestr",	1, 1, f_reltimestr},
-    {"remote_expr",	2, 4, f_remote_expr},
-    {"remote_foreground", 1, 1, f_remote_foreground},
-    {"remote_peek",	1, 2, f_remote_peek},
-    {"remote_read",	1, 2, f_remote_read},
-    {"remote_send",	2, 3, f_remote_send},
-    {"remote_startserver", 1, 1, f_remote_startserver},
-    {"remove",		2, 3, f_remove},
-    {"rename",		2, 2, f_rename},
-    {"repeat",		2, 2, f_repeat},
-    {"resolve",		1, 1, f_resolve},
-    {"reverse",		1, 1, f_reverse},
+    {"reltimefloat",	1, 1, 0, f_reltimefloat},
+#endif
+    {"reltimestr",	1, 1, 0, f_reltimestr},
+    {"remote_expr",	2, 4, 0, f_remote_expr},
+    {"remote_foreground", 1, 1, 0, f_remote_foreground},
+    {"remote_peek",	1, 2, 0, f_remote_peek},
+    {"remote_read",	1, 2, 0, f_remote_read},
+    {"remote_send",	2, 3, 0, f_remote_send},
+    {"remote_startserver", 1, 1, 0, f_remote_startserver},
+    {"remove",		2, 3, 0, f_remove},
+    {"rename",		2, 2, 0, f_rename},
+    {"repeat",		2, 2, 0, f_repeat},
+    {"resolve",		1, 1, 0, f_resolve},
+    {"reverse",		1, 1, 0, f_reverse},
 #ifdef FEAT_FLOAT
-    {"round",		1, 1, f_round},
+    {"round",		1, 1, 0, f_round},
 #endif
 #ifdef FEAT_RUBY
-    {"rubyeval",	1, 1, f_rubyeval},
-#endif
-    {"screenattr",	2, 2, f_screenattr},
-    {"screenchar",	2, 2, f_screenchar},
-    {"screenchars",	2, 2, f_screenchars},
-    {"screencol",	0, 0, f_screencol},
-    {"screenpos",	3, 3, f_screenpos},
-    {"screenrow",	0, 0, f_screenrow},
-    {"screenstring",	2, 2, f_screenstring},
-    {"search",		1, 4, f_search},
-    {"searchdecl",	1, 3, f_searchdecl},
-    {"searchpair",	3, 7, f_searchpair},
-    {"searchpairpos",	3, 7, f_searchpairpos},
-    {"searchpos",	1, 4, f_searchpos},
-    {"server2client",	2, 2, f_server2client},
-    {"serverlist",	0, 0, f_serverlist},
-    {"setbufline",	3, 3, f_setbufline},
-    {"setbufvar",	3, 3, f_setbufvar},
-    {"setcharsearch",	1, 1, f_setcharsearch},
-    {"setcmdpos",	1, 1, f_setcmdpos},
-    {"setenv",		2, 2, f_setenv},
-    {"setfperm",	2, 2, f_setfperm},
-    {"setline",		2, 2, f_setline},
-    {"setloclist",	2, 4, f_setloclist},
-    {"setmatches",	1, 2, f_setmatches},
-    {"setpos",		2, 2, f_setpos},
-    {"setqflist",	1, 3, f_setqflist},
-    {"setreg",		2, 3, f_setreg},
-    {"settabvar",	3, 3, f_settabvar},
-    {"settabwinvar",	4, 4, f_settabwinvar},
-    {"settagstack",	2, 3, f_settagstack},
-    {"setwinvar",	3, 3, f_setwinvar},
+    {"rubyeval",	1, 1, 0, f_rubyeval},
+#endif
+    {"screenattr",	2, 2, 0, f_screenattr},
+    {"screenchar",	2, 2, 0, f_screenchar},
+    {"screenchars",	2, 2, 0, f_screenchars},
+    {"screencol",	0, 0, 0, f_screencol},
+    {"screenpos",	3, 3, 0, f_screenpos},
+    {"screenrow",	0, 0, 0, f_screenrow},
+    {"screenstring",	2, 2, 0, f_screenstring},
+    {"search",		1, 4, 0, f_search},
+    {"searchdecl",	1, 3, 0, f_searchdecl},
+    {"searchpair",	3, 7, 0, f_searchpair},
+    {"searchpairpos",	3, 7, 0, f_searchpairpos},
+    {"searchpos",	1, 4, 0, f_searchpos},
+    {"server2client",	2, 2, 0, f_server2client},
+    {"serverlist",	0, 0, 0, f_serverlist},
+    {"setbufline",	3, 3, 0, f_setbufline},
+    {"setbufvar",	3, 3, 0, f_setbufvar},
+    {"setcharsearch",	1, 1, 0, f_setcharsearch},
+    {"setcmdpos",	1, 1, 0, f_setcmdpos},
+    {"setenv",		2, 2, 0, f_setenv},
+    {"setfperm",	2, 2, 0, f_setfperm},
+    {"setline",		2, 2, 0, f_setline},
+    {"setloclist",	2, 4, 0, f_setloclist},
+    {"setmatches",	1, 2, 0, f_setmatches},
+    {"setpos",		2, 2, 0, f_setpos},
+    {"setqflist",	1, 3, 0, f_setqflist},
+    {"setreg",		2, 3, 0, f_setreg},
+    {"settabvar",	3, 3, 0, f_settabvar},
+    {"settabwinvar",	4, 4, 0, f_settabwinvar},
+    {"settagstack",	2, 3, 0, f_settagstack},
+    {"setwinvar",	3, 3, 0, f_setwinvar},
 #ifdef FEAT_CRYPT
-    {"sha256",		1, 1, f_sha256},
-#endif
-    {"shellescape",	1, 2, f_shellescape},
-    {"shiftwidth",	0, 1, f_shiftwidth},
+    {"sha256",		1, 1, 0, f_sha256},
+#endif
+    {"shellescape",	1, 2, 0, f_shellescape},
+    {"shiftwidth",	0, 1, 0, f_shiftwidth},
 #ifdef FEAT_SIGNS
-    {"sign_define",	1, 2, f_sign_define},
-    {"sign_getdefined",	0, 1, f_sign_getdefined},
-    {"sign_getplaced",	0, 2, f_sign_getplaced},
-    {"sign_jump",	3, 3, f_sign_jump},
-    {"sign_place",	4, 5, f_sign_place},
-    {"sign_placelist",	1, 1, f_sign_placelist},
-    {"sign_undefine",	0, 1, f_sign_undefine},
-    {"sign_unplace",	1, 2, f_sign_unplace},
-    {"sign_unplacelist",	1, 2, f_sign_unplacelist},
-#endif
-    {"simplify",	1, 1, f_simplify},
+    {"sign_define",	1, 2, 0, f_sign_define},
+    {"sign_getdefined",	0, 1, 0, f_sign_getdefined},
+    {"sign_getplaced",	0, 2, 0, f_sign_getplaced},
+    {"sign_jump",	3, 3, 0, f_sign_jump},
+    {"sign_place",	4, 5, 0, f_sign_place},
+    {"sign_placelist",	1, 1, 0, f_sign_placelist},
+    {"sign_undefine",	0, 1, 0, f_sign_undefine},
+    {"sign_unplace",	1, 2, 0, f_sign_unplace},
+    {"sign_unplacelist",	1, 2, 0, f_sign_unplacelist},
+#endif
+    {"simplify",	1, 1, 0, f_simplify},
 #ifdef FEAT_FLOAT
-    {"sin",		1, 1, f_sin},
-    {"sinh",		1, 1, f_sinh},
-#endif
-    {"sort",		1, 3, f_sort},
+    {"sin",		1, 1, 0, f_sin},
+    {"sinh",		1, 1, 0, f_sinh},
+#endif
+    {"sort",		1, 3, 0, f_sort},
 #ifdef FEAT_SOUND
-    {"sound_clear",	0, 0, f_sound_clear},
-    {"sound_playevent",	1, 2, f_sound_playevent},
-    {"sound_playfile",	1, 2, f_sound_playfile},
-    {"sound_stop",	1, 1, f_sound_stop},
-#endif
-    {"soundfold",	1, 1, f_soundfold},
-    {"spellbadword",	0, 1, f_spellbadword},
-    {"spellsuggest",	1, 3, f_spellsuggest},
-    {"split",		1, 3, f_split},
+    {"sound_clear",	0, 0, 0, f_sound_clear},
+    {"sound_playevent",	1, 2, 0, f_sound_playevent},
+    {"sound_playfile",	1, 2, 0, f_sound_playfile},
+    {"sound_stop",	1, 1, 0, f_sound_stop},
+#endif
+    {"soundfold",	1, 1, 0, f_soundfold},
+    {"spellbadword",	0, 1, 0, f_spellbadword},
+    {"spellsuggest",	1, 3, 0, f_spellsuggest},
+    {"split",		1, 3, 0, f_split},
 #ifdef FEAT_FLOAT
-    {"sqrt",		1, 1, f_sqrt},
-    {"str2float",	1, 1, f_str2float},
-#endif
-    {"str2list",	1, 2, f_str2list},
-    {"str2nr",		1, 2, f_str2nr},
-    {"strcharpart",	2, 3, f_strcharpart},
-    {"strchars",	1, 2, f_strchars},
-    {"strdisplaywidth",	1, 2, f_strdisplaywidth},
+    {"sqrt",		1, 1, 0, f_sqrt},
+    {"str2float",	1, 1, 0, f_str2float},
+#endif
+    {"str2list",	1, 2, 0, f_str2list},
+    {"str2nr",		1, 2, 0, f_str2nr},
+    {"strcharpart",	2, 3, 0, f_strcharpart},
+    {"strchars",	1, 2, 0, f_strchars},
+    {"strdisplaywidth",	1, 2, 0, f_strdisplaywidth},
 #ifdef HAVE_STRFTIME
-    {"strftime",	1, 2, f_strftime},
-#endif
-    {"strgetchar",	2, 2, f_strgetchar},
-    {"stridx",		2, 3, f_stridx},
-    {"string",		1, 1, f_string},
-    {"strlen",		1, 1, f_strlen},
-    {"strpart",		2, 3, f_strpart},
-    {"strridx",		2, 3, f_strridx},
-    {"strtrans",	1, 1, f_strtrans},
-    {"strwidth",	1, 1, f_strwidth},
-    {"submatch",	1, 2, f_submatch},
-    {"substitute",	4, 4, f_substitute},
-    {"swapinfo",	1, 1, f_swapinfo},
-    {"swapname",	1, 1, f_swapname},
-    {"synID",		3, 3, f_synID},
-    {"synIDattr",	2, 3, f_synIDattr},
-    {"synIDtrans",	1, 1, f_synIDtrans},
-    {"synconcealed",	2, 2, f_synconcealed},
-    {"synstack",	2, 2, f_synstack},
-    {"system",		1, 2, f_system},
-    {"systemlist",	1, 2, f_systemlist},
-    {"tabpagebuflist",	0, 1, f_tabpagebuflist},
-    {"tabpagenr",	0, 1, f_tabpagenr},
-    {"tabpagewinnr",	1, 2, f_tabpagewinnr},
-    {"tagfiles",	0, 0, f_tagfiles},
-    {"taglist",		1, 2, f_taglist},
+    {"strftime",	1, 2, 0, f_strftime},
+#endif
+    {"strgetchar",	2, 2, 0, f_strgetchar},
+    {"stridx",		2, 3, 0, f_stridx},
+    {"string",		1, 1, 0, f_string},
+    {"strlen",		1, 1, 0, f_strlen},
+    {"strpart",		2, 3, 0, f_strpart},
+    {"strridx",		2, 3, 0, f_strridx},
+    {"strtrans",	1, 1, 0, f_strtrans},
+    {"strwidth",	1, 1, 0, f_strwidth},
+    {"submatch",	1, 2, 0, f_submatch},
+    {"substitute",	4, 4, 0, f_substitute},
+    {"swapinfo",	1, 1, 0, f_swapinfo},
+    {"swapname",	1, 1, 0, f_swapname},
+    {"synID",		3, 3, 0, f_synID},
+    {"synIDattr",	2, 3, 0, f_synIDattr},
+    {"synIDtrans",	1, 1, 0, f_synIDtrans},
+    {"synconcealed",	2, 2, 0, f_synconcealed},
+    {"synstack",	2, 2, 0, f_synstack},
+    {"system",		1, 2, 0, f_system},
+    {"systemlist",	1, 2, 0, f_systemlist},
+    {"tabpagebuflist",	0, 1, 0, f_tabpagebuflist},
+    {"tabpagenr",	0, 1, 0, f_tabpagenr},
+    {"tabpagewinnr",	1, 2, 0, f_tabpagewinnr},
+    {"tagfiles",	0, 0, 0, f_tagfiles},
+    {"taglist",		1, 2, 0, f_taglist},
 #ifdef FEAT_FLOAT
-    {"tan",		1, 1, f_tan},
-    {"tanh",		1, 1, f_tanh},
-#endif
-    {"tempname",	0, 0, f_tempname},
+    {"tan",		1, 1, 0, f_tan},
+    {"tanh",		1, 1, 0, f_tanh},
+#endif
+    {"tempname",	0, 0, 0, f_tempname},
 #ifdef FEAT_TERMINAL
-    {"term_dumpdiff",	2, 3, f_term_dumpdiff},
-    {"term_dumpload",	1, 2, f_term_dumpload},
-    {"term_dumpwrite",	2, 3, f_term_dumpwrite},
-    {"term_getaltscreen", 1, 1, f_term_getaltscreen},
+    {"term_dumpdiff",	2, 3, 0, f_term_dumpdiff},
+    {"term_dumpload",	1, 2, 0, f_term_dumpload},
+    {"term_dumpwrite",	2, 3, 0, f_term_dumpwrite},
+    {"term_getaltscreen", 1, 1, 0, f_term_getaltscreen},
 # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
-    {"term_getansicolors", 1, 1, f_term_getansicolors},
+    {"term_getansicolors", 1, 1, 0, f_term_getansicolors},
 # endif
-    {"term_getattr",	2, 2, f_term_getattr},
-    {"term_getcursor",	1, 1, f_term_getcursor},
-    {"term_getjob",	1, 1, f_term_getjob},
-    {"term_getline",	2, 2, f_term_getline},
-    {"term_getscrolled", 1, 1, f_term_getscrolled},
-    {"term_getsize",	1, 1, f_term_getsize},
-    {"term_getstatus",	1, 1, f_term_getstatus},
-    {"term_gettitle",	1, 1, f_term_gettitle},
-    {"term_gettty",	1, 2, f_term_gettty},
-    {"term_list",	0, 0, f_term_list},
-    {"term_scrape",	2, 2, f_term_scrape},
-    {"term_sendkeys",	2, 2, f_term_sendkeys},
+    {"term_getattr",	2, 2, 0, f_term_getattr},
+    {"term_getcursor",	1, 1, 0, f_term_getcursor},
+    {"term_getjob",	1, 1, 0, f_term_getjob},
+    {"term_getline",	2, 2, 0, f_term_getline},
+    {"term_getscrolled", 1, 1, 0, f_term_getscrolled},
+    {"term_getsize",	1, 1, 0, f_term_getsize},
+    {"term_getstatus",	1, 1, 0, f_term_getstatus},
+    {"term_gettitle",	1, 1, 0, f_term_gettitle},
+    {"term_gettty",	1, 2, 0, f_term_gettty},
+    {"term_list",	0, 0, 0, f_term_list},
+    {"term_scrape",	2, 2, 0, f_term_scrape},
+    {"term_sendkeys",	2, 2, 0, f_term_sendkeys},
 # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
-    {"term_setansicolors", 2, 2, f_term_setansicolors},
+    {"term_setansicolors", 2, 2, 0, f_term_setansicolors},
 # endif
-    {"term_setkill",	2, 2, f_term_setkill},
-    {"term_setrestore",	2, 2, f_term_setrestore},
-    {"term_setsize",	3, 3, f_term_setsize},
-    {"term_start",	1, 2, f_term_start},
-    {"term_wait",	1, 2, f_term_wait},
-#endif
-    {"test_alloc_fail",	3, 3, f_test_alloc_fail},
-    {"test_autochdir",	0, 0, f_test_autochdir},
-    {"test_feedinput",	1, 1, f_test_feedinput},
-    {"test_garbagecollect_now",	0, 0, f_test_garbagecollect_now},
-    {"test_garbagecollect_soon",	0, 0, f_test_garbagecollect_soon},
-    {"test_getvalue",	1, 1, f_test_getvalue},
-    {"test_ignore_error",	1, 1, f_test_ignore_error},
-    {"test_null_blob",	0, 0, f_test_null_blob},
+    {"term_setkill",	2, 2, 0, f_term_setkill},
+    {"term_setrestore",	2, 2, 0, f_term_setrestore},
+    {"term_setsize",	3, 3, 0, f_term_setsize},
+    {"term_start",	1, 2, 0, f_term_start},
+    {"term_wait",	1, 2, 0, f_term_wait},
+#endif
+    {"test_alloc_fail",	3, 3, 0, f_test_alloc_fail},
+    {"test_autochdir",	0, 0, 0, f_test_autochdir},
+    {"test_feedinput",	1, 1, 0, f_test_feedinput},
+    {"test_garbagecollect_now",	0, 0, 0, f_test_garbagecollect_now},
+    {"test_garbagecollect_soon",	0, 0, 0, f_test_garbagecollect_soon},
+    {"test_getvalue",	1, 1, 0, f_test_getvalue},
+    {"test_ignore_error",	1, 1, 0, f_test_ignore_error},
+    {"test_null_blob",	0, 0, 0, f_test_null_blob},
 #ifdef FEAT_JOB_CHANNEL
-    {"test_null_channel", 0, 0, f_test_null_channel},
-#endif
-    {"test_null_dict",	0, 0, f_test_null_dict},
+    {"test_null_channel", 0, 0, 0, f_test_null_channel},
+#endif
+    {"test_null_dict",	0, 0, 0, f_test_null_dict},
 #ifdef FEAT_JOB_CHANNEL
-    {"test_null_job",	0, 0, f_test_null_job},
-#endif
-    {"test_null_list",	0, 0, f_test_null_list},
-    {"test_null_partial", 0, 0, f_test_null_partial},
-    {"test_null_string", 0, 0, f_test_null_string},
-    {"test_option_not_set", 1, 1, f_test_option_not_set},
-    {"test_override",	2, 2, f_test_override},
-    {"test_refcount",	1, 1, f_test_refcount},
+    {"test_null_job",	0, 0, 0, f_test_null_job},
+#endif
+    {"test_null_list",	0, 0, 0, f_test_null_list},
+    {"test_null_partial", 0, 0, 0, f_test_null_partial},
+    {"test_null_string", 0, 0, 0, f_test_null_string},
+    {"test_option_not_set", 1, 1, 0, f_test_option_not_set},
+    {"test_override",	2, 2, 0, f_test_override},
+    {"test_refcount",	1, 1, 0, f_test_refcount},
 #ifdef FEAT_GUI
-    {"test_scrollbar",	3, 3, f_test_scrollbar},
+    {"test_scrollbar",	3, 3, 0, f_test_scrollbar},
 #endif
 #ifdef FEAT_MOUSE
-    {"test_setmouse",	2, 2, f_test_setmouse},
-#endif
-    {"test_settime",	1, 1, f_test_settime},
+    {"test_setmouse",	2, 2, 0, f_test_setmouse},
+#endif
+    {"test_settime",	1, 1, 0, f_test_settime},
 #ifdef FEAT_TIMERS
-    {"timer_info",	0, 1, f_timer_info},
-    {"timer_pause",	2, 2, f_timer_pause},
-    {"timer_start",	2, 3, f_timer_start},
-    {"timer_stop",	1, 1, f_timer_stop},
-    {"timer_stopall",	0, 0, f_timer_stopall},
-#endif
-    {"tolower",		1, 1, f_tolower},
-    {"toupper",		1, 1, f_toupper},
-    {"tr",		3, 3, f_tr},
-    {"trim",		1, 2, f_trim},
+    {"timer_info",	0, 1, 0, f_timer_info},
+    {"timer_pause",	2, 2, 0, f_timer_pause},
+    {"timer_start",	2, 3, 0, f_timer_start},
+    {"timer_stop",	1, 1, 0, f_timer_stop},
+    {"timer_stopall",	0, 0, 0, f_timer_stopall},
+#endif
+    {"tolower",		1, 1, 0, f_tolower},
+    {"toupper",		1, 1, 0, f_toupper},
+    {"tr",		3, 3, 0, f_tr},
+    {"trim",		1, 2, 0, f_trim},
 #ifdef FEAT_FLOAT
-    {"trunc",		1, 1, f_trunc},
-#endif
-    {"type",		1, 1, f_type},
-    {"undofile",	1, 1, f_undofile},
-    {"undotree",	0, 0, f_undotree},
-    {"uniq",		1, 3, f_uniq},
-    {"values",		1, 1, f_values},
-    {"virtcol",		1, 1, f_virtcol},
-    {"visualmode",	0, 1, f_visualmode},
-    {"wildmenumode",	0, 0, f_wildmenumode},
-    {"win_execute",	2, 3, f_win_execute},
-    {"win_findbuf",	1, 1, f_win_findbuf},
-    {"win_getid",	0, 2, f_win_getid},
-    {"win_gotoid",	1, 1, f_win_gotoid},
-    {"win_id2tabwin",	1, 1, f_win_id2tabwin},
-    {"win_id2win",	1, 1, f_win_id2win},
-    {"win_screenpos",	1, 1, f_win_screenpos},
-    {"winbufnr",	1, 1, f_winbufnr},
-    {"wincol",		0, 0, f_wincol},
-    {"winheight",	1, 1, f_winheight},
-    {"winlayout",	0, 1, f_winlayout},
-    {"winline",		0, 0, f_winline},
-    {"winnr",		0, 1, f_winnr},
-    {"winrestcmd",	0, 0, f_winrestcmd},
-    {"winrestview",	1, 1, f_winrestview},
-    {"winsaveview",	0, 0, f_winsaveview},
-    {"winwidth",	1, 1, f_winwidth},
-    {"wordcount",	0, 0, f_wordcount},
-    {"writefile",	2, 3, f_writefile},
-    {"xor",		2, 2, f_xor},
+    {"trunc",		1, 1, 0, f_trunc},
+#endif
+    {"type",		1, 1, 0, f_type},
+    {"undofile",	1, 1, 0, f_undofile},
+    {"undotree",	0, 0, 0, f_undotree},
+    {"uniq",		1, 3, 0, f_uniq},
+    {"values",		1, 1, 0, f_values},
+    {"virtcol",		1, 1, 0, f_virtcol},
+    {"visualmode",	0, 1, 0, f_visualmode},
+    {"wildmenumode",	0, 0, 0, f_wildmenumode},
+    {"win_execute",	2, 3, 0, f_win_execute},
+    {"win_findbuf",	1, 1, 0, f_win_findbuf},
+    {"win_getid",	0, 2, 0, f_win_getid},
+    {"win_gotoid",	1, 1, 0, f_win_gotoid},
+    {"win_id2tabwin",	1, 1, 0, f_win_id2tabwin},
+    {"win_id2win",	1, 1, 0, f_win_id2win},
+    {"win_screenpos",	1, 1, 0, f_win_screenpos},
+    {"winbufnr",	1, 1, 0, f_winbufnr},
+    {"wincol",		0, 0, 0, f_wincol},
+    {"winheight",	1, 1, 0, f_winheight},
+    {"winlayout",	0, 1, 0, f_winlayout},
+    {"winline",		0, 0, 0, f_winline},
+    {"winnr",		0, 1, 0, f_winnr},
+    {"winrestcmd",	0, 0, 0, f_winrestcmd},
+    {"winrestview",	1, 1, 0, f_winrestview},
+    {"winsaveview",	0, 0, 0, f_winsaveview},
+    {"winwidth",	1, 1, 0, f_winwidth},
+    {"wordcount",	0, 0, 0, f_wordcount},
+    {"writefile",	2, 3, 0, f_writefile},
+    {"xor",		2, 2, 0, f_xor},
 };
 
+// values for f_argtype
+#define FEARG_LAST 1	    // base is the last argument
+#define FEARG_2    2	    // base is the second argument
+
 /*
  * Methods that call the internal function with the base as the first argument.
  */
 static funcentry_T base_methods[] =
 {
-    {"add",		1, 1, f_add},
-    {"copy",		0, 0, f_copy},
-    {"count",		1, 3, f_count},
-    {"empty",		0, 0, f_empty},
-    {"extend",		1, 2, f_extend},
-    {"filter",		1, 1, f_filter},
-    {"get",		1, 2, f_get},
-    {"index",		1, 3, f_index},
-    {"insert",		1, 2, f_insert},
-    {"items",		0, 0, f_items},
-    {"join",		0, 1, f_join},
-    {"keys",		0, 0, f_keys},
-    {"len",		0, 0, f_len},
-    {"map",		1, 1, f_map},
-    {"max",		0, 0, f_max},
-    {"min",		0, 0, f_min},
-    {"remove",		1, 2, f_remove},
-    {"repeat",		1, 1, f_repeat},
-    {"reverse",		0, 0, f_reverse},
-    {"sort",		0, 2, f_sort},
-    {"string",		0, 0, f_string},
-    {"type",		0, 0, f_type},
-    {"uniq",		0, 2, f_uniq},
-    {"values",		0, 0, f_values},
+    {"add",		1, 1, 0,	    f_add},
+    {"append",		1, 1, FEARG_LAST,   f_append},
+    {"appendbufline",	2, 2, FEARG_LAST,   f_appendbufline},
+    {"assert_equal",	1, 2, FEARG_2,	    f_assert_equal},
+    {"assert_notequal",	1, 2, FEARG_2,	    f_assert_notequal},
+    {"copy",		0, 0, 0,	    f_copy},
+    {"count",		1, 3, 0,	    f_count},
+    {"empty",		0, 0, 0,	    f_empty},
+    {"eval",		0, 0, 0,	    f_eval},
+    {"extend",		1, 2, 0,	    f_extend},
+    {"filter",		1, 1, 0,	    f_filter},
+    {"get",		1, 2, 0,	    f_get},
+    {"index",		1, 3, 0,	    f_index},
+    {"insert",		1, 2, 0,	    f_insert},
+    {"items",		0, 0, 0,	    f_items},
+    {"join",		0, 1, 0,	    f_join},
+    {"keys",		0, 0, 0,	    f_keys},
+    {"len",		0, 0, 0,	    f_len},
+    {"map",		1, 1, 0,	    f_map},
+    {"max",		0, 0, 0,	    f_max},
+    {"min",		0, 0, 0,	    f_min},
+    {"remove",		1, 2, 0,	    f_remove},
+    {"repeat",		1, 1, 0,	    f_repeat},
+    {"reverse",		0, 0, 0,	    f_reverse},
+    {"sort",		0, 2, 0,	    f_sort},
+    {"string",		0, 0, 0,	    f_string},
+    {"type",		0, 0, 0,	    f_type},
+    {"uniq",		0, 2, 0,	    f_uniq},
+    {"values",		0, 0, 0,	    f_values},
 };
 
 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
@@ -1159,9 +1169,27 @@ call_internal_method(
     if (argcount > base_methods[fi].f_max_argc)
 	return ERROR_TOOMANY;
 
-    argv[0] = *basetv;
-    for (i = 0; i < argcount; ++i)
-	argv[i + 1] = argvars[i];
+    if (base_methods[fi].f_argtype == FEARG_LAST)
+    {
+	// base value goes last
+	for (i = 0; i < argcount; ++i)
+	    argv[i] = argvars[i];
+	argv[argcount] = *basetv;
+    }
+    else if (base_methods[fi].f_argtype == FEARG_2)
+    {
+	// base value goes second
+	argv[0] = argvars[0];
+	argv[1] = *basetv;
+	for (i = 1; i < argcount; ++i)
+	    argv[i + 1] = argvars[i];
+    }
+    else
+    {
+	argv[0] = *basetv;
+	for (i = 0; i < argcount; ++i)
+	    argv[i + 1] = argvars[i];
+    }
     argv[argcount + 1].v_type = VAR_UNKNOWN;
 
     base_methods[fi].f_func(argv, rettv);
--- a/src/ex_cmdidxs.h
+++ b/src/ex_cmdidxs.h
@@ -10,27 +10,27 @@ static const unsigned short cmdidxs1[26]
   /* c */ 42,
   /* d */ 108,
   /* e */ 130,
-  /* f */ 150,
-  /* g */ 166,
-  /* h */ 172,
-  /* i */ 181,
-  /* j */ 199,
-  /* k */ 201,
-  /* l */ 206,
-  /* m */ 268,
-  /* n */ 286,
-  /* o */ 306,
-  /* p */ 318,
-  /* q */ 357,
-  /* r */ 360,
-  /* s */ 380,
-  /* t */ 448,
-  /* u */ 493,
-  /* v */ 504,
-  /* w */ 522,
-  /* x */ 536,
-  /* y */ 546,
-  /* z */ 547
+  /* f */ 151,
+  /* g */ 167,
+  /* h */ 173,
+  /* i */ 182,
+  /* j */ 200,
+  /* k */ 202,
+  /* l */ 207,
+  /* m */ 269,
+  /* n */ 287,
+  /* o */ 307,
+  /* p */ 319,
+  /* q */ 358,
+  /* r */ 361,
+  /* s */ 381,
+  /* t */ 449,
+  /* u */ 494,
+  /* v */ 505,
+  /* w */ 523,
+  /* x */ 537,
+  /* y */ 547,
+  /* z */ 548
 };
 
 /*
@@ -45,7 +45,7 @@ static const unsigned char cmdidxs2[26][
   /* b */ {  2,  0,  0,  4,  5,  7,  0,  0,  0,  0,  0,  8,  9, 10, 11, 12,  0, 13,  0,  0,  0,  0, 22,  0,  0,  0 },
   /* c */ {  3, 12, 16, 18, 20, 22, 25,  0,  0,  0,  0, 33, 37, 40, 46, 56, 58, 59, 60,  0, 62,  0, 65,  0,  0,  0 },
   /* d */ {  0,  0,  0,  0,  0,  0,  0,  0,  6, 15,  0, 16,  0,  0, 17,  0,  0, 19, 20,  0,  0,  0,  0,  0,  0,  0 },
-  /* e */ {  1,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  7,  9, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16,  0,  0 },
+  /* e */ {  1,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  7,  9, 10,  0,  0,  0,  0,  0,  0,  0, 16,  0, 17,  0,  0 },
   /* f */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0, 15,  0,  0,  0,  0,  0 },
   /* g */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  2,  0,  0,  4,  5,  0,  0,  0,  0 },
   /* h */ {  5,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
@@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][
   /* z */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
 };
 
-static const int command_count = 560;
+static const int command_count = 561;
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -544,6 +544,9 @@ EXCMD(CMD_endwhile,	"endwhile",	ex_endwh
 EXCMD(CMD_enew,		"enew",		ex_edit,
 	EX_BANG|EX_TRLBAR,
 	ADDR_NONE),
+EXCMD(CMD_eval,		"eval",		ex_eval,
+	EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN,
+	ADDR_NONE),
 EXCMD(CMD_ex,		"ex",		ex_edit,
 	EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR,
 	ADDR_NONE),
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -871,6 +871,18 @@ report_discard_pending(int pending, void
 
 
 /*
+ * ":eval".
+ */
+    void
+ex_eval(exarg_T *eap)
+{
+    typval_T	tv;
+
+    if (eval0(eap->arg, &tv, &eap->nextcmd, !eap->skip) == OK)
+	clear_tv(&tv);
+}
+
+/*
  * ":if".
  */
     void
--- a/src/proto/ex_eval.pro
+++ b/src/proto/ex_eval.pro
@@ -12,6 +12,7 @@ void discard_current_exception(void);
 void report_make_pending(int pending, void *value);
 void report_resume_pending(int pending, void *value);
 void report_discard_pending(int pending, void *value);
+void ex_eval(exarg_T *eap);
 void ex_if(exarg_T *eap);
 void ex_endif(exarg_T *eap);
 void ex_else(exarg_T *eap);
--- a/src/testdir/test_method.vim
+++ b/src/testdir/test_method.vim
@@ -3,18 +3,23 @@
 func Test_list()
   let l = [1, 2, 3]
   call assert_equal([1, 2, 3, 4], [1, 2, 3]->add(4))
+  eval l->assert_equal(l)
+  eval l->assert_equal(l, 'wrong')
+  eval l->assert_notequal([3, 2, 1])
+  eval l->assert_notequal([3, 2, 1], 'wrong')
   call assert_equal(l, l->copy())
   call assert_equal(1, l->count(2))
   call assert_false(l->empty())
   call assert_true([]->empty())
+  call assert_equal(579, ['123', '+', '456']->join()->eval())
   call assert_equal([1, 2, 3, 4, 5], [1, 2, 3]->extend([4, 5]))
   call assert_equal([1, 3], [1, 2, 3]->filter('v:val != 2'))
   call assert_equal(2, l->get(1))
   call assert_equal(1, l->index(2))
   call assert_equal([0, 1, 2, 3], [1, 2, 3]->insert(0))
-  call assert_fails('let x = l->items()', 'E715:')
+  call assert_fails('eval l->items()', 'E715:')
   call assert_equal('1 2 3', l->join())
-  call assert_fails('let x = l->keys()', 'E715:')
+  call assert_fails('eval l->keys()', 'E715:')
   call assert_equal(3, l->len())
   call assert_equal([2, 3, 4], [1, 2, 3]->map('v:val + 1'))
   call assert_equal(3, l->max())
@@ -26,7 +31,7 @@ func Test_list()
   call assert_equal('[1, 2, 3]', l->string())
   call assert_equal(v:t_list, l->type())
   call assert_equal([1, 2, 3], [1, 1, 2, 3, 3]->uniq())
-  call assert_fails('let x = l->values()', 'E715:')
+  call assert_fails('eval l->values()', 'E715:')
 endfunc
 
 func Test_dict()
@@ -59,3 +64,17 @@ func Test_dict()
   call assert_fails('let x = d->uniq()', 'E686:')
   call assert_equal([1, 2, 3], d->values())
 endfunc
+
+func Test_append()
+  new
+  eval ['one', 'two', 'three']->append(1)
+  call assert_equal(['', 'one', 'two', 'three'], getline(1, '$'))
+
+  %del
+  let bnr = bufnr('')
+  wincmd w
+  eval ['one', 'two', 'three']->appendbufline(bnr, 1)
+  call assert_equal(['', 'one', 'two', 'three'], getbufline(bnr, 1, '$'))
+
+  exe 'bwipe! ' .. bnr
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -774,6 +774,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1807,
+/**/
     1806,
 /**/
     1805,