summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIllia Bobyr <illia.bobyr@gmail.com>2023-10-17 11:09:45 +0200
committerChristian Brabandt <cb@256bit.org>2023-10-17 11:09:45 +0200
commit6e6386716f9494ae86027c6d34f657fd03dfec42 (patch)
tree4a6c57ffec25e0af23238b2c23bd038eb2a2c86f
parent2e3cd52fa02b1a208c97992b1bca3b04f7be66d4 (diff)
patch 9.0.2040: trim(): hard to use default maskv9.0.2040
Problem: trim(): hard to use default mask Solution: Use default 'mask' when it is v:none The default 'mask' value is pretty complex, as it includes many characters. Yet, if one needs to specify the trimming direction, the third argument, 'trim()' currently requires the 'mask' value to be provided explicitly. 'v:none' is already used to mean "use the default argument value" in user defined functions. See |none-function_argument| in help. closes: #13363 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Illia Bobyr <illia.bobyr@gmail.com>
-rw-r--r--runtime/doc/builtin.txt7
-rw-r--r--src/errors.h2
-rw-r--r--src/proto/typval.pro1
-rw-r--r--src/strings.c28
-rw-r--r--src/testdir/test_functions.vim6
-rw-r--r--src/testdir/test_vim9_builtin.vim2
-rw-r--r--src/typval.c31
-rw-r--r--src/version.c2
8 files changed, 59 insertions, 20 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index a9bba86d8c..38c4b6f688 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -10119,9 +10119,10 @@ trim({text} [, {mask} [, {dir}]]) *trim()*
Return {text} as a String where any character in {mask} is
removed from the beginning and/or end of {text}.
- If {mask} is not given, {mask} is all characters up to 0x20,
- which includes Tab, space, NL and CR, plus the non-breaking
- space character 0xa0.
+ If {mask} is not given, or is |v:none| (see
+ |none-function_argument|), {mask} is all characters up to
+ 0x20, which includes Tab, space, NL and CR, plus the
+ non-breaking space character 0xa0.
The optional {dir} argument specifies where to remove the
characters:
diff --git a/src/errors.h b/src/errors.h
index 7b1181ae94..d7ed81a16e 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3539,6 +3539,8 @@ EXTERN char e_cannot_lock_object_variable_str[]
EXTERN char e_cannot_lock_class_variable_str[]
INIT(= N_("E1392: Cannot (un)lock class variable \"%s\" in class \"%s\""));
#endif
+EXTERN char e_string_or_none_required_for_argument_nr[]
+ INIT(= N_("E1393: String or v:none required for argument %d"));
// E1393 - E1499 unused (reserved for Vim9 class support)
EXTERN char e_cannot_mix_positional_and_non_positional_str[]
INIT(= N_("E1500: Cannot mix positional and non-positional arguments: %s"));
diff --git a/src/proto/typval.pro b/src/proto/typval.pro
index db8f94ebb0..10f6e67111 100644
--- a/src/proto/typval.pro
+++ b/src/proto/typval.pro
@@ -14,6 +14,7 @@ int check_for_unknown_arg(typval_T *args, int idx);
int check_for_string_arg(typval_T *args, int idx);
int check_for_nonempty_string_arg(typval_T *args, int idx);
int check_for_opt_string_arg(typval_T *args, int idx);
+int check_for_opt_string_or_none_arg(typval_T *args, int idx, int *is_none);
int check_for_number_arg(typval_T *args, int idx);
int check_for_opt_number_arg(typval_T *args, int idx);
int check_for_float_or_nr_arg(typval_T *args, int idx);
diff --git a/src/strings.c b/src/strings.c
index c04cbe84f6..f1c8af8f99 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -1962,7 +1962,7 @@ f_trim(typval_T *argvars, typval_T *rettv)
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
- || check_for_opt_string_arg(argvars, 1) == FAIL
+ || check_for_opt_string_or_none_arg(argvars, 1, NULL) == FAIL
|| (argvars[1].v_type != VAR_UNKNOWN
&& check_for_opt_number_arg(argvars, 2) == FAIL)))
return;
@@ -1971,26 +1971,24 @@ f_trim(typval_T *argvars, typval_T *rettv)
if (head == NULL)
return;
- if (check_for_opt_string_arg(argvars, 1) == FAIL)
+ if (check_for_opt_string_or_none_arg(argvars, 1, NULL) == FAIL)
return;
if (argvars[1].v_type == VAR_STRING)
- {
mask = tv_get_string_buf_chk(&argvars[1], buf2);
- if (argvars[2].v_type != VAR_UNKNOWN)
- {
- int error = 0;
+ if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN)
+ {
+ int error = 0;
- // leading or trailing characters to trim
- dir = (int)tv_get_number_chk(&argvars[2], &error);
- if (error)
- return;
- if (dir < 0 || dir > 2)
- {
- semsg(_(e_invalid_argument_str), tv_get_string(&argvars[2]));
- return;
- }
+ // leading or trailing characters to trim
+ dir = (int)tv_get_number_chk(&argvars[2], &error);
+ if (error)
+ return;
+ if (dir < 0 || dir > 2)
+ {
+ semsg(_(e_invalid_argument_str), tv_get_string(&argvars[2]));
+ return;
}
}
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index d598966977..85d1d22ee6 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -2231,11 +2231,15 @@ func Test_trim()
call assert_fails('eval trim(" vim ", " ", [])', 'E745:')
call assert_fails('eval trim(" vim ", " ", -1)', 'E475:')
call assert_fails('eval trim(" vim ", " ", 3)', 'E475:')
- call assert_fails('eval trim(" vim ", 0)', 'E1174:')
+ call assert_fails('eval trim(" vim ", 0)', 'E1393:')
let chars = join(map(range(1, 0x20) + [0xa0], {n -> n->nr2char()}), '')
call assert_equal("x", trim(chars . "x" . chars))
+ call assert_equal("x", trim(chars . "x" . chars, v:none, 0))
+ call assert_equal("x" . chars, trim(chars . "x" . chars, v:none, 1))
+ call assert_equal(chars . "x", trim(chars . "x" . chars, v:none, 2))
+
call assert_fails('let c=trim([])', 'E730:')
endfunc
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 1efc47a074..206f97f2e0 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -4786,7 +4786,7 @@ enddef
def Test_trim()
v9.CheckDefAndScriptFailure(['trim(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1'])
- v9.CheckDefAndScriptFailure(['trim("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected string but got list<string>', 'E1174: String required for argument 2'])
+ v9.CheckDefAndScriptFailure(['trim("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected string but got list<string>', 'E1393: String or v:none required for argument 2'])
v9.CheckDefAndScriptFailure(['trim("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3'])
trim('')->assert_equal('')
trim('', '')->assert_equal('')
diff --git a/src/typval.c b/src/typval.c
index 08dd2313f2..b6371aaa43 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -451,6 +451,37 @@ check_for_opt_string_arg(typval_T *args, int idx)
}
/*
+ * Check for an optional string argument at 'idx', that can also be 'v:none' to
+ * use the default value.
+ *
+ * If 'is_none' is non-NULL it is set to 0 and updated to 1 when "args[idx]" is
+ * 'v:none'.
+ */
+ int
+check_for_opt_string_or_none_arg(typval_T *args, int idx, int *is_none)
+{
+ if (is_none != NULL)
+ *is_none = 0;
+
+ if (args[idx].v_type == VAR_UNKNOWN)
+ return OK;
+
+ if (args[idx].v_type == VAR_SPECIAL
+ && args[idx].vval.v_number == VVAL_NONE)
+ {
+ if (is_none != NULL)
+ *is_none = 1;
+ return OK;
+ }
+
+ if (args[idx].v_type == VAR_STRING)
+ return OK;
+
+ semsg(_(e_string_or_none_required_for_argument_nr), idx + 1);
+ return FAIL;
+}
+
+/*
* Give an error and return FAIL unless "args[idx]" is a number.
*/
int
diff --git a/src/version.c b/src/version.c
index 208d7a8819..0896c643f9 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2040,
+/**/
2039,
/**/
2038,