From 64b4d701bd264505ff699029d57caed632672e17 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Fri, 27 May 2011 13:57:28 +0100 Subject: [PATCH] New formatter function merge_lists, and its documentation --- src/calibre/manual/template_lang.rst | 3 ++- src/calibre/utils/formatter_functions.py | 25 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/calibre/manual/template_lang.rst b/src/calibre/manual/template_lang.rst index 16a90f7531..059376565d 100644 --- a/src/calibre/manual/template_lang.rst +++ b/src/calibre/manual/template_lang.rst @@ -253,6 +253,7 @@ The following functions are available in addition to those described in single-f * ``eval(string)`` -- evaluates the string as a program, passing the local variables (those ``assign`` ed to). This permits using the template processor to construct complex results from local variables. * ``not(value)`` -- returns the string "1" if the value is empty, otherwise returns the empty string. This function works well with test or first_non_empty. You can have as many values as you want. + * ``merge_lists(list1, list2, separator)`` -- return a list made by merging the items in list1 and list2, removing duplicate items using a case-insensitive compare. If items differ in case, the one in list1 is used. The items in list1 and list2 are separated by separator, as are the items in the returned list. * ``multiply(x, y)`` -- returns x * y. Throws an exception if either x or y are not numbers. * ``or(value, value, ...)`` -- returns the string "1" if any value is not empty, otherwise returns the empty string. This function works well with test or first_non_empty. You can have as many values as you want. * ``print(a, b, ...)`` -- prints the arguments to standard output. Unless you start calibre from the command line (``calibre-debug -g``), the output will go to a black hole. @@ -271,7 +272,7 @@ Function classification summary: * If-then-else: ``contains``, ``test`` * Iterating over values: ``first_non_empty``, ``lookup``, ``switch`` * List lookup: ``in_list``, ``list_item``, ``select``, - * List manipulation: ``count``, ``sublist``, ``subitems`` + * List manipulation: ``count``, ``merge_lists``, ``sublist``, ``subitems`` * Recursion: ``eval``, ``template`` * Relational: ``cmp`` , ``strcmp`` for strings * String case changes: ``lowercase``, ``uppercase``, ``titlecase``, ``capitalize`` diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index a3a156648f..2f15d5d592 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -642,6 +642,30 @@ class BuiltinNot(BuiltinFormatterFunction): i += 1 return '' +class BuiltinMergeLists(BuiltinFormatterFunction): + name = 'merge_lists' + arg_count = 3 + doc = _('merge_lists(list1, list2, separator) -- ' + 'return a list made by merging the items in list1 and list2, ' + 'removing duplicate items using a case-insensitive compare. If ' + 'items differ in case, the one in list1 is used. ' + 'The items in list1 and list2 are separated by separator, as are ' + 'the items in the returned list.') + + def evaluate(self, formatter, kwargs, mi, locals, list1, list2, separator): + l1 = [l.strip() for l in list1.split(separator) if l.strip()] + l2 = [l.strip() for l in list2.split(separator) if l.strip()] + lcl1 = set([icu_lower(l) for l in l1]) + + res = [] + for i in l1: + res.append(i) + for i in l2: + if icu_lower(i) not in lcl1: + res.append(i) + return ', '.join(sorted(res, key=sort_key)) + + builtin_add = BuiltinAdd() builtin_and = BuiltinAnd() builtin_assign = BuiltinAssign() @@ -660,6 +684,7 @@ builtin_in_list = BuiltinInList() builtin_list_item = BuiltinListitem() builtin_lookup = BuiltinLookup() builtin_lowercase = BuiltinLowercase() +builtin_merge_lists = BuiltinMergeLists() builtin_multiply = BuiltinMultiply() builtin_not = BuiltinNot() builtin_or = BuiltinOr()