diff --git a/manual/template_lang.rst b/manual/template_lang.rst index c9956cf177..548c248d13 100644 --- a/manual/template_lang.rst +++ b/manual/template_lang.rst @@ -340,6 +340,16 @@ The following functions are available in addition to those described in single-f * ``round(x)`` -- returns the nearest integer to x. Throws an exception if x is not a number. * ``series_sort()`` -- returns the series sort value. + * ``'split(list_val, sep, id_prefix)`` -- splits the ``list_val`` into separate values using ``sep``, then assigns the values to variables named ``id_prefix_N`` where N is the position of the value in the list. The first item has position 0 (zero). The function returns the last element in the list. Example:: + + split('one, two, foo', ',', 'var') + + is equivalent to:: + + var_0 = 'one'; + var_1 = 'two'; + var_3 = 'foo + * ``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``. diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index e0513c2922..7e1ebd09f1 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -146,7 +146,7 @@ class BuiltinFormatterFunction(FormatterFunction): def __init__(self): formatter_functions().register_builtin(self) eval_func = inspect.getmembers(self.__class__, - lambda x: inspect.ismethod(x) and x.__name__ == 'evaluate') + lambda x: inspect.isfunction(x) and x.__name__ == 'evaluate') try: lines = [l[4:] for l in inspect.getsourcelines(eval_func[0][1])[0]] except: @@ -404,6 +404,26 @@ class BuiltinAssign(BuiltinFormatterFunction): return value +class BuiltinListSplit(BuiltinFormatterFunction): + name = 'list_split' + arg_count = 3 + category = 'List manipulation' + __doc__ = doc = _('split(list_val, sep, id_prefix) -- splits the list_val ' + "into separate values using 'sep', then assigns the values " + "to variables named 'id_prefix_N' where N is the position " + "of the value in the list. The first item has position 0 (zero). " + "The function returns the last element in the list. " + "Example: split('one, two, foo', ',', 'var') is equivalent " + "to var_0 = 'one'; var_1 = 'two'; var_3 = 'foo'.") + + def evaluate(self, formatter, kwargs, mi, locals, list_val, sep, id_prefix): + l = [v.strip() for v in list_val.split(sep)] + res = '' + for i,v in enumerate(l): + res = locals[id_prefix+'_'+unicode_type(i)] = v + return res + + class BuiltinPrint(BuiltinFormatterFunction): name = 'print' arg_count = -1 @@ -1885,7 +1905,8 @@ _formatter_builtins = [ BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(), BuiltinInList(), BuiltinListDifference(), BuiltinListEquals(), BuiltinListIntersection(), BuiltinListitem(), BuiltinListRe(), - BuiltinListReGroup(), BuiltinListSort(), BuiltinListUnion(), BuiltinLookup(), + BuiltinListReGroup(), BuiltinListSort(), BuiltinListSplit(), BuiltinListUnion(), + BuiltinLookup(), BuiltinLowercase(), BuiltinMod(), BuiltinMultiply(), BuiltinNot(), BuiltinOndevice(), BuiltinOr(), BuiltinPrint(), BuiltinRatingToStars(), BuiltinRawField(), BuiltinRawList(), BuiltinRe(), BuiltinReGroup(), BuiltinRound(), BuiltinSelect(), BuiltinSeriesSort(),