mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Various improvements:
1) Changes to the template program language discussed in https://www.mobileread.com/forums/showthread.php?t=337668 2) General improvement of the template documentation, including documentation of the above changes. I looked at the changes using a markdown interpreter, but there might be problems exposed by generation of the web page. 3) Focus the program text box when opening the template dialog 4) Small changes to non-built-in template functions to improve performance
This commit is contained in:
parent
eeb7672774
commit
ac9c9d6ab5
File diff suppressed because it is too large
Load Diff
@ -372,6 +372,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
|||||||
|
|
||||||
self.font_size_box.setValue(gprefs['gpm_template_editor_font_size'])
|
self.font_size_box.setValue(gprefs['gpm_template_editor_font_size'])
|
||||||
self.font_size_box.valueChanged.connect(self.font_size_changed)
|
self.font_size_box.valueChanged.connect(self.font_size_changed)
|
||||||
|
self.textbox.setFocus()
|
||||||
|
|
||||||
def font_size_changed(self, toWhat):
|
def font_size_changed(self, toWhat):
|
||||||
gprefs['gpm_template_editor_font_size'] = toWhat
|
gprefs['gpm_template_editor_font_size'] = toWhat
|
||||||
|
@ -10,6 +10,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import re, string, traceback, numbers
|
import re, string, traceback, numbers
|
||||||
|
from math import modf
|
||||||
|
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
from calibre.constants import DEBUG
|
from calibre.constants import DEBUG
|
||||||
@ -23,8 +24,8 @@ class Node(object):
|
|||||||
NODE_IF = 2
|
NODE_IF = 2
|
||||||
NODE_ASSIGN = 3
|
NODE_ASSIGN = 3
|
||||||
NODE_FUNC = 4
|
NODE_FUNC = 4
|
||||||
NODE_STRING_INFIX = 5
|
NODE_COMPARE_STRING = 5
|
||||||
NODE_NUMERIC_INFIX = 6
|
NODE_COMPARE_NUMERIC = 6
|
||||||
NODE_CONSTANT = 7
|
NODE_CONSTANT = 7
|
||||||
NODE_FIELD = 8
|
NODE_FIELD = 8
|
||||||
NODE_RAW_FIELD = 9
|
NODE_RAW_FIELD = 9
|
||||||
@ -35,6 +36,10 @@ class Node(object):
|
|||||||
NODE_GLOBALS = 14
|
NODE_GLOBALS = 14
|
||||||
NODE_SET_GLOBALS = 15
|
NODE_SET_GLOBALS = 15
|
||||||
NODE_CONTAINS = 16
|
NODE_CONTAINS = 16
|
||||||
|
NODE_BINARY_LOGOP = 17
|
||||||
|
NODE_UNARY_LOGOP = 18
|
||||||
|
NODE_BINARY_ARITHOP = 19
|
||||||
|
NODE_UNARY_ARITHOP = 20
|
||||||
|
|
||||||
|
|
||||||
class IfNode(Node):
|
class IfNode(Node):
|
||||||
@ -101,24 +106,58 @@ class SetGlobalsNode(Node):
|
|||||||
self.expression_list = expression_list
|
self.expression_list = expression_list
|
||||||
|
|
||||||
|
|
||||||
class StringInfixNode(Node):
|
class StringCompareNode(Node):
|
||||||
def __init__(self, operator, left, right):
|
def __init__(self, operator, left, right):
|
||||||
Node.__init__(self)
|
Node.__init__(self)
|
||||||
self.node_type = self.NODE_STRING_INFIX
|
self.node_type = self.NODE_COMPARE_STRING
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
|
|
||||||
|
|
||||||
class NumericInfixNode(Node):
|
class NumericCompareNode(Node):
|
||||||
def __init__(self, operator, left, right):
|
def __init__(self, operator, left, right):
|
||||||
Node.__init__(self)
|
Node.__init__(self)
|
||||||
self.node_type = self.NODE_NUMERIC_INFIX
|
self.node_type = self.NODE_COMPARE_NUMERIC
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
|
|
||||||
|
|
||||||
|
class LogopBinaryNode(Node):
|
||||||
|
def __init__(self, operator, left, right):
|
||||||
|
Node.__init__(self)
|
||||||
|
self.node_type = self.NODE_BINARY_LOGOP
|
||||||
|
self.operator = operator
|
||||||
|
self.left = left
|
||||||
|
self.right = right
|
||||||
|
|
||||||
|
|
||||||
|
class LogopUnaryNode(Node):
|
||||||
|
def __init__(self, operator, expr):
|
||||||
|
Node.__init__(self)
|
||||||
|
self.node_type = self.NODE_UNARY_LOGOP
|
||||||
|
self.operator = operator
|
||||||
|
self.expr = expr
|
||||||
|
|
||||||
|
|
||||||
|
class NumericBinaryNode(Node):
|
||||||
|
def __init__(self, operator, left, right):
|
||||||
|
Node.__init__(self)
|
||||||
|
self.node_type = self.NODE_BINARY_ARITHOP
|
||||||
|
self.operator = operator
|
||||||
|
self.left = left
|
||||||
|
self.right = right
|
||||||
|
|
||||||
|
|
||||||
|
class NumericUnaryNode(Node):
|
||||||
|
def __init__(self, operator, expr):
|
||||||
|
Node.__init__(self)
|
||||||
|
self.node_type = self.NODE_UNARY_ARITHOP
|
||||||
|
self.operator = operator
|
||||||
|
self.expr = expr
|
||||||
|
|
||||||
|
|
||||||
class ConstantNode(Node):
|
class ConstantNode(Node):
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
Node.__init__(self)
|
Node.__init__(self)
|
||||||
@ -252,6 +291,55 @@ class _Parser(object):
|
|||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def token_op_is_plus(self):
|
||||||
|
try:
|
||||||
|
token = self.prog[self.lex_pos]
|
||||||
|
return token[1] == '+' and token[0] == self.LEX_OP
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def token_op_is_minus(self):
|
||||||
|
try:
|
||||||
|
token = self.prog[self.lex_pos]
|
||||||
|
return token[1] == '-' and token[0] == self.LEX_OP
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def token_op_is_times(self):
|
||||||
|
try:
|
||||||
|
token = self.prog[self.lex_pos]
|
||||||
|
return token[1] == '*' and token[0] == self.LEX_OP
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def token_op_is_divide(self):
|
||||||
|
try:
|
||||||
|
token = self.prog[self.lex_pos]
|
||||||
|
return token[1] == '/' and token[0] == self.LEX_OP
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def token_op_is_and(self):
|
||||||
|
try:
|
||||||
|
token = self.prog[self.lex_pos]
|
||||||
|
return token[1] == '&&' and token[0] == self.LEX_OP
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def token_op_is_or(self):
|
||||||
|
try:
|
||||||
|
token = self.prog[self.lex_pos]
|
||||||
|
return token[1] == '||' and token[0] == self.LEX_OP
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def token_op_is_not(self):
|
||||||
|
try:
|
||||||
|
token = self.prog[self.lex_pos]
|
||||||
|
return token[1] == '!' and token[0] == self.LEX_OP
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
def token_is_id(self):
|
def token_is_id(self):
|
||||||
try:
|
try:
|
||||||
return self.prog[self.lex_pos][0] == self.LEX_ID
|
return self.prog[self.lex_pos][0] == self.LEX_ID
|
||||||
@ -357,7 +445,7 @@ class _Parser(object):
|
|||||||
def expression_list(self):
|
def expression_list(self):
|
||||||
expr_list = []
|
expr_list = []
|
||||||
while not self.token_is_eof():
|
while not self.token_is_eof():
|
||||||
expr_list.append(self.infix_expr())
|
expr_list.append(self.top_expr())
|
||||||
if not self.token_op_is_semicolon():
|
if not self.token_op_is_semicolon():
|
||||||
break
|
break
|
||||||
self.consume()
|
self.consume()
|
||||||
@ -365,7 +453,7 @@ class _Parser(object):
|
|||||||
|
|
||||||
def if_expression(self):
|
def if_expression(self):
|
||||||
self.consume()
|
self.consume()
|
||||||
condition = self.infix_expr()
|
condition = self.top_expr()
|
||||||
if not self.token_is_then():
|
if not self.token_is_then():
|
||||||
self.error(_("Missing 'then' in if statement"))
|
self.error(_("Missing 'then' in if statement"))
|
||||||
self.consume()
|
self.consume()
|
||||||
@ -390,7 +478,7 @@ class _Parser(object):
|
|||||||
if not self.token_is_in():
|
if not self.token_is_in():
|
||||||
self.error(_("Missing 'in' in for statement"))
|
self.error(_("Missing 'in' in for statement"))
|
||||||
self.consume()
|
self.consume()
|
||||||
list_expr = self.infix_expr()
|
list_expr = self.top_expr()
|
||||||
if self.token_is_separator():
|
if self.token_is_separator():
|
||||||
self.consume()
|
self.consume()
|
||||||
separator = self.expr()
|
separator = self.expr()
|
||||||
@ -405,16 +493,66 @@ class _Parser(object):
|
|||||||
self.consume()
|
self.consume()
|
||||||
return ForNode(variable, list_expr, separator, block)
|
return ForNode(variable, list_expr, separator, block)
|
||||||
|
|
||||||
def infix_expr(self):
|
def top_expr(self):
|
||||||
left = self.expr()
|
return self.or_expr()
|
||||||
|
|
||||||
|
def or_expr(self):
|
||||||
|
left = self.and_expr()
|
||||||
|
while self.token_op_is_or():
|
||||||
|
self.consume()
|
||||||
|
right = self.and_expr()
|
||||||
|
left = LogopBinaryNode('or', left, right)
|
||||||
|
return left
|
||||||
|
|
||||||
|
def and_expr(self):
|
||||||
|
left = self.not_expr()
|
||||||
|
while self.token_op_is_and():
|
||||||
|
self.consume()
|
||||||
|
right = self.not_expr()
|
||||||
|
left = LogopBinaryNode('and', left, right)
|
||||||
|
return left
|
||||||
|
|
||||||
|
def not_expr(self):
|
||||||
|
if self.token_op_is_not():
|
||||||
|
self.consume()
|
||||||
|
return LogopUnaryNode('not', self.not_expr())
|
||||||
|
return self.compare_expr()
|
||||||
|
|
||||||
|
def compare_expr(self):
|
||||||
|
left = self.add_subtract_expr()
|
||||||
if self.token_op_is_string_infix_compare() or self.token_is_in():
|
if self.token_op_is_string_infix_compare() or self.token_is_in():
|
||||||
operator = self.token()
|
operator = self.token()
|
||||||
return StringInfixNode(operator, left, self.expr())
|
return StringCompareNode(operator, left, self.add_subtract_expr())
|
||||||
if self.token_op_is_numeric_infix_compare():
|
if self.token_op_is_numeric_infix_compare():
|
||||||
operator = self.token()
|
operator = self.token()
|
||||||
return NumericInfixNode(operator, left, self.expr())
|
return NumericCompareNode(operator, left, self.add_subtract_expr())
|
||||||
return left
|
return left
|
||||||
|
|
||||||
|
def add_subtract_expr(self):
|
||||||
|
left = self.times_divide_expr()
|
||||||
|
while self.token_op_is_plus() or self.token_op_is_minus():
|
||||||
|
operator = self.token()
|
||||||
|
right = self.times_divide_expr()
|
||||||
|
left = NumericBinaryNode(operator, left, right)
|
||||||
|
return left
|
||||||
|
|
||||||
|
def times_divide_expr(self):
|
||||||
|
left = self.unary_plus_minus_expr()
|
||||||
|
while self.token_op_is_times() or self.token_op_is_divide():
|
||||||
|
operator = self.token()
|
||||||
|
right = self.unary_plus_minus_expr()
|
||||||
|
left = NumericBinaryNode(operator, left, right)
|
||||||
|
return left
|
||||||
|
|
||||||
|
def unary_plus_minus_expr(self):
|
||||||
|
if self.token_op_is_plus():
|
||||||
|
self.consume()
|
||||||
|
return NumericUnaryNode('+', self.unary_plus_minus_expr())
|
||||||
|
if self.token_op_is_minus():
|
||||||
|
self.consume()
|
||||||
|
return NumericUnaryNode('-', self.unary_plus_minus_expr())
|
||||||
|
return self.expr()
|
||||||
|
|
||||||
def call_expression(self, name, arguments):
|
def call_expression(self, name, arguments):
|
||||||
subprog = self.funcs[name].cached_parse_tree
|
subprog = self.funcs[name].cached_parse_tree
|
||||||
if subprog is None:
|
if subprog is None:
|
||||||
@ -428,6 +566,13 @@ class _Parser(object):
|
|||||||
return CallNode(subprog, arguments)
|
return CallNode(subprog, arguments)
|
||||||
|
|
||||||
def expr(self):
|
def expr(self):
|
||||||
|
if self.token_op_is_lparen():
|
||||||
|
self.consume()
|
||||||
|
rv = self.top_expr()
|
||||||
|
if not self.token_op_is_rparen():
|
||||||
|
self.error(_('Missing )'))
|
||||||
|
self.consume()
|
||||||
|
return rv
|
||||||
if self.token_is_if():
|
if self.token_is_if():
|
||||||
return self.if_expression()
|
return self.if_expression()
|
||||||
if self.token_is_for():
|
if self.token_is_for():
|
||||||
@ -439,7 +584,7 @@ class _Parser(object):
|
|||||||
if self.token_op_is_equals():
|
if self.token_op_is_equals():
|
||||||
# classic assignment statement
|
# classic assignment statement
|
||||||
self.consume()
|
self.consume()
|
||||||
return AssignNode(id_, self.infix_expr())
|
return AssignNode(id_, self.top_expr())
|
||||||
return VariableNode(id_)
|
return VariableNode(id_)
|
||||||
|
|
||||||
# We have a function.
|
# We have a function.
|
||||||
@ -453,7 +598,7 @@ class _Parser(object):
|
|||||||
arguments = list()
|
arguments = list()
|
||||||
while not self.token_op_is_rparen():
|
while not self.token_op_is_rparen():
|
||||||
# evaluate the expression (recursive call)
|
# evaluate the expression (recursive call)
|
||||||
arguments.append(self.infix_expr())
|
arguments.append(self.top_expr())
|
||||||
if not self.token_op_is_comma():
|
if not self.token_op_is_comma():
|
||||||
break
|
break
|
||||||
self.consume()
|
self.consume()
|
||||||
@ -520,7 +665,7 @@ class _Interpreter(object):
|
|||||||
val = self.expr(p)
|
val = self.expr(p)
|
||||||
return val
|
return val
|
||||||
|
|
||||||
INFIX_STRING_OPS = {
|
INFIX_STRING_COMPARE_OPS = {
|
||||||
"==": lambda x, y: strcmp(x, y) == 0,
|
"==": lambda x, y: strcmp(x, y) == 0,
|
||||||
"!=": lambda x, y: strcmp(x, y) != 0,
|
"!=": lambda x, y: strcmp(x, y) != 0,
|
||||||
"<": lambda x, y: strcmp(x, y) < 0,
|
"<": lambda x, y: strcmp(x, y) < 0,
|
||||||
@ -534,11 +679,11 @@ class _Interpreter(object):
|
|||||||
try:
|
try:
|
||||||
left = self.expr(prog.left)
|
left = self.expr(prog.left)
|
||||||
right = self.expr(prog.right)
|
right = self.expr(prog.right)
|
||||||
return ('1' if self.INFIX_STRING_OPS[prog.operator](left, right) else '')
|
return ('1' if self.INFIX_STRING_COMPARE_OPS[prog.operator](left, right) else '')
|
||||||
except:
|
except:
|
||||||
self.error(_('Error during string comparison. Operator {0}').format(prog.operator))
|
self.error(_('Error during string comparison. Operator {0}').format(prog.operator))
|
||||||
|
|
||||||
INFIX_NUMERIC_OPS = {
|
INFIX_NUMERIC_COMPARE_OPS = {
|
||||||
"==#": lambda x, y: x == y,
|
"==#": lambda x, y: x == y,
|
||||||
"!=#": lambda x, y: x != y,
|
"!=#": lambda x, y: x != y,
|
||||||
"<#": lambda x, y: x < y,
|
"<#": lambda x, y: x < y,
|
||||||
@ -556,7 +701,7 @@ class _Interpreter(object):
|
|||||||
try:
|
try:
|
||||||
left = self.float_deal_with_none(self.expr(prog.left))
|
left = self.float_deal_with_none(self.expr(prog.left))
|
||||||
right = self.float_deal_with_none(self.expr(prog.right))
|
right = self.float_deal_with_none(self.expr(prog.right))
|
||||||
return '1' if self.INFIX_NUMERIC_OPS[prog.operator](left, right) else ''
|
return '1' if self.INFIX_NUMERIC_COMPARE_OPS[prog.operator](left, right) else ''
|
||||||
except:
|
except:
|
||||||
self.error(_('Value used in comparison is not a number. Operator {0}').format(prog.operator))
|
self.error(_('Value used in comparison is not a number. Operator {0}').format(prog.operator))
|
||||||
|
|
||||||
@ -687,6 +832,55 @@ class _Interpreter(object):
|
|||||||
return self.expr(prog.match_expression)
|
return self.expr(prog.match_expression)
|
||||||
return self.expr(prog.not_match_expression)
|
return self.expr(prog.not_match_expression)
|
||||||
|
|
||||||
|
LOGICAL_BINARY_OPS = {
|
||||||
|
'and': lambda self, x, y: self.expr(x) and self.expr(y),
|
||||||
|
'or': lambda self, x, y: self.expr(x) or self.expr(y),
|
||||||
|
}
|
||||||
|
|
||||||
|
def do_node_logop(self, prog):
|
||||||
|
try:
|
||||||
|
return ('1' if self.LOGICAL_BINARY_OPS[prog.operator](self, prog.left, prog.right) else '')
|
||||||
|
except:
|
||||||
|
self.error(_('Error during operator evaluation. Operator {0}').format(prog.operator))
|
||||||
|
|
||||||
|
LOGICAL_UNARY_OPS = {
|
||||||
|
'not': lambda x: not x,
|
||||||
|
}
|
||||||
|
|
||||||
|
def do_node_logop_unary(self, prog):
|
||||||
|
try:
|
||||||
|
expr = self.expr(prog.expr)
|
||||||
|
return ('1' if self.LOGICAL_UNARY_OPS[prog.operator](expr) else '')
|
||||||
|
except:
|
||||||
|
self.error(_('Error during operator evaluation. Operator {0}').format(prog.operator))
|
||||||
|
|
||||||
|
ARITHMETIC_BINARY_OPS = {
|
||||||
|
'+': lambda x, y: x + y,
|
||||||
|
'-': lambda x, y: x - y,
|
||||||
|
'*': lambda x, y: x * y,
|
||||||
|
'/': lambda x, y: x / y,
|
||||||
|
}
|
||||||
|
|
||||||
|
def do_node_binary_arithop(self, prog):
|
||||||
|
try:
|
||||||
|
answer = self.ARITHMETIC_BINARY_OPS[prog.operator](float(self.expr(prog.left)),
|
||||||
|
float(self.expr(prog.right)))
|
||||||
|
return unicode_type(answer if modf(answer)[0] != 0 else int(answer))
|
||||||
|
except:
|
||||||
|
self.error(_('Error during arithmetic operator evaluation. Operator {0}').format(prog.operator))
|
||||||
|
|
||||||
|
ARITHMETIC_UNARY_OPS = {
|
||||||
|
'+': lambda x: x,
|
||||||
|
'-': lambda x: -x,
|
||||||
|
}
|
||||||
|
|
||||||
|
def do_node_unary_arithop(self, prog):
|
||||||
|
try:
|
||||||
|
expr = self.ARITHMETIC_UNARY_OPS[prog.operator](float(self.expr(prog.expr)))
|
||||||
|
return unicode_type(expr if modf(expr)[0] != 0 else int(expr))
|
||||||
|
except:
|
||||||
|
self.error(_('Error during arithmetic operator evaluation. Operator {0}').format(prog.operator))
|
||||||
|
|
||||||
NODE_OPS = {
|
NODE_OPS = {
|
||||||
Node.NODE_IF: do_node_if,
|
Node.NODE_IF: do_node_if,
|
||||||
Node.NODE_ASSIGN: do_node_assign,
|
Node.NODE_ASSIGN: do_node_assign,
|
||||||
@ -695,8 +889,8 @@ class _Interpreter(object):
|
|||||||
Node.NODE_FUNC: do_node_func,
|
Node.NODE_FUNC: do_node_func,
|
||||||
Node.NODE_FIELD: do_node_field,
|
Node.NODE_FIELD: do_node_field,
|
||||||
Node.NODE_RAW_FIELD: do_node_raw_field,
|
Node.NODE_RAW_FIELD: do_node_raw_field,
|
||||||
Node.NODE_STRING_INFIX: do_node_string_infix,
|
Node.NODE_COMPARE_STRING: do_node_string_infix,
|
||||||
Node.NODE_NUMERIC_INFIX: do_node_numeric_infix,
|
Node.NODE_COMPARE_NUMERIC:do_node_numeric_infix,
|
||||||
Node.NODE_ARGUMENTS: do_node_arguments,
|
Node.NODE_ARGUMENTS: do_node_arguments,
|
||||||
Node.NODE_CALL: do_node_call,
|
Node.NODE_CALL: do_node_call,
|
||||||
Node.NODE_FIRST_NON_EMPTY:do_node_first_non_empty,
|
Node.NODE_FIRST_NON_EMPTY:do_node_first_non_empty,
|
||||||
@ -704,6 +898,10 @@ class _Interpreter(object):
|
|||||||
Node.NODE_GLOBALS: do_node_globals,
|
Node.NODE_GLOBALS: do_node_globals,
|
||||||
Node.NODE_SET_GLOBALS: do_node_set_globals,
|
Node.NODE_SET_GLOBALS: do_node_set_globals,
|
||||||
Node.NODE_CONTAINS: do_node_contains,
|
Node.NODE_CONTAINS: do_node_contains,
|
||||||
|
Node.NODE_BINARY_LOGOP: do_node_logop,
|
||||||
|
Node.NODE_UNARY_LOGOP: do_node_logop_unary,
|
||||||
|
Node.NODE_BINARY_ARITHOP: do_node_binary_arithop,
|
||||||
|
Node.NODE_UNARY_ARITHOP: do_node_unary_arithop,
|
||||||
}
|
}
|
||||||
|
|
||||||
def expr(self, prog):
|
def expr(self, prog):
|
||||||
@ -781,14 +979,15 @@ class TemplateFormatter(string.Formatter):
|
|||||||
(r'.*?\)', lambda x,t: t[:-1]),
|
(r'.*?\)', lambda x,t: t[:-1]),
|
||||||
])
|
])
|
||||||
|
|
||||||
# ################# 'Functional' template language ######################
|
# ################# Template language lexical analyzer ######################
|
||||||
|
|
||||||
lex_scanner = re.Scanner([
|
lex_scanner = re.Scanner([
|
||||||
(r'(==#|!=#|<=#|<#|>=#|>#)', lambda x,t: (_Parser.LEX_NUMERIC_INFIX, t)),
|
(r'(==#|!=#|<=#|<#|>=#|>#)', lambda x,t: (_Parser.LEX_NUMERIC_INFIX, t)),
|
||||||
(r'(==|!=|<=|<|>=|>)', lambda x,t: (_Parser.LEX_STRING_INFIX, t)), # noqa
|
(r'(==|!=|<=|<|>=|>)', lambda x,t: (_Parser.LEX_STRING_INFIX, t)), # noqa
|
||||||
(r'(if|then|else|elif|fi)\b',lambda x,t: (_Parser.LEX_KEYWORD, t)), # noqa
|
(r'(if|then|else|elif|fi)\b',lambda x,t: (_Parser.LEX_KEYWORD, t)), # noqa
|
||||||
(r'(for|in|rof)\b', lambda x,t: (_Parser.LEX_KEYWORD, t)), # noqa
|
(r'(for|in|rof)\b', lambda x,t: (_Parser.LEX_KEYWORD, t)), # noqa
|
||||||
(r'[(),=;:]', lambda x,t: (_Parser.LEX_OP, t)), # noqa
|
(r'(\|\||&&|!)', lambda x,t: (_Parser.LEX_OP, t)), # noqa
|
||||||
|
(r'[(),=;:\+\-*/]', lambda x,t: (_Parser.LEX_OP, t)), # noqa
|
||||||
(r'-?[\d\.]+', lambda x,t: (_Parser.LEX_CONST, t)), # noqa
|
(r'-?[\d\.]+', lambda x,t: (_Parser.LEX_CONST, t)), # noqa
|
||||||
(r'\$', lambda x,t: (_Parser.LEX_ID, t)), # noqa
|
(r'\$', lambda x,t: (_Parser.LEX_ID, t)), # noqa
|
||||||
(r'\w+', lambda x,t: (_Parser.LEX_ID, t)), # noqa
|
(r'\w+', lambda x,t: (_Parser.LEX_ID, t)), # noqa
|
||||||
|
@ -884,9 +884,10 @@ class BuiltinSelect(BuiltinFormatterFunction):
|
|||||||
if not val:
|
if not val:
|
||||||
return ''
|
return ''
|
||||||
vals = [v.strip() for v in val.split(',')]
|
vals = [v.strip() for v in val.split(',')]
|
||||||
|
tkey = key+':'
|
||||||
for v in vals:
|
for v in vals:
|
||||||
if v.startswith(key+':'):
|
if v.startswith(tkey):
|
||||||
return v[len(key)+1:]
|
return v[len(tkey):]
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
@ -1096,7 +1097,7 @@ class BuiltinSubitems(BuiltinFormatterFunction):
|
|||||||
si = int(start_index)
|
si = int(start_index)
|
||||||
ei = int(end_index)
|
ei = int(end_index)
|
||||||
has_periods = '.' in val
|
has_periods = '.' in val
|
||||||
items = [v.strip() for v in val.split(',')]
|
items = [v.strip() for v in val.split(',') if v.strip()]
|
||||||
rv = set()
|
rv = set()
|
||||||
for item in items:
|
for item in items:
|
||||||
if has_periods and '.' in item:
|
if has_periods and '.' in item:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user