mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
c0ff9b11e8
@ -610,6 +610,7 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
|
||||
* ``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.
|
||||
* ``switch_if([test_expression, value_expression,]+ else_expression)`` -- for each ``test_expression, value_expression`` pair, checks if ``test_expression`` is True (non-empty) and if so returns the result of ``value_expression``. If no ``test_expression`` is True then the result of ``else_expression` is returned. You can have as many ``test_expression, value_expressio`` pairs as you want.
|
||||
* ``today()`` -- return a date+time string for today (now). 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 <https://en.wikipedia.org/wiki/ISO_8601>`_ date/time format.
|
||||
* ``template(x)`` -- evaluates ``x`` as a template. The evaluation is done in its own context, meaning that variables are not shared between the caller and the template evaluation.
|
||||
* ``to_hex(val)`` -- returns the string ``val`` encoded in hex. This is useful when constructing calibre URLs.
|
||||
|
@ -55,6 +55,7 @@ class Node:
|
||||
NODE_LOCAL_FUNCTION_CALL = 29
|
||||
NODE_RANGE = 30
|
||||
NODE_SWITCH = 31
|
||||
NODE_SWITCH_IF = 32
|
||||
|
||||
def __init__(self, line_number, name):
|
||||
self.my_line_number = line_number
|
||||
@ -289,6 +290,13 @@ class SwitchNode(Node):
|
||||
self.expression_list = expression_list
|
||||
|
||||
|
||||
class SwitchIfNode(Node):
|
||||
def __init__(self, line_number, expression_list):
|
||||
Node.__init__(self, line_number, 'switch_if()')
|
||||
self.node_type = self.NODE_SWITCH_IF
|
||||
self.expression_list = expression_list
|
||||
|
||||
|
||||
class ContainsNode(Node):
|
||||
def __init__(self, line_number, arguments):
|
||||
Node.__init__(self, line_number, 'contains()')
|
||||
@ -687,6 +695,8 @@ class _Parser:
|
||||
lambda ln, args: FirstNonEmptyNode(ln, args)),
|
||||
'switch': (lambda args: len(args) >= 3 and (len(args) %2) == 0,
|
||||
lambda ln, args: SwitchNode(ln, args)),
|
||||
'switch_if': (lambda args: len(args) > 0 and (len(args) %2) == 1,
|
||||
lambda ln, args: SwitchIfNode(ln, args)),
|
||||
'assign': (lambda args: len(args) == 2 and len(args[0]) == 1 and args[0][0].node_type == Node.NODE_RVALUE,
|
||||
lambda ln, args: AssignNode(ln, args[0][0].name, args[1])),
|
||||
'contains': (lambda args: len(args) == 4,
|
||||
@ -1303,6 +1313,21 @@ class _Interpreter:
|
||||
self.break_reporter(prog.node_name, res, prog.line_number)
|
||||
return res
|
||||
|
||||
def do_node_switch_if(self, prog):
|
||||
for i in range(0, len(prog.expression_list)-1, 2):
|
||||
tst = self.expr(prog.expression_list[i])
|
||||
if self.break_reporter:
|
||||
self.break_reporter("switch_if(): test expr", tst, prog.line_number)
|
||||
if tst:
|
||||
res = self.expr(prog.expression_list[i+1])
|
||||
if self.break_reporter:
|
||||
self.break_reporter("switch_if(): value expr", res, prog.line_number)
|
||||
return res
|
||||
res = self.expr(prog.expression_list[-1])
|
||||
if (self.break_reporter):
|
||||
self.break_reporter("switch_if(): default expr", res, prog.line_number)
|
||||
return res
|
||||
|
||||
def do_node_strcat(self, prog):
|
||||
res = ''.join([self.expr(expr) for expr in prog.expression_list])
|
||||
if self.break_reporter:
|
||||
@ -1519,6 +1544,7 @@ class _Interpreter:
|
||||
Node.NODE_CALL_STORED_TEMPLATE: do_node_stored_template_call,
|
||||
Node.NODE_FIRST_NON_EMPTY: do_node_first_non_empty,
|
||||
Node.NODE_SWITCH: do_node_switch,
|
||||
Node.NODE_SWITCH_IF: do_node_switch_if,
|
||||
Node.NODE_FOR: do_node_for,
|
||||
Node.NODE_RANGE: do_node_range,
|
||||
Node.NODE_GLOBALS: do_node_globals,
|
||||
|
@ -667,6 +667,30 @@ class BuiltinSwitch(BuiltinFormatterFunction):
|
||||
i += 2
|
||||
|
||||
|
||||
class BuiltinSwitchIf(BuiltinFormatterFunction):
|
||||
name = 'switch_if'
|
||||
arg_count = -1
|
||||
category = 'Iterating over values'
|
||||
__doc__ = doc = _('switch_if([test_expression, value_expression,]+ else_expression) -- '
|
||||
'for each "test_expression, value_expression" pair, checks if test_expression '
|
||||
'is True (non-empty) and if so returns the result of value_expression. '
|
||||
'If no test_expression is True then the result of else_expression is returned. '
|
||||
'You can have as many "test_expression, value_expression" pairs as you want.')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, *args):
|
||||
if (len(args) % 2) != 1:
|
||||
raise ValueError(_('switch_if requires an odd number of arguments'))
|
||||
# We shouldn't get here because the function is inlined. However, someone
|
||||
# might call it directly.
|
||||
i = 0
|
||||
while i < len(args):
|
||||
if i + 1 >= len(args):
|
||||
return args[i]
|
||||
if args[i]:
|
||||
return args[i+1]
|
||||
i += 2
|
||||
|
||||
|
||||
class BuiltinStrcatMax(BuiltinFormatterFunction):
|
||||
name = 'strcat_max'
|
||||
arg_count = -1
|
||||
@ -2384,7 +2408,7 @@ _formatter_builtins = [
|
||||
BuiltinSetGlobals(), BuiltinShorten(), BuiltinStrcat(), BuiltinStrcatMax(),
|
||||
BuiltinStrcmp(), BuiltinStrcmpcase(), BuiltinStrInList(), BuiltinStrlen(), BuiltinSubitems(),
|
||||
BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundArticles(),
|
||||
BuiltinSwapAroundComma(), BuiltinSwitch(),
|
||||
BuiltinSwapAroundComma(), BuiltinSwitch(), BuiltinSwitchIf(),
|
||||
BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(), BuiltinToday(),
|
||||
BuiltinToHex(), BuiltinTransliterate(), BuiltinUppercase(), BuiltinUrlsFromIdentifiers(),
|
||||
BuiltinUserCategories(), BuiltinVirtualLibraries(), BuiltinAnnotationCount()
|
||||
|
Loading…
x
Reference in New Issue
Block a user