mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
New formatter function: list_re. Also fix several unreported problems with reconstructed lists potentially using the wrong separator. Finally, correct some problems in function grouping in the manual.
This commit is contained in:
parent
71d3ede2aa
commit
f55fb94a42
@ -268,6 +268,7 @@ The following functions are available in addition to those described in single-f
|
|||||||
* ``list_difference(list1, list2, separator)`` -- return a list made by removing from `list1` any item found in `list2`, using a case-insensitive compare. The items in `list1` and `list2` are separated by separator, as are the items in the returned list.
|
* ``list_difference(list1, list2, separator)`` -- return a list made by removing from `list1` any item found in `list2`, using a case-insensitive compare. The items in `list1` and `list2` are separated by separator, as are the items in the returned list.
|
||||||
* ``list_equals(list1, sep1, list2, sep2, yes_val, no_val)`` -- return `yes_val` if `list1` and `list2` contain the same items, otherwise return `no_val`. The items are determined by splitting each list using the appropriate separator character (`sep1` or `sep2`). The order of items in the lists is not relevant. The compare is case insensitive.
|
* ``list_equals(list1, sep1, list2, sep2, yes_val, no_val)`` -- return `yes_val` if `list1` and `list2` contain the same items, otherwise return `no_val`. The items are determined by splitting each list using the appropriate separator character (`sep1` or `sep2`). The order of items in the lists is not relevant. The compare is case insensitive.
|
||||||
* ``list_intersection(list1, list2, separator)`` -- return a list made by removing from `list1` any item not found in `list2`, using a case-insensitive compare. The items in `list1` and `list2` are separated by separator, as are the items in the returned list.
|
* ``list_intersection(list1, list2, separator)`` -- return a list made by removing from `list1` any item not found in `list2`, using a case-insensitive compare. The items in `list1` and `list2` are separated by separator, as are the items in the returned list.
|
||||||
|
* ``list_re(src_list, separator, search_re, opt_replace)`` -- Construct a list by first separating `src_list` into items using the `separator` character. For each item in the list, check if it matches `search_re`. If it does, then add it to the list to be returned. If `opt_replace` is not the empty string, then apply the replacement before adding the item to the returned list.
|
||||||
* ``list_sort(list, direction, separator)`` -- return list sorted using a case-insensitive sort. If `direction` is zero, the list is sorted ascending, otherwise descending. The list items are separated by separator, as are the items in the returned list.
|
* ``list_sort(list, direction, separator)`` -- return list sorted using a case-insensitive sort. If `direction` is zero, the list is sorted ascending, otherwise descending. The list items are separated by separator, as are the items in the returned list.
|
||||||
* ``list_union(list1, list2, separator)`` -- return a list made by merging the items in list1 and list2, removing duplicate items using a case-insensitive compare. If items differ in case, the one in list1 is used. The items in list1 and list2 are separated by separator, as are the items in the returned list.
|
* ``list_union(list1, list2, separator)`` -- return a list made by merging the items in list1 and list2, removing duplicate items using a case-insensitive compare. If items differ in case, the one in list1 is used. The items in list1 and list2 are separated by separator, as are the items in the returned list.
|
||||||
* ``multiply(x, y)`` -- returns x * y. Throws an exception if either x or y are not numbers.
|
* ``multiply(x, y)`` -- returns x * y. Throws an exception if either x or y are not numbers.
|
||||||
|
@ -133,7 +133,7 @@ class BuiltinCmp(BuiltinFormatterFunction):
|
|||||||
class BuiltinStrcat(BuiltinFormatterFunction):
|
class BuiltinStrcat(BuiltinFormatterFunction):
|
||||||
name = 'strcat'
|
name = 'strcat'
|
||||||
arg_count = -1
|
arg_count = -1
|
||||||
category = 'String Manipulation'
|
category = 'String manipulation'
|
||||||
__doc__ = doc = _('strcat(a, b, ...) -- can take any number of arguments. Returns a '
|
__doc__ = doc = _('strcat(a, b, ...) -- can take any number of arguments. Returns a '
|
||||||
'string formed by concatenating all the arguments')
|
'string formed by concatenating all the arguments')
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ class BuiltinStrcat(BuiltinFormatterFunction):
|
|||||||
class BuiltinStrlen(BuiltinFormatterFunction):
|
class BuiltinStrlen(BuiltinFormatterFunction):
|
||||||
name = 'strlen'
|
name = 'strlen'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
category = 'String Manipulation'
|
category = 'String manipulation'
|
||||||
__doc__ = doc = _('strlen(a) -- Returns the length of the string passed as '
|
__doc__ = doc = _('strlen(a) -- Returns the length of the string passed as '
|
||||||
'the argument')
|
'the argument')
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ class BuiltinRawField(BuiltinFormatterFunction):
|
|||||||
class BuiltinSubstr(BuiltinFormatterFunction):
|
class BuiltinSubstr(BuiltinFormatterFunction):
|
||||||
name = 'substr'
|
name = 'substr'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
category = 'String Manipulation'
|
category = 'String manipulation'
|
||||||
__doc__ = doc = _('substr(str, start, end) -- returns the start\'th through the end\'th '
|
__doc__ = doc = _('substr(str, start, end) -- returns the start\'th through the end\'th '
|
||||||
'characters of str. The first character in str is the zero\'th '
|
'characters of str. The first character in str is the zero\'th '
|
||||||
'character. If end is negative, then it indicates that many '
|
'character. If end is negative, then it indicates that many '
|
||||||
@ -369,7 +369,7 @@ class BuiltinSwitch(BuiltinFormatterFunction):
|
|||||||
class BuiltinStrcatMax(BuiltinFormatterFunction):
|
class BuiltinStrcatMax(BuiltinFormatterFunction):
|
||||||
name = 'strcat_max'
|
name = 'strcat_max'
|
||||||
arg_count = -1
|
arg_count = -1
|
||||||
category = 'String Manipulation'
|
category = 'String manipulation'
|
||||||
__doc__ = doc = _('strcat_max(max, string1, prefix2, string2, ...) -- '
|
__doc__ = doc = _('strcat_max(max, string1, prefix2, string2, ...) -- '
|
||||||
'Returns a string formed by concatenating the arguments. The '
|
'Returns a string formed by concatenating the arguments. The '
|
||||||
'returned value is initialized to string1. `Prefix, string` '
|
'returned value is initialized to string1. `Prefix, string` '
|
||||||
@ -403,7 +403,7 @@ class BuiltinStrcatMax(BuiltinFormatterFunction):
|
|||||||
class BuiltinInList(BuiltinFormatterFunction):
|
class BuiltinInList(BuiltinFormatterFunction):
|
||||||
name = 'in_list'
|
name = 'in_list'
|
||||||
arg_count = 5
|
arg_count = 5
|
||||||
category = 'List Lookup'
|
category = 'List lookup'
|
||||||
__doc__ = doc = _('in_list(val, separator, pattern, found_val, not_found_val) -- '
|
__doc__ = doc = _('in_list(val, separator, pattern, found_val, not_found_val) -- '
|
||||||
'treat val as a list of items separated by separator, '
|
'treat val as a list of items separated by separator, '
|
||||||
'comparing the pattern against each value in the list. If the '
|
'comparing the pattern against each value in the list. If the '
|
||||||
@ -468,7 +468,7 @@ class BuiltinIdentifierInList(BuiltinFormatterFunction):
|
|||||||
class BuiltinRe(BuiltinFormatterFunction):
|
class BuiltinRe(BuiltinFormatterFunction):
|
||||||
name = 're'
|
name = 're'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
category = 'String Manipulation'
|
category = 'String manipulation'
|
||||||
__doc__ = doc = _('re(val, pattern, replacement) -- return the field after applying '
|
__doc__ = doc = _('re(val, pattern, replacement) -- return the field after applying '
|
||||||
'the regular expression. All instances of `pattern` are replaced '
|
'the regular expression. All instances of `pattern` are replaced '
|
||||||
'with `replacement`. As in all of calibre, these are '
|
'with `replacement`. As in all of calibre, these are '
|
||||||
@ -480,7 +480,7 @@ class BuiltinRe(BuiltinFormatterFunction):
|
|||||||
class BuiltinSwapAroundComma(BuiltinFormatterFunction):
|
class BuiltinSwapAroundComma(BuiltinFormatterFunction):
|
||||||
name = 'swap_around_comma'
|
name = 'swap_around_comma'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
category = 'String Manipulation'
|
category = 'String manipulation'
|
||||||
__doc__ = doc = _('swap_around_comma(val) -- given a value of the form '
|
__doc__ = doc = _('swap_around_comma(val) -- given a value of the form '
|
||||||
'"B, A", return "A B". This is most useful for converting names '
|
'"B, A", return "A B". This is most useful for converting names '
|
||||||
'in LN, FN format to FN LN. If there is no comma, the function '
|
'in LN, FN format to FN LN. If there is no comma, the function '
|
||||||
@ -505,7 +505,7 @@ class BuiltinIfempty(BuiltinFormatterFunction):
|
|||||||
class BuiltinShorten(BuiltinFormatterFunction):
|
class BuiltinShorten(BuiltinFormatterFunction):
|
||||||
name = 'shorten'
|
name = 'shorten'
|
||||||
arg_count = 4
|
arg_count = 4
|
||||||
category = 'String Manipulation'
|
category = 'String manipulation'
|
||||||
__doc__ = doc = _('shorten(val, left chars, middle text, right chars) -- Return a '
|
__doc__ = doc = _('shorten(val, left chars, middle text, right chars) -- Return a '
|
||||||
'shortened version of the field, consisting of `left chars` '
|
'shortened version of the field, consisting of `left chars` '
|
||||||
'characters from the beginning of the field, followed by '
|
'characters from the beginning of the field, followed by '
|
||||||
@ -531,7 +531,7 @@ class BuiltinShorten(BuiltinFormatterFunction):
|
|||||||
class BuiltinCount(BuiltinFormatterFunction):
|
class BuiltinCount(BuiltinFormatterFunction):
|
||||||
name = 'count'
|
name = 'count'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
category = 'List Manipulation'
|
category = 'List manipulation'
|
||||||
__doc__ = doc = _('count(val, separator) -- interprets the value as a list of items '
|
__doc__ = doc = _('count(val, separator) -- interprets the value as a list of items '
|
||||||
'separated by `separator`, returning the number of items in the '
|
'separated by `separator`, returning the number of items in the '
|
||||||
'list. Most lists use a comma as the separator, but authors '
|
'list. Most lists use a comma as the separator, but authors '
|
||||||
@ -543,7 +543,7 @@ class BuiltinCount(BuiltinFormatterFunction):
|
|||||||
class BuiltinListitem(BuiltinFormatterFunction):
|
class BuiltinListitem(BuiltinFormatterFunction):
|
||||||
name = 'list_item'
|
name = 'list_item'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
category = 'List Lookup'
|
category = 'List lookup'
|
||||||
__doc__ = doc = _('list_item(val, index, separator) -- interpret the value as a list of '
|
__doc__ = doc = _('list_item(val, index, separator) -- interpret the value as a list of '
|
||||||
'items separated by `separator`, returning the `index`th item. '
|
'items separated by `separator`, returning the `index`th item. '
|
||||||
'The first item is number zero. The last item can be returned '
|
'The first item is number zero. The last item can be returned '
|
||||||
@ -564,7 +564,7 @@ class BuiltinListitem(BuiltinFormatterFunction):
|
|||||||
class BuiltinSelect(BuiltinFormatterFunction):
|
class BuiltinSelect(BuiltinFormatterFunction):
|
||||||
name = 'select'
|
name = 'select'
|
||||||
arg_count = 2
|
arg_count = 2
|
||||||
category = 'List Lookup'
|
category = 'List lookup'
|
||||||
__doc__ = doc = _('select(val, key) -- interpret the value as a comma-separated list '
|
__doc__ = doc = _('select(val, key) -- interpret the value as a comma-separated list '
|
||||||
'of items, with the items being "id:value". Find the pair with the '
|
'of items, with the items being "id:value". Find the pair with the '
|
||||||
'id equal to key, and return the corresponding value.'
|
'id equal to key, and return the corresponding value.'
|
||||||
@ -656,7 +656,7 @@ class BuiltinFormatNumber(BuiltinFormatterFunction):
|
|||||||
class BuiltinSublist(BuiltinFormatterFunction):
|
class BuiltinSublist(BuiltinFormatterFunction):
|
||||||
name = 'sublist'
|
name = 'sublist'
|
||||||
arg_count = 4
|
arg_count = 4
|
||||||
category = 'List Manipulation'
|
category = 'List manipulation'
|
||||||
__doc__ = doc = _('sublist(val, start_index, end_index, separator) -- interpret the '
|
__doc__ = doc = _('sublist(val, start_index, end_index, separator) -- interpret the '
|
||||||
'value as a list of items separated by `separator`, returning a '
|
'value as a list of items separated by `separator`, returning a '
|
||||||
'new list made from the `start_index` to the `end_index` item. '
|
'new list made from the `start_index` to the `end_index` item. '
|
||||||
@ -677,6 +677,9 @@ class BuiltinSublist(BuiltinFormatterFunction):
|
|||||||
ei = int(end_index)
|
ei = int(end_index)
|
||||||
# allow empty list items so counts are what the user expects
|
# allow empty list items so counts are what the user expects
|
||||||
val = [v.strip() for v in val.split(sep)]
|
val = [v.strip() for v in val.split(sep)]
|
||||||
|
|
||||||
|
if sep == ',':
|
||||||
|
sep = ', '
|
||||||
try:
|
try:
|
||||||
if ei == 0:
|
if ei == 0:
|
||||||
return sep.join(val[si:])
|
return sep.join(val[si:])
|
||||||
@ -688,7 +691,7 @@ class BuiltinSublist(BuiltinFormatterFunction):
|
|||||||
class BuiltinSubitems(BuiltinFormatterFunction):
|
class BuiltinSubitems(BuiltinFormatterFunction):
|
||||||
name = 'subitems'
|
name = 'subitems'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
category = 'List Manipulation'
|
category = 'List manipulation'
|
||||||
__doc__ = doc = _('subitems(val, start_index, end_index) -- This function is used to '
|
__doc__ = doc = _('subitems(val, start_index, end_index) -- This function is used to '
|
||||||
'break apart lists of items such as genres. It interprets the value '
|
'break apart lists of items such as genres. It interprets the value '
|
||||||
'as a comma-separated list of items, where each item is a period-'
|
'as a comma-separated list of items, where each item is a period-'
|
||||||
@ -892,7 +895,7 @@ class BuiltinNot(BuiltinFormatterFunction):
|
|||||||
class BuiltinListUnion(BuiltinFormatterFunction):
|
class BuiltinListUnion(BuiltinFormatterFunction):
|
||||||
name = 'list_union'
|
name = 'list_union'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
category = 'List Manipulation'
|
category = 'List manipulation'
|
||||||
__doc__ = doc = _('list_union(list1, list2, separator) -- '
|
__doc__ = doc = _('list_union(list1, list2, separator) -- '
|
||||||
'return a list made by merging the items in list1 and list2, '
|
'return a list made by merging the items in list1 and list2, '
|
||||||
'removing duplicate items using a case-insensitive compare. If '
|
'removing duplicate items using a case-insensitive compare. If '
|
||||||
@ -912,12 +915,14 @@ class BuiltinListUnion(BuiltinFormatterFunction):
|
|||||||
for i in l2:
|
for i in l2:
|
||||||
if icu_lower(i) not in lcl1:
|
if icu_lower(i) not in lcl1:
|
||||||
res.append(i)
|
res.append(i)
|
||||||
|
if separator == ',':
|
||||||
return ', '.join(res)
|
return ', '.join(res)
|
||||||
|
return separator.join(res)
|
||||||
|
|
||||||
class BuiltinListDifference(BuiltinFormatterFunction):
|
class BuiltinListDifference(BuiltinFormatterFunction):
|
||||||
name = 'list_difference'
|
name = 'list_difference'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
category = 'List Manipulation'
|
category = 'List manipulation'
|
||||||
__doc__ = doc = _('list_difference(list1, list2, separator) -- '
|
__doc__ = doc = _('list_difference(list1, list2, separator) -- '
|
||||||
'return a list made by removing from list1 any item found in list2, '
|
'return a list made by removing from list1 any item found in list2, '
|
||||||
'using a case-insensitive compare. The items in list1 and list2 '
|
'using a case-insensitive compare. The items in list1 and list2 '
|
||||||
@ -931,12 +936,14 @@ class BuiltinListDifference(BuiltinFormatterFunction):
|
|||||||
for i in l1:
|
for i in l1:
|
||||||
if icu_lower(i) not in l2:
|
if icu_lower(i) not in l2:
|
||||||
res.append(i)
|
res.append(i)
|
||||||
|
if separator == ',':
|
||||||
return ', '.join(res)
|
return ', '.join(res)
|
||||||
|
return separator.join(res)
|
||||||
|
|
||||||
class BuiltinListIntersection(BuiltinFormatterFunction):
|
class BuiltinListIntersection(BuiltinFormatterFunction):
|
||||||
name = 'list_intersection'
|
name = 'list_intersection'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
category = 'List Manipulation'
|
category = 'List manipulation'
|
||||||
__doc__ = doc = _('list_intersection(list1, list2, separator) -- '
|
__doc__ = doc = _('list_intersection(list1, list2, separator) -- '
|
||||||
'return a list made by removing from list1 any item not found in list2, '
|
'return a list made by removing from list1 any item not found in list2, '
|
||||||
'using a case-insensitive compare. The items in list1 and list2 '
|
'using a case-insensitive compare. The items in list1 and list2 '
|
||||||
@ -950,12 +957,14 @@ class BuiltinListIntersection(BuiltinFormatterFunction):
|
|||||||
for i in l1:
|
for i in l1:
|
||||||
if icu_lower(i) in l2:
|
if icu_lower(i) in l2:
|
||||||
res.append(i)
|
res.append(i)
|
||||||
|
if separator == ',':
|
||||||
return ', '.join(res)
|
return ', '.join(res)
|
||||||
|
return separator.join(res)
|
||||||
|
|
||||||
class BuiltinListSort(BuiltinFormatterFunction):
|
class BuiltinListSort(BuiltinFormatterFunction):
|
||||||
name = 'list_sort'
|
name = 'list_sort'
|
||||||
arg_count = 3
|
arg_count = 3
|
||||||
category = 'List Manipulation'
|
category = 'List manipulation'
|
||||||
__doc__ = doc = _('list_sort(list, direction, separator) -- '
|
__doc__ = doc = _('list_sort(list, direction, separator) -- '
|
||||||
'return list sorted using a case-insensitive sort. If direction is '
|
'return list sorted using a case-insensitive sort. If direction is '
|
||||||
'zero, the list is sorted ascending, otherwise descending. The list items '
|
'zero, the list is sorted ascending, otherwise descending. The list items '
|
||||||
@ -963,12 +972,14 @@ class BuiltinListSort(BuiltinFormatterFunction):
|
|||||||
|
|
||||||
def evaluate(self, formatter, kwargs, mi, locals, list1, direction, separator):
|
def evaluate(self, formatter, kwargs, mi, locals, list1, direction, separator):
|
||||||
res = [l.strip() for l in list1.split(separator) if l.strip()]
|
res = [l.strip() for l in list1.split(separator) if l.strip()]
|
||||||
|
if separator == ',':
|
||||||
return ', '.join(sorted(res, key=sort_key, reverse=direction != "0"))
|
return ', '.join(sorted(res, key=sort_key, reverse=direction != "0"))
|
||||||
|
return separator.join(sorted(res, key=sort_key, reverse=direction != "0"))
|
||||||
|
|
||||||
class BuiltinListEquals(BuiltinFormatterFunction):
|
class BuiltinListEquals(BuiltinFormatterFunction):
|
||||||
name = 'list_equals'
|
name = 'list_equals'
|
||||||
arg_count = 6
|
arg_count = 6
|
||||||
category = 'List Manipulation'
|
category = 'List manipulation'
|
||||||
__doc__ = doc = _('list_equals(list1, sep1, list2, sep2, yes_val, no_val) -- '
|
__doc__ = doc = _('list_equals(list1, sep1, list2, sep2, yes_val, no_val) -- '
|
||||||
'return yes_val if list1 and list2 contain the same items, '
|
'return yes_val if list1 and list2 contain the same items, '
|
||||||
'otherwise return no_val. The items are determined by splitting '
|
'otherwise return no_val. The items are determined by splitting '
|
||||||
@ -983,6 +994,29 @@ class BuiltinListEquals(BuiltinFormatterFunction):
|
|||||||
return yes_val
|
return yes_val
|
||||||
return no_val
|
return no_val
|
||||||
|
|
||||||
|
class BuiltinListRe(BuiltinFormatterFunction):
|
||||||
|
name = 'list_re'
|
||||||
|
arg_count = 4
|
||||||
|
category = 'List manipulation'
|
||||||
|
__doc__ = doc = _('list_re(src_list, separator, search_re, opt_replace) -- '
|
||||||
|
'Construct a list by first separating src_list into items using '
|
||||||
|
'the separator character. For each item in the list, check if it '
|
||||||
|
'matches search_re. If it does, then add it to the list to be '
|
||||||
|
'returned. If opt_replace is not the empty string, then apply the '
|
||||||
|
'replacement before adding the item to the returned list.')
|
||||||
|
|
||||||
|
def evaluate(self, formatter, kwargs, mi, locals, src_list, separator, search_re, opt_replace):
|
||||||
|
l = [l.strip() for l in src_list.split(separator) if l.strip()]
|
||||||
|
res = []
|
||||||
|
for item in l:
|
||||||
|
if re.search(search_re, item, flags=re.I) is not None:
|
||||||
|
if opt_replace:
|
||||||
|
item = re.sub(search_re, opt_replace, item)
|
||||||
|
res.append(item)
|
||||||
|
if separator == ',':
|
||||||
|
return ', '.join(res)
|
||||||
|
return separator.join(res)
|
||||||
|
|
||||||
class BuiltinToday(BuiltinFormatterFunction):
|
class BuiltinToday(BuiltinFormatterFunction):
|
||||||
name = 'today'
|
name = 'today'
|
||||||
arg_count = 0
|
arg_count = 0
|
||||||
@ -1064,8 +1098,8 @@ _formatter_builtins = [
|
|||||||
BuiltinHasCover(), BuiltinHumanReadable(), BuiltinIdentifierInList(),
|
BuiltinHasCover(), BuiltinHumanReadable(), BuiltinIdentifierInList(),
|
||||||
BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(),
|
BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(),
|
||||||
BuiltinInList(), BuiltinListDifference(), BuiltinListEquals(),
|
BuiltinInList(), BuiltinListDifference(), BuiltinListEquals(),
|
||||||
BuiltinListIntersection(), BuiltinListitem(), BuiltinListSort(),
|
BuiltinListIntersection(), BuiltinListitem(), BuiltinListRe(),
|
||||||
BuiltinListUnion(), BuiltinLookup(),
|
BuiltinListSort(), BuiltinListUnion(), BuiltinLookup(),
|
||||||
BuiltinLowercase(), BuiltinMultiply(), BuiltinNot(),
|
BuiltinLowercase(), BuiltinMultiply(), BuiltinNot(),
|
||||||
BuiltinOndevice(), BuiltinOr(), BuiltinPrint(), BuiltinRawField(),
|
BuiltinOndevice(), BuiltinOr(), BuiltinPrint(), BuiltinRawField(),
|
||||||
BuiltinRe(), BuiltinSelect(), BuiltinShorten(), BuiltinStrcat(),
|
BuiltinRe(), BuiltinSelect(), BuiltinShorten(), BuiltinStrcat(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user