diff --git a/NEWS.txt b/NEWS.txt index 950e37096..8383c0420 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -42,7 +42,7 @@ * Use MusicBrainz Server translations for release groups, medium formats and cover art types * Add checkbox to toggle debug at runtime in log/debug view dialog * Add a plugin to add Artist Official Homepage relationships to the website tag (ID3 WOAR tag) - + * Add integrated functions $eq_any, $ne_all, $eq_all, $ne_any, $swapprefix and $delprefix. Version 1.2 - 2013-03-30 diff --git a/contrib/plugins/swapprefix.py b/contrib/plugins/swapprefix.py deleted file mode 100644 index 20a59f802..000000000 --- a/contrib/plugins/swapprefix.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Picard plugin swapprefix -# Adds the swapprefix tagger script function. -# This function offers the same functionality as the one in Foobar2000. -# See http://wiki.hydrogenaudio.org/index.php?title=Foobar2000:Title_Formatting_Reference -# -# Copyright (C) 2010 Philipp Wolfer -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -PLUGIN_NAME = 'swapprefix function' -PLUGIN_AUTHOR = 'Philipp Wolfer' -PLUGIN_DESCRIPTION = 'Moves the specified prefixes to the end of a string.' -PLUGIN_VERSION = "0.1" -PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.11", "0.12", "0.15"] - -from picard.script import register_script_function -import re - - -def swapprefix(parser, text, *prefixes): - """ - Moves the specified prefixes to the end of text. - If no prefix is specified 'A' and 'The' are taken - as default. - """ - if not prefixes: - prefixes = ('A', 'The') - for prefix in prefixes: - pattern = re.compile('^' + re.escape(prefix) + '\s') - match = pattern.match(text) - if match: - rest = pattern.split(text)[1].strip() - if rest: - return ", ".join((rest, match.group(0).rstrip())) - return text - -register_script_function(swapprefix) diff --git a/picard/script.py b/picard/script.py index b7d7f157c..b0e4145ca 100644 --- a/picard/script.py +++ b/picard/script.py @@ -632,6 +632,84 @@ def func_truncate(parser, text, length): return text[:length].rstrip() +def func_swapprefix(parser, text, *prefixes): + """ + Moves the specified prefixes to the end of text. + If no prefix is specified 'A' and 'The' are taken as default. + """ + # Inspired by the swapprefix plugin by Philipp Wolfer. + + text, prefix = _delete_prefix(parser, text, *prefixes) + if prefix != '': + return text + ', ' + prefix + return text + +def func_delprefix(parser, text, *prefixes): + """ + Deletes the specified prefixes. + If no prefix is specified 'A' and 'The' are taken as default. + """ + # Inspired by the swapprefix plugin by Philipp Wolfer. + + return _delete_prefix(parser, text, *prefixes)[0] + +def _delete_prefix(parser, text, *prefixes): + """ + Worker function to deletes the specified prefixes. + Returns remaining string and deleted part separately. + If no prefix is specified 'A' and 'The' used. + """ + # Inspired by the swapprefix plugin by Philipp Wolfer. + + if not prefixes: + prefixes = ('A', 'The') + text = text.strip() + match = re.match('(' + r'\s+)|('.join(prefixes) + r'\s+)', text) + if match: + pref = match.group() + return text[len(pref):], pref.strip() + return text, '' + + +def func_eq_any(parser, x, *args): + """ + Return True if one string matches any of one or more other strings. + $eq_any(a,b,c ...) is functionally equivalent to $or($eq(a,b),$eq(a,c) ...) + Example: $if($eq_any(%artist%,foo,bar,baz),$set(engineer,test)) + """ + # Inspired by the eq2 plugin by Brian Schweitzer. + return '1' if x in args else '' + +def func_ne_all(parser, x, *args): + """ + Return True if one string doesn't match all of one or more other strings. + $ne_all(a,b,c ...) is functionally equivalent to $and($ne(a,b),$ne(a,c) ...) + Example: $if($ne_all(%artist%,foo,bar,baz),$set(engineer,test)) + """ + # Inspired by the ne2 plugin by Brian Schweitzer. + return '1' if x not in args else '' + + +def func_eq_all(parser, x, *args): + """ + Return True if all string are equal. + $eq_all(a,b,c ...) is functionally equivalent to $and($eq(a,b),$eq(a,c) ...) + Example: $if($eq_all(%albumartist%,%artist%,Justin Bieber),$set(engineer,Meat Loaf)) + """ + for i in args: + if x != i: + return '' + return '1' + +def func_ne_any(parser, x, *args): + """ + Return True if all strings are not equal. + $ne_any(a,b,c ...) is functionally equivalent to $or($ne(a,b),$ne(a,c) ...) + Example: $if($ne_any(%albumartist%,%trackartist%,%composer%),$set(lyricist,%composer%)) + """ + return func_not(parser, func_eq_all(parser, x, *args)) + + register_script_function(func_if, "if", eval_args=False) register_script_function(func_if2, "if2", eval_args=False) register_script_function(func_noop, "noop", eval_args=False) @@ -675,3 +753,9 @@ register_script_function(func_firstalphachar, "firstalphachar") register_script_function(func_initials, "initials") register_script_function(func_firstwords, "firstwords") register_script_function(func_truncate, "truncate") +register_script_function(func_swapprefix, "swapprefix", check_argcount=False) +register_script_function(func_delprefix, "delprefix", check_argcount=False) +register_script_function(func_eq_any, "eq_any", check_argcount=False) +register_script_function(func_ne_all, "ne_all", check_argcount=False) +register_script_function(func_eq_all, "eq_all", check_argcount=False) +register_script_function(func_ne_any, "ne_any", check_argcount=False) diff --git a/test/test_script.py b/test/test_script.py index c79095374..a0840dd81 100644 --- a/test/test_script.py +++ b/test/test_script.py @@ -254,3 +254,39 @@ class ScriptParserTest(unittest.TestCase): context["target"] = "targetval" context["source"] = "sourceval" self._eval_and_check_copymerge(context, ["targetval", "sourceval"]) + + def test_cmd_eq_any(self): + self.assertEqual(self.parser.eval("$eq_any(abc,def,ghi,jkl)"), "") + self.assertEqual(self.parser.eval("$eq_any(abc,def,ghi,jkl,abc)"), "1") + + def test_cmd_ne_all(self): + self.assertEqual(self.parser.eval("$ne_all(abc,def,ghi,jkl)"), "1") + self.assertEqual(self.parser.eval("$ne_all(abc,def,ghi,jkl,abc)"), "") + + def test_cmd_eq_all(self): + self.assertEqual(self.parser.eval("$eq_all(abc,abc,abc,abc)"), "1") + self.assertEqual(self.parser.eval("$eq_all(abc,abc,def,ghi)"), "") + + def test_cmd_ne_any(self): + self.assertEqual(self.parser.eval("$ne_any(abc,abc,abc,abc)"), "") + self.assertEqual(self.parser.eval("$ne_any(abc,abc,def,ghi)"), "1") + + def test_cmd_swapprefix(self): + self.assertEqual(self.parser.eval("$swapprefix(A stitch in time)"), "stitch in time, A") + self.assertEqual(self.parser.eval("$swapprefix(The quick brown fox)"), "quick brown fox, The") + self.assertEqual(self.parser.eval("$swapprefix(How now brown cow)"), "How now brown cow") + self.assertEqual(self.parser.eval("$swapprefix(When the red red robin)"), "When the red red robin") + self.assertEqual(self.parser.eval("$swapprefix(A stitch in time,How,When,Who)"), "A stitch in time") + self.assertEqual(self.parser.eval("$swapprefix(The quick brown fox,How,When,Who)"), "The quick brown fox") + self.assertEqual(self.parser.eval("$swapprefix(How now brown cow,How,When,Who)"), "now brown cow, How") + self.assertEqual(self.parser.eval("$swapprefix(When the red red robin,How,When,Who)"), "the red red robin, When") + + def test_cmd_delprefix(self): + self.assertEqual(self.parser.eval("$delprefix(A stitch in time)"), "stitch in time") + self.assertEqual(self.parser.eval("$delprefix(The quick brown fox)"), "quick brown fox") + self.assertEqual(self.parser.eval("$delprefix(How now brown cow)"), "How now brown cow") + self.assertEqual(self.parser.eval("$delprefix(When the red red robin)"), "When the red red robin") + self.assertEqual(self.parser.eval("$delprefix(A stitch in time,How,When,Who)"), "A stitch in time") + self.assertEqual(self.parser.eval("$delprefix(The quick brown fox,How,When,Who)"), "The quick brown fox") + self.assertEqual(self.parser.eval("$delprefix(How now brown cow,How,When,Who)"), "now brown cow") + self.assertEqual(self.parser.eval("$delprefix(When the red red robin,How,When,Who)"), "the red red robin")