mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Many small changes to the new formatter function stuff:
1) put isempty back. 2) use 'inspect' to get the source code for builtins so it can be displayed in the managemnet dialog box 3) change 'eval' to 'eval_' 4) do a better job of formatting exceptions 5) many changes to the help text 6) added a 'replace' box to the management dialog, so it is visually clear how to modify a function 7) got rid of a print statement
This commit is contained in:
parent
35f05e2866
commit
eb0ebd4df0
@ -25,37 +25,49 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
template function is written in python. It takes information from the
|
template function is written in python. It takes information from the
|
||||||
book, processes it in some way, then returns a string result. Functions
|
book, processes it in some way, then returns a string result. Functions
|
||||||
defined here are usable in templates in the same way that builtin
|
defined here are usable in templates in the same way that builtin
|
||||||
functions are usable. The function must be named evaluate, and must
|
functions are usable. The function must be named <b>evaluate</b>, and
|
||||||
have the signature shown below.</p>
|
must have the signature shown below.</p>
|
||||||
<p><code>evaluate(self, formatter, kwargs, mi, locals, your_arguments)
|
<p><code>evaluate(self, formatter, kwargs, mi, locals, your parameters)
|
||||||
→ returning a unicode string</code></p>
|
→ returning a unicode string</code></p>
|
||||||
<p>The arguments to evaluate are:
|
<p>The parameters of the evaluate function are:
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>formatter:</b> the instance of the formatter being used to
|
<li><b>formatter</b>: the instance of the formatter being used to
|
||||||
evaluate the current template. You can use this to do recursive
|
evaluate the current template. You can use this to do recursive
|
||||||
template evaluation.</li>
|
template evaluation.</li>
|
||||||
<li><b>kwargs:</b> a dictionary of metadata. Field values are in this
|
<li><b>kwargs</b>: a dictionary of metadata. Field values are in this
|
||||||
dictionary. mi: a Metadata instance. Used to get field information.
|
dictionary.
|
||||||
|
<li><b>mi</b>: a Metadata instance. Used to get field information.
|
||||||
This parameter can be None in some cases, such as when evaluating
|
This parameter can be None in some cases, such as when evaluating
|
||||||
non-book templates.</li>
|
non-book templates.</li>
|
||||||
<li><b>locals:</b> the local variables assigned to by the current
|
<li><b>locals</b>: the local variables assigned to by the current
|
||||||
template program.</li>
|
template program.</li>
|
||||||
<li><b>Your_arguments</b> must be one or more parameter (number
|
<li><b>your parameters</b>: You must supply one or more formal
|
||||||
matching the arg count box), or the value *args for a variable number
|
parameters. The number must match the arg count box, unless arg count is
|
||||||
of arguments. These are values passed into the function. One argument
|
-1 (variable number or arguments), in which case the last argument must
|
||||||
is required, and is usually the value of the field being operated upon.
|
be *args. At least one argument is required, and is usually the value of
|
||||||
Note that when writing in basic template mode, the user does not
|
the field being operated upon. Note that when writing in basic template
|
||||||
provide this first argument. Instead it is the value of the field the
|
mode, the user does not provide this first argument. Instead it is
|
||||||
function is operating upon.</li>
|
supplied by the formatter.</li>
|
||||||
</ul></p>
|
</ul></p>
|
||||||
<p>
|
<p>
|
||||||
The following example function looks for various values in the tags
|
The following example function checks the value of the field. If the
|
||||||
metadata field, returning those values that appear in tags.
|
field is not empty, the field's value is returned, otherwise the value
|
||||||
|
EMPTY is returned.
|
||||||
<pre>
|
<pre>
|
||||||
|
name: my_ifempty
|
||||||
|
arg count: 1
|
||||||
|
doc: my_ifempty(val) -- return val if it is not empty, otherwise the string 'EMPTY'
|
||||||
|
program code:
|
||||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||||
awards=['allbooks', 'PBook', 'ggff']
|
if val:
|
||||||
return ', '.join([t for t in kwargs.get('tags') if t in awards])
|
return val
|
||||||
</pre>
|
else:
|
||||||
|
return 'EMPTY'</pre>
|
||||||
|
This function can be called in any of the three template program modes:
|
||||||
|
<ul>
|
||||||
|
<li>single-function mode: {tags:my_ifempty()}</li>
|
||||||
|
<li>template program mode: {tags:'my_ifempty($)'}</li>
|
||||||
|
<li>general program mode: program: my_ifempty(field('tags'))</li>
|
||||||
</p>
|
</p>
|
||||||
''')
|
''')
|
||||||
self.textBrowser.setHtml(help_text)
|
self.textBrowser.setHtml(help_text)
|
||||||
@ -67,14 +79,22 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.build_function_names_box()
|
self.build_function_names_box()
|
||||||
self.function_name.currentIndexChanged[str].connect(self.function_index_changed)
|
self.function_name.currentIndexChanged[str].connect(self.function_index_changed)
|
||||||
self.function_name.editTextChanged.connect(self.function_name_edited)
|
self.function_name.editTextChanged.connect(self.function_name_edited)
|
||||||
|
self.argument_count.valueChanged.connect(self.enable_replace_button)
|
||||||
|
self.documentation.textChanged.connect(self.enable_replace_button)
|
||||||
|
self.program.textChanged.connect(self.enable_replace_button)
|
||||||
self.create_button.clicked.connect(self.create_button_clicked)
|
self.create_button.clicked.connect(self.create_button_clicked)
|
||||||
self.delete_button.clicked.connect(self.delete_button_clicked)
|
self.delete_button.clicked.connect(self.delete_button_clicked)
|
||||||
self.create_button.setEnabled(False)
|
self.create_button.setEnabled(False)
|
||||||
self.delete_button.setEnabled(False)
|
self.delete_button.setEnabled(False)
|
||||||
|
self.replace_button.setEnabled(False)
|
||||||
self.clear_button.clicked.connect(self.clear_button_clicked)
|
self.clear_button.clicked.connect(self.clear_button_clicked)
|
||||||
|
self.replace_button.clicked.connect(self.replace_button_clicked)
|
||||||
self.program.setTabStopWidth(20)
|
self.program.setTabStopWidth(20)
|
||||||
self.highlighter = PythonHighlighter(self.program.document())
|
self.highlighter = PythonHighlighter(self.program.document())
|
||||||
|
|
||||||
|
def enable_replace_button(self):
|
||||||
|
self.replace_button.setEnabled(self.delete_button.isEnabled())
|
||||||
|
|
||||||
def clear_button_clicked(self):
|
def clear_button_clicked(self):
|
||||||
self.build_function_names_box()
|
self.build_function_names_box()
|
||||||
self.program.clear()
|
self.program.clear()
|
||||||
@ -112,6 +132,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.create_button.setEnabled(True)
|
self.create_button.setEnabled(True)
|
||||||
self.delete_button.setEnabled(False)
|
self.delete_button.setEnabled(False)
|
||||||
self.build_function_names_box(set_to=name)
|
self.build_function_names_box(set_to=name)
|
||||||
|
self.program.setReadOnly(False)
|
||||||
else:
|
else:
|
||||||
error_dialog(self.gui, _('Template functions'),
|
error_dialog(self.gui, _('Template functions'),
|
||||||
_('Function not defined'), show=True)
|
_('Function not defined'), show=True)
|
||||||
@ -143,6 +164,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.documentation.setReadOnly(False)
|
self.documentation.setReadOnly(False)
|
||||||
self.argument_count.setReadOnly(False)
|
self.argument_count.setReadOnly(False)
|
||||||
self.create_button.setEnabled(True)
|
self.create_button.setEnabled(True)
|
||||||
|
self.replace_button.setEnabled(False)
|
||||||
|
self.program.setReadOnly(False)
|
||||||
|
|
||||||
def function_index_changed(self, txt):
|
def function_index_changed(self, txt):
|
||||||
txt = unicode(txt)
|
txt = unicode(txt)
|
||||||
@ -156,15 +179,21 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
func = self.funcs[txt]
|
func = self.funcs[txt]
|
||||||
self.argument_count.setValue(func.arg_count)
|
self.argument_count.setValue(func.arg_count)
|
||||||
self.documentation.setText(func.doc)
|
self.documentation.setText(func.doc)
|
||||||
|
self.program.setPlainText(func.program_text)
|
||||||
if txt in self.builtins:
|
if txt in self.builtins:
|
||||||
self.documentation.setReadOnly(True)
|
self.documentation.setReadOnly(True)
|
||||||
self.argument_count.setReadOnly(True)
|
self.argument_count.setReadOnly(True)
|
||||||
self.program.clear()
|
self.program.setReadOnly(True)
|
||||||
self.delete_button.setEnabled(False)
|
self.delete_button.setEnabled(False)
|
||||||
else:
|
else:
|
||||||
self.program.setPlainText(func.program_text)
|
self.program.setPlainText(func.program_text)
|
||||||
self.delete_button.setEnabled(True)
|
self.delete_button.setEnabled(True)
|
||||||
|
self.program.setReadOnly(False)
|
||||||
|
self.replace_button.setEnabled(False)
|
||||||
|
|
||||||
|
def replace_button_clicked(self):
|
||||||
|
self.delete_button_clicked()
|
||||||
|
self.create_button_clicked()
|
||||||
def refresh_gui(self, gui):
|
def refresh_gui(self, gui):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QComboBox" name="function_name">
|
<widget class="QComboBox" name="function_name">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Enter the name of the function to create</string>
|
<string>Enter the name of the function to create.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -48,7 +48,7 @@
|
|||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string></string>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Arg &count:</string>
|
<string>Arg &count:</string>
|
||||||
@ -100,6 +100,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="replace_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>Replace</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="create_button">
|
<widget class="QPushButton" name="create_button">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -144,8 +151,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QTextBrowser" name="textBrowser">
|
<widget class="QTextBrowser" name="textBrowser"/>
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -96,7 +96,7 @@ class _Parser(object):
|
|||||||
# classic assignment statement
|
# classic assignment statement
|
||||||
self.consume()
|
self.consume()
|
||||||
cls = funcs['assign']
|
cls = funcs['assign']
|
||||||
return cls.eval(self.parent, self.parent.kwargs,
|
return cls.eval_(self.parent, self.parent.kwargs,
|
||||||
self.parent.book, self.parent.locals, id, self.expr())
|
self.parent.book, self.parent.locals, id, self.expr())
|
||||||
return self.parent.locals.get(id, _('unknown id ') + id)
|
return self.parent.locals.get(id, _('unknown id ') + id)
|
||||||
# We have a function.
|
# We have a function.
|
||||||
@ -130,7 +130,7 @@ class _Parser(object):
|
|||||||
cls = funcs[id]
|
cls = funcs[id]
|
||||||
if cls.arg_count != -1 and len(args) != cls.arg_count:
|
if cls.arg_count != -1 and len(args) != cls.arg_count:
|
||||||
self.error('incorrect number of arguments for function {}'.format(id))
|
self.error('incorrect number of arguments for function {}'.format(id))
|
||||||
return cls.eval(self.parent, self.parent.kwargs,
|
return cls.eval_(self.parent, self.parent.kwargs,
|
||||||
self.parent.book, self.parent.locals, *args)
|
self.parent.book, self.parent.locals, *args)
|
||||||
else:
|
else:
|
||||||
f = self.parent.functions[id]
|
f = self.parent.functions[id]
|
||||||
@ -286,12 +286,11 @@ class TemplateFormatter(string.Formatter):
|
|||||||
args = [self.backslash_comma_to_comma.sub(',', a) for a in args]
|
args = [self.backslash_comma_to_comma.sub(',', a) for a in args]
|
||||||
if (func.arg_count == 1 and (len(args) != 0)) or \
|
if (func.arg_count == 1 and (len(args) != 0)) or \
|
||||||
(func.arg_count > 1 and func.arg_count != len(args)+1):
|
(func.arg_count > 1 and func.arg_count != len(args)+1):
|
||||||
print args
|
|
||||||
raise ValueError('Incorrect number of arguments for function '+ fmt[0:p])
|
raise ValueError('Incorrect number of arguments for function '+ fmt[0:p])
|
||||||
if func.arg_count == 1:
|
if func.arg_count == 1:
|
||||||
val = func.eval(self, self.kwargs, self.book, self.locals, val).strip()
|
val = func.eval_(self, self.kwargs, self.book, self.locals, val).strip()
|
||||||
else:
|
else:
|
||||||
val = func.eval(self, self.kwargs, self.book, self.locals,
|
val = func.eval_(self, self.kwargs, self.book, self.locals,
|
||||||
val, *args).strip()
|
val, *args).strip()
|
||||||
if val:
|
if val:
|
||||||
val = self._do_format(val, dispfmt)
|
val = self._do_format(val, dispfmt)
|
||||||
|
@ -8,7 +8,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import re, traceback
|
import inspect, re, traceback, sys
|
||||||
|
|
||||||
from calibre.utils.titlecase import titlecase
|
from calibre.utils.titlecase import titlecase
|
||||||
from calibre.utils.icu import capitalize, strcmp
|
from calibre.utils.icu import capitalize, strcmp
|
||||||
@ -58,13 +58,10 @@ class FormatterFunction(object):
|
|||||||
name = 'no name provided'
|
name = 'no name provided'
|
||||||
arg_count = 0
|
arg_count = 0
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
formatter_functions.register_builtin(self)
|
|
||||||
|
|
||||||
def evaluate(self, formatter, kwargs, mi, locals, *args):
|
def evaluate(self, formatter, kwargs, mi, locals, *args):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def eval(self, formatter, kwargs, mi, locals, *args):
|
def eval_(self, formatter, kwargs, mi, locals, *args):
|
||||||
try:
|
try:
|
||||||
ret = self.evaluate(formatter, kwargs, mi, locals, *args)
|
ret = self.evaluate(formatter, kwargs, mi, locals, *args)
|
||||||
if isinstance(ret, (str, unicode)):
|
if isinstance(ret, (str, unicode)):
|
||||||
@ -75,9 +72,21 @@ class FormatterFunction(object):
|
|||||||
return ','.join(list)
|
return ','.join(list)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return _('Function threw exception' + traceback.format_exc())
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
|
info = ': '.join(traceback.format_exception(exc_type, exc_value,
|
||||||
|
exc_traceback)[-2:]).replace('\n', '')
|
||||||
|
return _('Exception ' + info)
|
||||||
|
|
||||||
class BuiltinStrcmp(FormatterFunction):
|
|
||||||
|
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')
|
||||||
|
lines = [l[4:] for l in inspect.getsourcelines(eval_func[0][1])[0]]
|
||||||
|
self.program_text = ''.join(lines)
|
||||||
|
|
||||||
|
class BuiltinStrcmp(BuiltinFormatterFunction):
|
||||||
name = 'strcmp'
|
name = 'strcmp'
|
||||||
arg_count = 5
|
arg_count = 5
|
||||||
doc = _('strcmp(x, y, lt, eq, gt) -- does a case-insensitive comparison of x '
|
doc = _('strcmp(x, y, lt, eq, gt) -- does a case-insensitive comparison of x '
|
||||||
@ -92,7 +101,7 @@ class BuiltinStrcmp(FormatterFunction):
|
|||||||
return eq
|
return eq
|
||||||
return gt
|
return gt
|
||||||
|
|
||||||
class BuiltinCmp(FormatterFunction):
|
class BuiltinCmp(BuiltinFormatterFunction):
|
||||||
name = 'cmp'
|
name = 'cmp'
|
||||||
arg_count = 5
|
arg_count = 5
|
||||||
doc = _('cmp(x, y, lt, eq, gt) -- compares x and y after converting both to '
|
doc = _('cmp(x, y, lt, eq, gt) -- compares x and y after converting both to '
|
||||||
@ -107,7 +116,7 @@ class BuiltinCmp(FormatterFunction):
|
|||||||
return eq
|
return eq
|
||||||
return gt
|
return gt
|
||||||
|
|
||||||
class BuiltinStrcat(FormatterFunction):
|
class BuiltinStrcat(BuiltinFormatterFunction):
|
||||||
name = 'strcat'
|
name = 'strcat'
|
||||||
arg_count = -1
|
arg_count = -1
|
||||||
doc = _('strcat(a, b, ...) -- can take any number of arguments. Returns a '
|
doc = _('strcat(a, b, ...) -- can take any number of arguments. Returns a '
|
||||||
@ -120,7 +129,7 @@ class BuiltinStrcat(FormatterFunction):
|
|||||||
res += args[i]
|
res += args[i]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
class BuiltinAdd(FormatterFunction):
|
class BuiltinAdd(BuiltinFormatterFunction):
|
||||||
name = 'add'
|
name = 'add'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
doc = _('add(x, y) -- returns x + y. Throws an exception if either x or y are not numbers.')
|
doc = _('add(x, y) -- returns x + y. Throws an exception if either x or y are not numbers.')
|
||||||
@ -130,7 +139,7 @@ class BuiltinAdd(FormatterFunction):
|
|||||||
y = float(y if y else 0)
|
y = float(y if y else 0)
|
||||||
return unicode(x + y)
|
return unicode(x + y)
|
||||||
|
|
||||||
class BuiltinSubtract(FormatterFunction):
|
class BuiltinSubtract(BuiltinFormatterFunction):
|
||||||
name = 'subtract'
|
name = 'subtract'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
doc = _('subtract(x, y) -- returns x - y. Throws an exception if either x or y are not numbers.')
|
doc = _('subtract(x, y) -- returns x - y. Throws an exception if either x or y are not numbers.')
|
||||||
@ -140,7 +149,7 @@ class BuiltinSubtract(FormatterFunction):
|
|||||||
y = float(y if y else 0)
|
y = float(y if y else 0)
|
||||||
return unicode(x - y)
|
return unicode(x - y)
|
||||||
|
|
||||||
class BuiltinMultiply(FormatterFunction):
|
class BuiltinMultiply(BuiltinFormatterFunction):
|
||||||
name = 'multiply'
|
name = 'multiply'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
doc = _('multiply(x, y) -- returns x * y. Throws an exception if either x or y are not numbers.')
|
doc = _('multiply(x, y) -- returns x * y. Throws an exception if either x or y are not numbers.')
|
||||||
@ -150,7 +159,7 @@ class BuiltinMultiply(FormatterFunction):
|
|||||||
y = float(y if y else 0)
|
y = float(y if y else 0)
|
||||||
return unicode(x * y)
|
return unicode(x * y)
|
||||||
|
|
||||||
class BuiltinDivide(FormatterFunction):
|
class BuiltinDivide(BuiltinFormatterFunction):
|
||||||
name = 'divide'
|
name = 'divide'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
doc = _('divide(x, y) -- returns x / y. Throws an exception if either x or y are not numbers.')
|
doc = _('divide(x, y) -- returns x / y. Throws an exception if either x or y are not numbers.')
|
||||||
@ -160,7 +169,7 @@ class BuiltinDivide(FormatterFunction):
|
|||||||
y = float(y if y else 0)
|
y = float(y if y else 0)
|
||||||
return unicode(x / y)
|
return unicode(x / y)
|
||||||
|
|
||||||
class BuiltinTemplate(FormatterFunction):
|
class BuiltinTemplate(BuiltinFormatterFunction):
|
||||||
name = 'template'
|
name = 'template'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
doc = _('template(x) -- evaluates x as a template. The evaluation is done '
|
doc = _('template(x) -- evaluates x as a template. The evaluation is done '
|
||||||
@ -168,17 +177,17 @@ class BuiltinTemplate(FormatterFunction):
|
|||||||
'the caller and the template evaluation. Because the { and } '
|
'the caller and the template evaluation. Because the { and } '
|
||||||
'characters are special, you must use [[ for the { character and '
|
'characters are special, you must use [[ for the { character and '
|
||||||
']] for the } character; they are converted automatically. '
|
']] for the } character; they are converted automatically. '
|
||||||
'For example, ``template(\'[[title_sort]]\') will evaluate the '
|
'For example, template(\'[[title_sort]]\') will evaluate the '
|
||||||
'template {title_sort} and return its value.')
|
'template {title_sort} and return its value.')
|
||||||
|
|
||||||
def evaluate(self, formatter, kwargs, mi, locals, template):
|
def evaluate(self, formatter, kwargs, mi, locals, template):
|
||||||
template = template.replace('[[', '{').replace(']]', '}')
|
template = template.replace('[[', '{').replace(']]', '}')
|
||||||
return formatter.safe_format(template, kwargs, 'TEMPLATE', mi)
|
return formatter.safe_format(template, kwargs, 'TEMPLATE', mi)
|
||||||
|
|
||||||
class BuiltinEval(FormatterFunction):
|
class BuiltinEval(BuiltinFormatterFunction):
|
||||||
name = 'eval'
|
name = 'eval'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
doc = _('eval(template)`` -- evaluates the template, passing the local '
|
doc = _('eval(template) -- evaluates the template, passing the local '
|
||||||
'variables (those \'assign\'ed to) instead of the book metadata. '
|
'variables (those \'assign\'ed to) instead of the book metadata. '
|
||||||
' This permits using the template processor to construct complex '
|
' This permits using the template processor to construct complex '
|
||||||
'results from local variables.')
|
'results from local variables.')
|
||||||
@ -188,7 +197,7 @@ class BuiltinEval(FormatterFunction):
|
|||||||
template = template.replace('[[', '{').replace(']]', '}')
|
template = template.replace('[[', '{').replace(']]', '}')
|
||||||
return eval_formatter.safe_format(template, locals, 'EVAL', None)
|
return eval_formatter.safe_format(template, locals, 'EVAL', None)
|
||||||
|
|
||||||
class BuiltinAssign(FormatterFunction):
|
class BuiltinAssign(BuiltinFormatterFunction):
|
||||||
name = 'assign'
|
name = 'assign'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
doc = _('assign(id, val) -- assigns val to id, then returns val. '
|
doc = _('assign(id, val) -- assigns val to id, then returns val. '
|
||||||
@ -198,7 +207,7 @@ class BuiltinAssign(FormatterFunction):
|
|||||||
locals[target] = value
|
locals[target] = value
|
||||||
return value
|
return value
|
||||||
|
|
||||||
class BuiltinPrint(FormatterFunction):
|
class BuiltinPrint(BuiltinFormatterFunction):
|
||||||
name = 'print'
|
name = 'print'
|
||||||
arg_count = -1
|
arg_count = -1
|
||||||
doc = _('print(a, b, ...) -- prints the arguments to standard output. '
|
doc = _('print(a, b, ...) -- prints the arguments to standard output. '
|
||||||
@ -209,7 +218,7 @@ class BuiltinPrint(FormatterFunction):
|
|||||||
print args
|
print args
|
||||||
return None
|
return None
|
||||||
|
|
||||||
class BuiltinField(FormatterFunction):
|
class BuiltinField(BuiltinFormatterFunction):
|
||||||
name = 'field'
|
name = 'field'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
doc = _('field(name) -- returns the metadata field named by name')
|
doc = _('field(name) -- returns the metadata field named by name')
|
||||||
@ -217,7 +226,7 @@ class BuiltinField(FormatterFunction):
|
|||||||
def evaluate(self, formatter, kwargs, mi, locals, name):
|
def evaluate(self, formatter, kwargs, mi, locals, name):
|
||||||
return formatter.get_value(name, [], kwargs)
|
return formatter.get_value(name, [], kwargs)
|
||||||
|
|
||||||
class BuiltinSubstr(FormatterFunction):
|
class BuiltinSubstr(BuiltinFormatterFunction):
|
||||||
name = 'substr'
|
name = 'substr'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
doc = _('substr(str, start, end) -- returns the start\'th through the end\'th '
|
doc = _('substr(str, start, end) -- returns the start\'th through the end\'th '
|
||||||
@ -230,7 +239,7 @@ class BuiltinSubstr(FormatterFunction):
|
|||||||
def evaluate(self, formatter, kwargs, mi, locals, str_, start_, end_):
|
def evaluate(self, formatter, kwargs, mi, locals, str_, start_, end_):
|
||||||
return str_[int(start_): len(str_) if int(end_) == 0 else int(end_)]
|
return str_[int(start_): len(str_) if int(end_) == 0 else int(end_)]
|
||||||
|
|
||||||
class BuiltinLookup(FormatterFunction):
|
class BuiltinLookup(BuiltinFormatterFunction):
|
||||||
name = 'lookup'
|
name = 'lookup'
|
||||||
arg_count = -1
|
arg_count = -1
|
||||||
doc = _('lookup(val, pattern, field, pattern, field, ..., else_field) -- '
|
doc = _('lookup(val, pattern, field, pattern, field, ..., else_field) -- '
|
||||||
@ -257,7 +266,7 @@ class BuiltinLookup(FormatterFunction):
|
|||||||
return formatter.vformat('{'+args[i+1].strip() + '}', [], kwargs)
|
return formatter.vformat('{'+args[i+1].strip() + '}', [], kwargs)
|
||||||
i += 2
|
i += 2
|
||||||
|
|
||||||
class BuiltinTest(FormatterFunction):
|
class BuiltinTest(BuiltinFormatterFunction):
|
||||||
name = 'test'
|
name = 'test'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
doc = _('test(val, text if not empty, text if empty) -- return `text if not '
|
doc = _('test(val, text if not empty, text if empty) -- return `text if not '
|
||||||
@ -269,7 +278,7 @@ class BuiltinTest(FormatterFunction):
|
|||||||
else:
|
else:
|
||||||
return value_not_set
|
return value_not_set
|
||||||
|
|
||||||
class BuiltinContains(FormatterFunction):
|
class BuiltinContains(BuiltinFormatterFunction):
|
||||||
name = 'contains'
|
name = 'contains'
|
||||||
arg_count = 4
|
arg_count = 4
|
||||||
doc = _('contains(val, pattern, text if match, text if not match) -- checks '
|
doc = _('contains(val, pattern, text if match, text if not match) -- checks '
|
||||||
@ -284,13 +293,13 @@ class BuiltinContains(FormatterFunction):
|
|||||||
else:
|
else:
|
||||||
return value_if_not
|
return value_if_not
|
||||||
|
|
||||||
class BuiltinSwitch(FormatterFunction):
|
class BuiltinSwitch(BuiltinFormatterFunction):
|
||||||
name = 'switch'
|
name = 'switch'
|
||||||
arg_count = -1
|
arg_count = -1
|
||||||
doc = _('switch(val, pattern, value, pattern, value, ..., else_value) -- '
|
doc = _('switch(val, pattern, value, pattern, value, ..., else_value) -- '
|
||||||
'for each ``pattern, value`` pair, checks if the field matches '
|
'for each `pattern, value` pair, checks if the field matches '
|
||||||
'the regular expression ``pattern`` and if so, returns that '
|
'the regular expression `pattern` and if so, returns that '
|
||||||
'value. If no pattern matches, then else_value is returned. '
|
'`value`. If no pattern matches, then else_value is returned. '
|
||||||
'You can have as many `pattern, value` pairs as you want')
|
'You can have as many `pattern, value` pairs as you want')
|
||||||
|
|
||||||
def evaluate(self, formatter, kwargs, mi, locals, val, *args):
|
def evaluate(self, formatter, kwargs, mi, locals, val, *args):
|
||||||
@ -304,7 +313,7 @@ class BuiltinSwitch(FormatterFunction):
|
|||||||
return args[i+1]
|
return args[i+1]
|
||||||
i += 2
|
i += 2
|
||||||
|
|
||||||
class BuiltinRe(FormatterFunction):
|
class BuiltinRe(BuiltinFormatterFunction):
|
||||||
name = 're'
|
name = 're'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
doc = _('re(val, pattern, replacement) -- return the field after applying '
|
doc = _('re(val, pattern, replacement) -- return the field after applying '
|
||||||
@ -315,10 +324,10 @@ class BuiltinRe(FormatterFunction):
|
|||||||
def evaluate(self, formatter, kwargs, mi, locals, val, pattern, replacement):
|
def evaluate(self, formatter, kwargs, mi, locals, val, pattern, replacement):
|
||||||
return re.sub(pattern, replacement, val)
|
return re.sub(pattern, replacement, val)
|
||||||
|
|
||||||
class BuiltinEvaluate(FormatterFunction):
|
class BuiltinIfempty(BuiltinFormatterFunction):
|
||||||
name = 'evaluate'
|
name = 'ifempty'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
doc = _('evaluate(val, text if empty) -- return val if val is not empty, '
|
doc = _('ifempty(val, text if empty) -- return val if val is not empty, '
|
||||||
'otherwise return `text if empty`')
|
'otherwise return `text if empty`')
|
||||||
|
|
||||||
def evaluate(self, formatter, kwargs, mi, locals, val, value_if_empty):
|
def evaluate(self, formatter, kwargs, mi, locals, val, value_if_empty):
|
||||||
@ -327,7 +336,7 @@ class BuiltinEvaluate(FormatterFunction):
|
|||||||
else:
|
else:
|
||||||
return value_if_empty
|
return value_if_empty
|
||||||
|
|
||||||
class BuiltinShorten(FormatterFunction):
|
class BuiltinShorten(BuiltinFormatterFunction):
|
||||||
name = 'shorten'
|
name = 'shorten'
|
||||||
arg_count = 4
|
arg_count = 4
|
||||||
doc = _('shorten(val, left chars, middle text, right chars) -- Return a '
|
doc = _('shorten(val, left chars, middle text, right chars) -- Return a '
|
||||||
@ -352,7 +361,7 @@ class BuiltinShorten(FormatterFunction):
|
|||||||
else:
|
else:
|
||||||
return val
|
return val
|
||||||
|
|
||||||
class BuiltinCount(FormatterFunction):
|
class BuiltinCount(BuiltinFormatterFunction):
|
||||||
name = 'count'
|
name = 'count'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
doc = _('count(val, separator) -- interprets the value as a list of items '
|
doc = _('count(val, separator) -- interprets the value as a list of items '
|
||||||
@ -363,7 +372,7 @@ class BuiltinCount(FormatterFunction):
|
|||||||
def evaluate(self, formatter, kwargs, mi, locals, val, sep):
|
def evaluate(self, formatter, kwargs, mi, locals, val, sep):
|
||||||
return unicode(len(val.split(sep)))
|
return unicode(len(val.split(sep)))
|
||||||
|
|
||||||
class BuiltinListitem(FormatterFunction):
|
class BuiltinListitem(BuiltinFormatterFunction):
|
||||||
name = 'list_item'
|
name = 'list_item'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
doc = _('list_item(val, index, separator) -- interpret the value as a list of '
|
doc = _('list_item(val, index, separator) -- interpret the value as a list of '
|
||||||
@ -383,7 +392,7 @@ class BuiltinListitem(FormatterFunction):
|
|||||||
except:
|
except:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
class BuiltinUppercase(FormatterFunction):
|
class BuiltinUppercase(BuiltinFormatterFunction):
|
||||||
name = 'uppercase'
|
name = 'uppercase'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
doc = _('uppercase(val) -- return value of the field in upper case')
|
doc = _('uppercase(val) -- return value of the field in upper case')
|
||||||
@ -391,7 +400,7 @@ class BuiltinUppercase(FormatterFunction):
|
|||||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||||
return val.upper()
|
return val.upper()
|
||||||
|
|
||||||
class BuiltinLowercase(FormatterFunction):
|
class BuiltinLowercase(BuiltinFormatterFunction):
|
||||||
name = 'lowercase'
|
name = 'lowercase'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
doc = _('lowercase(val) -- return value of the field in lower case')
|
doc = _('lowercase(val) -- return value of the field in lower case')
|
||||||
@ -399,7 +408,7 @@ class BuiltinLowercase(FormatterFunction):
|
|||||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||||
return val.lower()
|
return val.lower()
|
||||||
|
|
||||||
class BuiltinTitlecase(FormatterFunction):
|
class BuiltinTitlecase(BuiltinFormatterFunction):
|
||||||
name = 'titlecase'
|
name = 'titlecase'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
doc = _('titlecase(val) -- return value of the field in title case')
|
doc = _('titlecase(val) -- return value of the field in title case')
|
||||||
@ -407,7 +416,7 @@ class BuiltinTitlecase(FormatterFunction):
|
|||||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||||
return titlecase(val)
|
return titlecase(val)
|
||||||
|
|
||||||
class BuiltinCapitalize(FormatterFunction):
|
class BuiltinCapitalize(BuiltinFormatterFunction):
|
||||||
name = 'capitalize'
|
name = 'capitalize'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
doc = _('capitalize(val) -- return value of the field capitalized')
|
doc = _('capitalize(val) -- return value of the field capitalized')
|
||||||
@ -423,7 +432,7 @@ builtin_contains = BuiltinContains()
|
|||||||
builtin_count = BuiltinCount()
|
builtin_count = BuiltinCount()
|
||||||
builtin_divide = BuiltinDivide()
|
builtin_divide = BuiltinDivide()
|
||||||
builtin_eval = BuiltinEval()
|
builtin_eval = BuiltinEval()
|
||||||
builtin_evaluate = BuiltinEvaluate()
|
builtin_ifempty = BuiltinIfempty()
|
||||||
builtin_field = BuiltinField()
|
builtin_field = BuiltinField()
|
||||||
builtin_list_item = BuiltinListitem()
|
builtin_list_item = BuiltinListitem()
|
||||||
builtin_lookup = BuiltinLookup()
|
builtin_lookup = BuiltinLookup()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user