mirror of
git://github.com/kovidgoyal/calibre.git
synced 2026-04-22 21:13:43 +02:00
...
This commit is contained in:
commit
ea7947341d
4 changed files with 27 additions and 10 deletions
|
|
@ -38,7 +38,8 @@ def genesis(self, gui):
|
|||
This parameter can be None in some cases, such as when evaluating
|
||||
non-book templates.</li>
|
||||
<li><b>locals:</b> the local variables assigned to by the current
|
||||
template program. Your_arguments must be one or more parameter (number
|
||||
template program.</li>
|
||||
<li><b>Your_arguments</b> must be one or more parameter (number
|
||||
matching the arg count box), or the value *args for a variable number
|
||||
of arguments. These are values passed into the function. One argument
|
||||
is required, and is usually the value of the field being operated upon.
|
||||
|
|
|
|||
|
|
@ -308,6 +308,12 @@ The following program produces the same results as the original recipe, using on
|
|||
|
||||
It would be possible to do the above with no custom columns by putting the program into the template box of the plugboard. However, to do so, all comments must be removed because the plugboard text box does not support multi-line editing. It is debatable whether the gain of not having the custom column is worth the vast increase in difficulty caused by the program being one giant line.
|
||||
|
||||
|
||||
User-defined Template Functions
|
||||
-------------------------------
|
||||
|
||||
You can add your own functions to the template processor. Such functions are written in python, and can be used in any of the three template programming modes. The functions are added by going to Preferences -> Advanced -> Template Functions. Instructions are shown in that dialog.
|
||||
|
||||
Special notes for save/send templates
|
||||
-------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ def __init__(self, val, prog, parent):
|
|||
if prog[1] != '':
|
||||
self.error(_('failed to scan program. Invalid input {0}').format(prog[1]))
|
||||
self.parent = parent
|
||||
self.variables = {'$':val}
|
||||
self.parent.locals = {'$':val}
|
||||
|
||||
def error(self, message):
|
||||
m = 'Formatter: ' + message + _(' near ')
|
||||
|
|
@ -88,18 +88,20 @@ def statement(self):
|
|||
|
||||
def expr(self):
|
||||
if self.token_is_id():
|
||||
funcs = formatter_functions.get_functions()
|
||||
# We have an identifier. Determine if it is a function
|
||||
id = self.token()
|
||||
if not self.token_op_is_a('('):
|
||||
if self.token_op_is_a('='):
|
||||
# classic assignment statement
|
||||
self.consume()
|
||||
return self._assign(id, self.expr())
|
||||
return self.variables.get(id, _('unknown id ') + id)
|
||||
cls = funcs['assign']
|
||||
return cls.eval(self.parent, self.parent.kwargs,
|
||||
self.parent.book, self.parent.locals, id, self.expr())
|
||||
return self.parent.locals.get(id, _('unknown id ') + id)
|
||||
# We have a function.
|
||||
# Check if it is a known one. We do this here so error reporting is
|
||||
# better, as it can identify the tokens near the problem.
|
||||
funcs = formatter_functions.get_functions()
|
||||
|
||||
if id not in funcs:
|
||||
self.error(_('unknown function {0}').format(id))
|
||||
|
|
@ -129,7 +131,7 @@ def expr(self):
|
|||
if cls.arg_count != -1 and len(args) != cls.arg_count:
|
||||
self.error('incorrect number of arguments for function {}'.format(id))
|
||||
return cls.eval(self.parent, self.parent.kwargs,
|
||||
self.parent.book, locals, *args)
|
||||
self.parent.book, self.parent.locals, *args)
|
||||
else:
|
||||
f = self.parent.functions[id]
|
||||
if f[0] != -1 and len(args) != f[0]+1:
|
||||
|
|
@ -159,6 +161,7 @@ def __init__(self):
|
|||
self.book = None
|
||||
self.kwargs = None
|
||||
self.program_cache = {}
|
||||
self.locals = {}
|
||||
|
||||
def _do_format(self, val, fmt):
|
||||
if not fmt or not val:
|
||||
|
|
@ -286,9 +289,9 @@ def format_field(self, val, fmt):
|
|||
print args
|
||||
raise ValueError('Incorrect number of arguments for function '+ fmt[0:p])
|
||||
if func.arg_count == 1:
|
||||
val = func.eval(self, self.kwargs, self.book, locals, val).strip()
|
||||
val = func.eval(self, self.kwargs, self.book, self.locals, val).strip()
|
||||
else:
|
||||
val = func.eval(self, self.kwargs, self.book, locals,
|
||||
val = func.eval(self, self.kwargs, self.book, self.locals,
|
||||
val, *args).strip()
|
||||
if val:
|
||||
val = self._do_format(val, dispfmt)
|
||||
|
|
@ -309,6 +312,7 @@ def safe_format(self, fmt, kwargs, error_value, book):
|
|||
self.kwargs = kwargs
|
||||
self.book = book
|
||||
self.composite_values = {}
|
||||
self.locals = {}
|
||||
try:
|
||||
ans = self.vformat(fmt, [], kwargs).strip()
|
||||
except Exception, e:
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ def eval(self, formatter, kwargs, mi, locals, *args):
|
|||
if isinstance(ret, list):
|
||||
return ','.join(list)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return _('Function threw exception' + traceback.format_exc())
|
||||
|
||||
class BuiltinStrcmp(FormatterFunction):
|
||||
|
|
@ -327,7 +328,7 @@ def evaluate(self, formatter, kwargs, mi, locals, val, value_if_empty):
|
|||
return value_if_empty
|
||||
|
||||
class BuiltinShorten(FormatterFunction):
|
||||
name = 'shorten '
|
||||
name = 'shorten'
|
||||
arg_count = 4
|
||||
doc = _('shorten(val, left chars, middle text, right chars) -- Return a '
|
||||
'shortened version of the field, consisting of `left chars` '
|
||||
|
|
@ -448,8 +449,13 @@ def __init__(self, name, doc, arg_count, program_text):
|
|||
self.arg_count = arg_count
|
||||
self.program_text = program_text
|
||||
|
||||
tabs = re.compile(r'^\t*')
|
||||
def compile_user_function(name, doc, arg_count, eval_func):
|
||||
func = '\t' + eval_func.replace('\n', '\n\t')
|
||||
def replace_func(mo):
|
||||
return mo.group().replace('\t', ' ')
|
||||
|
||||
func = ' ' + '\n '.join([tabs.sub(replace_func, line )
|
||||
for line in eval_func.splitlines()])
|
||||
prog = '''
|
||||
from calibre.utils.formatter_functions import FormatterUserFunction
|
||||
class UserFunction(FormatterUserFunction):
|
||||
|
|
|
|||
Loading…
Reference in a new issue