diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index 4ae0278133..32aeba9122 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -69,9 +69,12 @@ categories_use_field_for_author_name = 'author' # avg_rating: the averate rating of all the books referencing this item # sort: the sort value. For authors, this is the author_sort for that author # category: the category (e.g., authors, series) that the item is in. -categories_collapsed_name_template = '{first.sort:shorten(4,'',0)} - {last.sort:shorten(4,'',0)}' -categories_collapsed_rating_template = '{first.avg_rating:4.2f:ifempty(0)} - {last.avg_rating:4.2f:ifempty(0)}' -categories_collapsed_popularity_template = '{first.count:d} - {last.count:d}' +# Note that the "r'" in front of the { is necessary if there are backslashes +# (\ characters) in the template. It doesn't hurt anything to leave it there +# even if there aren't any backslashes. +categories_collapsed_name_template = r'{first.sort:shorten(4,'',0)} - {last.sort:shorten(4,'',0)}' +categories_collapsed_rating_template = r'{first.avg_rating:4.2f:ifempty(0)} - {last.avg_rating:4.2f:ifempty(0)}' +categories_collapsed_popularity_template = r'{first.count:d} - {last.count:d}' # Set whether boolean custom columns are two- or three-valued. diff --git a/src/calibre/manual/template_lang.rst b/src/calibre/manual/template_lang.rst index 8a3bd854b1..1bf08c11f9 100644 --- a/src/calibre/manual/template_lang.rst +++ b/src/calibre/manual/template_lang.rst @@ -150,7 +150,7 @@ The example shows several things: * program mode is used if the expression begins with ``:'`` and ends with ``'``. Anything else is assumed to be single-function. * the variable ``$`` stands for the field the expression is operating upon, ``#series`` in this case. - * functions must be given all their arguments. There is no default value. This is true for the standard builtin functions, and is a significant difference from single-function mode. + * functions must be given all their arguments. There is no default value. For example, the standard builtin functions must be given an additional initial parameter indicating the source field, which is a significant difference from single-function mode. * white space is ignored and can be used anywhere within the expression. * constant strings are enclosed in matching quotes, either ``'`` or ``"``. @@ -204,7 +204,7 @@ For various values of series_index, the program returns: All the functions listed under single-function mode can be used in program mode, noting that unlike the functions described below you must supply a first parameter providing the value the function is to act upon. -The following functions are available in addition to those described in single-function mode. With the exception of the ``id`` parameter of assign, all parameters can be statements (sequences of expressions): +The following functions are available in addition to those described in single-function mode. Remember from the example above that the single-function mode functions require an additional first parameter specifying the field to operate on. With the exception of the ``id`` parameter of assign, all parameters can be statements (sequences of expressions): * ``add(x, y)`` -- returns x + y. Throws an exception if either x or y are not numbers. * ``assign(id, val)`` -- assigns val to id, then returns val. id must be an identifier, not an expression diff --git a/src/calibre/utils/formatter.py b/src/calibre/utils/formatter.py index 4fe8ad2e4f..4e9710ad14 100644 --- a/src/calibre/utils/formatter.py +++ b/src/calibre/utils/formatter.py @@ -431,7 +431,10 @@ class TemplateFormatter(string.Formatter): return prefix + val + suffix def vformat(self, fmt, args, kwargs): - ans = string.Formatter.vformat(self, fmt, args, kwargs) + if fmt.startswith('program:'): + ans = self._eval_program(None, fmt[8:]) + else: + ans = string.Formatter.vformat(self, fmt, args, kwargs) return self.compress_spaces.sub(' ', ans).strip() ########## a formatter guaranteed not to throw and exception ############ @@ -441,10 +444,7 @@ class TemplateFormatter(string.Formatter): self.book = book self.composite_values = {} try: - if fmt.startswith('program:'): - ans = self._eval_program(None, fmt[8:]) - else: - ans = self.vformat(fmt, [], kwargs).strip() + ans = self.vformat(fmt, [], kwargs).strip() except Exception, e: if DEBUG: traceback.print_exc()