diff --git a/picard/script.py b/picard/script.py index 2107664b7..3ffc7cdb7 100644 --- a/picard/script.py +++ b/picard/script.py @@ -1146,3 +1146,23 @@ def func_map(parser, multi, loop_code, separator=MULTI_VALUED_JOINER): if not isinstance(separator, str): separator = separator.eval(parser) return separator.join(multi_value) + + +@script_function(eval_args=False) +def func_join(parser, multi, join_phrase, separator=MULTI_VALUED_JOINER): + """Joins all elements in the specified multi-value variable, placing the join_phrase between each element. + + Arguments: + parser: The ScriptParser object used to parse the script. + multi: The ScriptVariable/Function that evaluates to a multi-value whose + elements are to be joined. + join_phrase: The ScriptVariable/Function that evaluates to a string which + will be placed between each of the elements. + separator: A string or the ScriptVariable/Function that evaluates to the + string used to separate the elements in the multi-value. + + Returns a string with the elements joined. + """ + join_phrase = str(join_phrase.eval(parser)) + multi_value = _get_multi_values(parser, multi, separator) + return join_phrase.join(multi_value) diff --git a/test/test_script.py b/test/test_script.py index cd01d3422..5067602f2 100644 --- a/test/test_script.py +++ b/test/test_script.py @@ -866,3 +866,30 @@ class ScriptParserTest(PicardTestCase): self.parser.eval("$map(abc; def)") with self.assertRaisesRegex(ScriptError, areg): self.parser.eval("$map(abc:def,$noop(),:,extra)") + + def test_cmd_joinmulti(self): + context = Metadata() + context["foo"] = "First:A; Second:B; Third:C" + context["bar"] = ["First:A", "Second:B", "Third:C"] + context["joiner"] = " ==> " + foo_output = "First:A; Second:B; Third:C" + bar_output = "First:A ==> Second:B ==> Third:C" + alternate_output = "First ==> A; Second ==> B; Third ==> C" + # Tests with context + self.assertScriptResultEquals("$join(%foo%,%joiner%)", foo_output, context) + self.assertScriptResultEquals("$join(%bar%,%joiner%)", bar_output, context) + # Tests with static inputs + self.assertScriptResultEquals("$join(First:A; Second:B; Third:C, ==> )", bar_output, context) + # Tests with missing inputs + self.assertScriptResultEquals("$join(, ==> )", "", context) + self.assertScriptResultEquals("$join(First:A; Second:B; Third:C,)", "First:ASecond:BThird:C", context) + # Tests with separator override + self.assertScriptResultEquals("$join(First:A; Second:B; Third:C, ==> ,:)", alternate_output, context) + # Tests with invalid number of arguments + areg = r"^Wrong number of arguments for \$join: Expected between 2 and 3, " + with self.assertRaisesRegex(ScriptError, areg): + self.parser.eval("$join()") + with self.assertRaisesRegex(ScriptError, areg): + self.parser.eval("$join(abc; def)") + with self.assertRaisesRegex(ScriptError, areg): + self.parser.eval("$join(abc:def, ==> ,:,extra)")