diff --git a/manual/template_lang.rst b/manual/template_lang.rst index 36fc4e8f9f..ddf219e99b 100644 --- a/manual/template_lang.rst +++ b/manual/template_lang.rst @@ -603,6 +603,10 @@ In `GPM` the functions described in `Single Function Mode` all require an additi * ``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``. Strings made from ``prefix, string`` pairs are added to the end of the value as long as the resulting string length is less than ``max``. Prefixes can be empty. Returns ``string1`` 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 lexical comparison of ``x`` and ``y``. Returns ``lt`` if ``x < y``, ``eq`` if ``x == y``, otherwise ``gt``. This function can often be replaced by one of the lexical comparison operators (``==``, ``>``, ``<``, etc.) +* ``strcmpcase(x, y, lt, eq, gt)`` -- does a case-sensitive lexical comparison of ``x`` and ``y``. Returns ``lt`` if ``x < y``, ``eq`` if ``x == y``, otherwise ``gt``. + + Note: This is NOT the default behavior used by calibre, for example, in the lexical comparison operators (``==``, ``>``, ``<``, etc.). This function could cause unexpected results, preferably use ``strcmp()`` whenever possible. + * ``strlen(value)`` -- Returns the length of the string ``value``. * ``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. This function can usually be replaced by the ``-`` operator. diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 0c0efab5f8..977383fdc6 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -197,6 +197,27 @@ class BuiltinStrcmp(BuiltinFormatterFunction): return gt +class BuiltinStrcmpcase(BuiltinFormatterFunction): + name = 'strcmpcase' + arg_count = 5 + category = 'Relational' + __doc__ = doc = _('strcmpcase(x, y, lt, eq, gt) -- does a case-sensitive comparison of x ' + 'and y as strings. Returns lt if x < y. Returns eq if x == y. ' + 'Otherwise returns gt.\n' + 'Note: This is NOT the default behavior used by calibre, for example, in the ' + 'lexical comparison operators (==, >, <, etc.). This function could ' + 'cause unexpected results, preferably use strcmp() whenever possible.') + + def evaluate(self, formatter, kwargs, mi, locals, x, y, lt, eq, gt): + from calibre.utils.icu import case_sensitive_strcmp as case_strcmp + v = case_strcmp(x, y) + if v < 0: + return lt + if v == 0: + return eq + return gt + + class BuiltinCmp(BuiltinFormatterFunction): name = 'cmp' category = 'Relational' @@ -2325,7 +2346,7 @@ _formatter_builtins = [ BuiltinRawField(), BuiltinRawList(), BuiltinRe(), BuiltinReGroup(), BuiltinRound(), BuiltinSelect(), BuiltinSeriesSort(), BuiltinSetGlobals(), BuiltinShorten(), BuiltinStrcat(), BuiltinStrcatMax(), - BuiltinStrcmp(), BuiltinStrInList(), BuiltinStrlen(), BuiltinSubitems(), + BuiltinStrcmp(), BuiltinStrcmpcase(), BuiltinStrInList(), BuiltinStrlen(), BuiltinSubitems(), BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundArticles(), BuiltinSwapAroundComma(), BuiltinSwitch(), BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(),