From 5d3674947479b18f6b3b94adf5078ea9b47fe5c4 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sat, 6 Aug 2011 15:26:21 +0100 Subject: [PATCH 1/2] Small fixes to template functions sublist, list_item, and swap_around_comma to strip the list items. --- src/calibre/utils/formatter_functions.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 0b54a85b9c..fbff64c800 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -432,7 +432,7 @@ class BuiltinSwapAroundComma(BuiltinFormatterFunction): 'returns val unchanged') def evaluate(self, formatter, kwargs, mi, locals, val): - return re.sub(r'^(.*?),(.*$)', r'\2 \1', val, flags=re.I) + return re.sub(r'^(.*?),\s*(.*$)', r'\2 \1', val, flags=re.I).strip() class BuiltinIfempty(BuiltinFormatterFunction): name = 'ifempty' @@ -502,7 +502,7 @@ class BuiltinListitem(BuiltinFormatterFunction): index = int(index) val = val.split(sep) try: - return val[index] + return val[index].strip() except: return '' @@ -620,7 +620,8 @@ class BuiltinSublist(BuiltinFormatterFunction): return '' si = int(start_index) ei = int(end_index) - val = val.split(sep) + # allow empty list items so counts are what the user expects + val = [v.strip() for v in val.split(sep)] try: if ei == 0: return sep.join(val[si:]) From 36bcb8a75424f41ace615bcb018d3c0736c71ccb Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sat, 6 Aug 2011 16:55:46 +0100 Subject: [PATCH 2/2] Add strlen and strcat_max functions --- src/calibre/manual/template_lang.rst | 2 + src/calibre/utils/formatter_functions.py | 50 +++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/calibre/manual/template_lang.rst b/src/calibre/manual/template_lang.rst index f2d01474b6..e2750e1ebf 100644 --- a/src/calibre/manual/template_lang.rst +++ b/src/calibre/manual/template_lang.rst @@ -273,7 +273,9 @@ The following functions are available in addition to those described in single-f * ``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. * ``raw_field(name)`` -- returns the metadata field named by name without applying any formatting. * ``strcat(a, b, ...)`` -- can take any number of arguments. Returns a string formed by concatenating all the arguments. + * ``strcat_max(max, string1, prefix2, string2, ...)`` -- Returns a string formed by concatenating the arguments. The returned value is initialized to string1. `Prefix, string` pairs are added to the end of the value as long as the resulting string length is less than `max`. String1 is returned even if string1 is longer than max. You can pass as many `prefix, string` pairs as you wish. * ``strcmp(x, y, lt, eq, gt)`` -- does a case-insensitive comparison x and y as strings. Returns ``lt`` if x < y. Returns ``eq`` if x == y. Otherwise returns ``gt``. + * ``strlen(a)`` -- Returns the length of the string passed as the argument. * ``substr(str, start, end)`` -- returns the ``start``'th through the ``end``'th characters of ``str``. The first character in ``str`` is the zero'th character. If end is negative, then it indicates that many characters counting from the right. If end is zero, then it indicates the last character. For example, ``substr('12345', 1, 0)`` returns ``'2345'``, and ``substr('12345', 1, -1)`` returns ``'234'``. * ``subtract(x, y)`` -- returns x - y. Throws an exception if either x or y are not numbers. * ``today()`` -- return a date string for today. This value is designed for use in format_date or days_between, but can be manipulated like any other string. The date is in ISO format. diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index fbff64c800..3d6775c242 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -136,6 +136,19 @@ class BuiltinStrcat(BuiltinFormatterFunction): res += args[i] return res +class BuiltinStrlen(BuiltinFormatterFunction): + name = 'strlen' + arg_count = 1 + category = 'String Manipulation' + __doc__ = doc = _('strlen(a) -- Returns the length of the string passed as ' + 'the argument') + + def evaluate(self, formatter, kwargs, mi, locals, a): + try: + return len(a) + except: + return -1 + class BuiltinAdd(BuiltinFormatterFunction): name = 'add' arg_count = 2 @@ -345,6 +358,40 @@ class BuiltinSwitch(BuiltinFormatterFunction): return args[i+1] i += 2 +class BuiltinStrcatMax(BuiltinFormatterFunction): + name = 'strcat_max' + arg_count = -1 + category = 'String Manipulation' + __doc__ = doc = _('strcat_max(max, string1, prefix2, string2, ...) -- ' + 'Returns a string formed by concatenating the arguments. The ' + 'returned value is initialized to string1. `Prefix, string` ' + 'pairs are added to the end of the value as long as the ' + 'resulting string length is less than `max`. String1 is returned ' + 'even if string1 is longer than max. You can pass as many ' + '`prefix, string` pairs as you wish.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + if len(args) < 2: + raise ValueError(_('strcat_max requires 2 or more arguments')) + if (len(args) % 2) != 0: + raise ValueError(_('strcat_max requires an even number of arguments')) + try: + max = int(args[0]) + except: + raise ValueError(_('first argument to strcat_max must be an integer')) + + i = 2 + result = args[1] + try: + while i < len(args): + if (len(result) + len(args[i]) + len(args[i+1])) > max: + break + result = result + args[i] + args[i+1] + i += 2 + except: + pass + return result.strip() + class BuiltinInList(BuiltinFormatterFunction): name = 'in_list' arg_count = 5 @@ -956,7 +1003,8 @@ _formatter_builtins = [ BuiltinLowercase(), BuiltinMultiply(), BuiltinNot(), BuiltinOndevice(), BuiltinOr(), BuiltinPrint(), BuiltinRawField(), BuiltinRe(), BuiltinSelect(), BuiltinShorten(), BuiltinStrcat(), - BuiltinStrcmp(), BuiltinStrInList(), BuiltinSubitems(), + BuiltinStrcatMax(), + BuiltinStrcmp(), BuiltinStrInList(), BuiltinStrlen(), BuiltinSubitems(), BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundComma(), BuiltinSwitch(), BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(), BuiltinToday(), BuiltinUppercase(),