diff --git a/manual/template_lang.rst b/manual/template_lang.rst index 1ff477a5f5..0c2d445c5d 100644 --- a/manual/template_lang.rst +++ b/manual/template_lang.rst @@ -250,6 +250,11 @@ The following functions are available in addition to those described in single-f * ``divide(x, y)`` -- returns x / y. Throws an exception if either x or y are not numbers. * ``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. Because the `{` and `}` characters are special, you must use `[[` for the `{` character and `]]` for the '}' character; they are converted automatically. Note also that prefixes and suffixes (the `|prefix|suffix` syntax) cannot be used in the argument to this function when using template program mode. * ``field(name)`` -- returns the metadata field named by ``name``. + * ``first_matching_cmp(val, cmp1, result1, cmp2, r2, ..., else_result)`` -- compares "val < cmpN" in sequence, returning resultN for the first comparison that succeeds. Returns else_result if no comparison succeeds. Example:: + + ``first_matching_cmp(10,5,"small",10,"middle",15,"large","giant")`` + + returns "middle". The same example with a first value of 16 returns "giant". * ``first_non_empty(value, value, ...)`` -- returns the first value that is not empty. If all values are empty, then the empty value is returned. You can have as many values as you want. * ``format_date(x, date_format)`` -- format_date(val, format_string) -- format the value, which must be a date field, using the format_string, returning a string. The formatting codes are:: diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 966e51c2ea..3ddecc4169 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -178,6 +178,27 @@ class BuiltinCmp(BuiltinFormatterFunction): return eq return gt +class BuiltinFirstMatchingCmp(BuiltinFormatterFunction): + name = 'first_matching_cmp' + category = 'Relational' + arg_count = -1 + __doc__ = doc = _('first_matching_cmp(val, cmp1, result1, cmp2, r2, ..., else_result) -- ' + 'compares "val < cmpN" in sequence, returning resultN for ' + 'the first comparison that succeeds. Returns else_result ' + 'if no comparison succeeds. Example: ' + 'first_matching_cmp(10,5,"small",10,"middle",15,"large","giant") ' + 'returns "middle". The same example with a first value of 16 returns "giant".') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + if (len(args) % 2) != 0: + raise ValueError(_('first_matching_cmp requires an even number of arguments')) + val = float(args[0] if args[0] and args[0] != 'None' else 0) + for i in range(1, len(args) - 1, 2): + c = float(args[i] if args[i] and args[i] != 'None' else 0) + if val < c: + return args[i+1] + return args[len(args)-1] + class BuiltinStrcat(BuiltinFormatterFunction): name = 'strcat' arg_count = -1 @@ -1310,9 +1331,9 @@ _formatter_builtins = [ BuiltinCapitalize(), BuiltinCmp(), BuiltinContains(), BuiltinCount(), BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(), BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(), - BuiltinField(), BuiltinFinishFormatting(), BuiltinFormatDate(), - BuiltinFormatNumber(), BuiltinFormatsModtimes(), BuiltinFormatsPaths(), - BuiltinFormatsSizes(), + BuiltinField(), BuiltinFinishFormatting(), BuiltinFirstMatchingCmp(), + BuiltinFormatDate(), BuiltinFormatNumber(), BuiltinFormatsModtimes(), + BuiltinFormatsPaths(), BuiltinFormatsSizes(), BuiltinHasCover(), BuiltinHumanReadable(), BuiltinIdentifierInList(), BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(), BuiltinInList(), BuiltinListDifference(), BuiltinListEquals(),