mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-10-01 16:55:40 -04:00
#1762 add filter() to list properties
This commit is contained in:
1 parent
a21bb8174d
commit
f194032139
4 files changed
+115
-40
No files matched your search
@@ -11,13 +11,31 @@ internal partial interface IListFormat<TList> where TList : IListFormat<TList>
|
||||
{
|
||||
static IEnumerable<T> FilteredList<T>(string formatString, IEnumerable<T> items, CultureInfo? culture) where T : IFormattable
|
||||
{
|
||||
return Max(formatString, Slice(formatString, Unique(formatString, items, culture)));
|
||||
return Max(formatString, Slice(formatString, Unique(formatString, Filter(formatString, items, culture), culture)));
|
||||
|
||||
static StringComparer GetStringComparer(CultureInfo? culture)
|
||||
{
|
||||
return StringComparer.Create(culture ?? CultureInfo.CurrentCulture, ignoreCase: true);
|
||||
}
|
||||
|
||||
static IEnumerable<T> Filter(string formatString, IEnumerable<T> items, CultureInfo? culture)
|
||||
{
|
||||
if (!FilterRegex().TryMatch(formatString, out var filterMatch))
|
||||
return items;
|
||||
|
||||
// read the format to apply on each item
|
||||
var format = filterMatch.ResolveValue("format");
|
||||
// use the operator to get a predicate function that compares the formatted item to the value specified in the filter
|
||||
var predicate = CompareCondition.GetPredicate(filterMatch.Value, filterMatch.ResolveValue("op"));
|
||||
// the value to compare the formatted item to. Might be a number or a quoted string.
|
||||
CommonFormatters.TryGetLiteral(filterMatch.ResolveValue("value"), out var value);
|
||||
|
||||
// return only the items that match the predicate
|
||||
return items.Where(FilterPredicate);
|
||||
|
||||
bool FilterPredicate(T n) => predicate(n.ToString(format, culture), value, culture);
|
||||
}
|
||||
|
||||
static IEnumerable<T> Unique(string formatString, IEnumerable<T> items, CultureInfo? culture)
|
||||
{
|
||||
return UniqueRegex().TryMatch(formatString, out var uniqueMatch)
|
||||
@@ -120,11 +138,36 @@ internal partial interface IListFormat<TList> where TList : IListFormat<TList>
|
||||
[GeneratedRegex("""[Ss]eparator\((?<separator>(?:\\.|'[^']*'|"[^"]*"|[^\\'"])*?)\)""")]
|
||||
private static partial Regex SeparatorRegex();
|
||||
|
||||
/// <summary> Count will substitute all list members with a single number equal to there count </summary>
|
||||
/// <summary> Count will substitute all list members with a single number equal to their count </summary>
|
||||
[GeneratedRegex("""[Cc]ount\((?<format>(?:\\.|'[^']*'|"[^"]*"|[^\\'"])*?)\)""")]
|
||||
private static partial Regex CountRegex();
|
||||
|
||||
/// <summary> Unique will shrink the list to unique members after applying format to them </summary>
|
||||
[GeneratedRegex("""[Uu]nique\((?<format>(?:\\.|'[^']*'|"[^"]*"|[^\\'"])*?)\)""")]
|
||||
private static partial Regex UniqueRegex();
|
||||
}
|
||||
|
||||
/// <summary> The filter will reduce the list, keeping only the items that match the specified criteria. </summary>
|
||||
[GeneratedRegex("""
|
||||
(?x) # option x: ignore all unescaped whitespace in pattern and allow comments starting with #
|
||||
[Ff]ilter # name of the command 'filter' or 'Filter'
|
||||
\( # details are enclosed in brackets
|
||||
(?<format>(?: # the first part captured as <format> specifies how to format items before comparison
|
||||
\\. # - '\' escapes always the next character.
|
||||
| '[^']*' # - allow 'string' to be included in the format, with '' being an escaped ' character
|
||||
| "[^"]*" # - allow "string" to be included in the format, with "" being an escaped " character
|
||||
| [^\\'"] # - match any other character. This will not catch the operator at first. Because ...
|
||||
) *? ) # With *? the pattern above tries not to consume the operator.
|
||||
\s* # Separate the following operator with whitespace
|
||||
(?<op> # capture operator in <op>
|
||||
[\#!≡=≠~<>≤≥&∉∌∈∌⋂⊆⊇⊂⊃-]+ # allow a wide range of operators, all non alphanumeric so that no operator is confused as value
|
||||
| :[a-z_]+: # allow :named: operators for readability, e.g. :contains:
|
||||
) \s* # ignore space between operator and second property
|
||||
(?<value> # the second operand is captured as <value> and is a quoted string encapsulated in either single or double quotes
|
||||
'(?:[^']|'')*' # - allow 'string' to be included in the format, with '' being an escaped ' character
|
||||
| "(?:[^"]|"")*" # - allow "string" to be included in the format, with "" being an escaped " character
|
||||
| \d+ # - allow a number
|
||||
) #
|
||||
\s* \) # end the filter details with optional whitespace and a closing bracket
|
||||
""")]
|
||||
private static partial Regex FilterRegex();
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using AssertionHelper;
|
||||
using FileManager.NamingTemplate;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
@@ -322,10 +321,33 @@ public class CommonFormattersTests
|
||||
Assert.AreEqual(expected, unescaped);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow(null, false, null, "null")]
|
||||
[DataRow("", false, null, "emptystring")]
|
||||
[DataRow("42", true, 42, "number")]
|
||||
[DataRow("\"only\" at start", false, null, "partly quoted")]
|
||||
[DataRow("\"mismatched'", false, null, "wrong pair of quotes")]
|
||||
[DataRow("\"simple string\"", true, "simple string", "simple quoted with double quotes")]
|
||||
[DataRow("'simple string'", true, "simple string", "simple quoted with single quotes")]
|
||||
[DataRow("\"string with \"\"escaped\"\" quotes\"", true, "string with \"escaped\" quotes", "quoted with embedded doubled quotes")]
|
||||
[DataRow("'string with ''escaped'' quotes'", true, "string with 'escaped' quotes", "quoted with embedded doubled single quotes")]
|
||||
[DataRow("\"string with 'single' quotes\"", true, "string with 'single' quotes", "quoted with embedded other quote type")]
|
||||
[DataRow("\"string with ''doubled single'' and \\\"escaped double\\\" quotes\"", true, "string with ''doubled single'' and \\\"escaped double\\\" quotes", "quoted with embedded doubling")]
|
||||
[DataRow(" \"string with whitespace\" ", true, "string with whitespace", "quoted with whitespace")]
|
||||
[DataRow("\"\"", true, "", "empty quoted string")]
|
||||
public void TryQuotedString_Various(string? value, bool expectedSuccess, object? expectedValue, string testDescription)
|
||||
{
|
||||
// WHEN
|
||||
var result = CommonFormatters.TryGetLiteral(value, out var unQuotedValue);
|
||||
|
||||
// THEN
|
||||
Assert.AreEqual(expectedSuccess, result, $"Failed for: {testDescription}");
|
||||
Assert.AreEqual(expectedValue, unQuotedValue, $"Failed for: {testDescription}");
|
||||
}
|
||||
|
||||
private class TestClass
|
||||
{
|
||||
public string? Author { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public string? Author { get; init; }
|
||||
public string? Title { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -400,6 +400,12 @@ namespace TemplatesTests
|
||||
[DataRow("<author[sort(LF) slice(4..5)]>", "Charles E. Gannon, Emma Gannon")]
|
||||
[DataRow("<author[sort(Lf) slice(4..5)]>", "Emma Gannon, Charles E. Gannon")]
|
||||
[DataRow("<author[unique({L:1}) format({L})]>", "Browne, Gannon, Fetherolf, Montgomery, Van Doren")]
|
||||
[DataRow("<author[filter({L:1} = 'B') count()]>", "2")]
|
||||
[DataRow("<author[filter({F:1}~{L}~'J~B') format({L})]>", "Browne, Bon Jovi")] // match correct position of operator
|
||||
[DataRow(@"<author[filter({F:1}\'{L:1} = 'J''B') format({L})]>", "Browne, Bon Jovi")] // allow quoted quotes
|
||||
[DataRow("<author[filter(<'99') count()]>", "")] // strings with numerical operators are substituted by their length
|
||||
[DataRow("<author[filter(<26) count()]>", "6")]
|
||||
[DataRow("<author[filter({L:1} != 'B') format({L}) slice(2..3)]>", "Fetherolf, Montgomery")]
|
||||
[DataRow("<author[count()]>", "7")]
|
||||
[DataRow("<author[max(42) count()]>", "7")]
|
||||
[DataRow("<author[max(2) count()]>", "2")]
|
||||
@@ -873,6 +879,7 @@ namespace TemplatesTests
|
||||
[DataRow("<tag[count(00)]>", "03")]
|
||||
[DataRow("<tag[unique({S:3}) sort(s)]>", "Tag3")]
|
||||
[DataRow("<tag[unique({S:3}) count()]>", "1")]
|
||||
[DataRow("<tag[filter(~ '[2-5]')]>", "Tag2, Tag3")]
|
||||
[DataRow("<tag [max(1)]>", "Tag1")]
|
||||
[DataRow("<tag [slice(2..)]>", "Tag2, Tag3")]
|
||||
[DataRow("<tag[sort(s)]>", "Tag3, Tag2, Tag1")]
|
||||
|
||||
@@ -131,19 +131,20 @@ Text formatting can change length and case of the text. Use \<#\>, \<#\>\<case\>
|
||||
|
||||
### Text List Formatters
|
||||
|
||||
| Formatter | Description | Example Usage | Example Result |
|
||||
|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------|----------------------------------------------|
|
||||
| separator() | Specify the text used to join<br>multiple entries.<br><br>Default is ", " | `<tag[separator(_)]>` | Tag1_Tag2_Tag3_Tag4_Tag5 |
|
||||
| format(\{S\}) **†** | Formats the entries by placing their values into the specified template.<br>Use \{S:[Text formatters](#text-formatters)\} to place the entry and optionally apply a format. | `<tag[format(Tag={S:l})`<br>`separator(;)]>` | Tag=tag1;Tag=tag2;Tag=tag3;Tag=tag4;Tag=tag5 |
|
||||
| unique(FMT) **†** | Reduce list members to a unique set. Entries are compared to each other after applying the given format. Duplicate entries (after format is applied) are removed, keeping the first occurrence. | `<tag[unique()]>`<hr>`<tag[unique({S:1L})`<br>`separator(;)]>` | Tag1, Tag2, Tag3<hr>tag1 |
|
||||
| sort(S) | Sorts the elements by their value.<br><br>*Sorting direction:*<br>uppercase = ascending<br>lowercase = descending<br><br>Default is unsorted | `<tag[sort(s)`<br>`separator(;)]>` | Tag5;Tag4;Tag3;Tag2;Tag1 |
|
||||
| max(#) | Only use the first # of entries | `<tag[max(1)]>` | Tag1 |
|
||||
| slice(#) | Only use the nth entry of the list | `<tag[slice(2)]>` | Tag2 |
|
||||
| slice(#..) | Only use entries of the list starting from # | `<tag[slice(2..)]>` | Tag2, Tag3, Tag4, Tag5 |
|
||||
| slice(..#) | Like max(#). Only use the first # of entries | `<tag[slice(..1)]>` | Tag1 |
|
||||
| slice(#..#) | Only use entries of the list starting from # and ending at # (inclusive) | `<tag[slice(2..4)]>` | Tag2, Tag3, Tag4 |
|
||||
| slice(-#..-#) | Numbers may be specified negative. In that case positions ar counted from the end with -1 pointing at the last member | `<tag[slice(-3..-2)]>` | Tag3, Tag4 |
|
||||
| count(FMT) **‡** | Instead of returning some or all members of the list, print out the number of entries using the specified [format](#number-formatters). | `<tag[count()]>`<hr>`<tag[count(00)]>` | 5<hr>05 |
|
||||
| Formatter | Description | Example Usage | Example Result |
|
||||
|--------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------|----------------------------------------------|
|
||||
| separator() | Specify the text used to join<br>multiple entries.<br><br>Default is ", " | `<tag[separator(_)]>` | Tag1_Tag2_Tag3_Tag4_Tag5 |
|
||||
| format(\{S\}) **†** | Formats the entries by placing their values into the specified template.<br>Use \{S:[Text formatters](#text-formatters)\} to place the entry and optionally apply a format. | `<tag[format(Tag={S:l})`<br>`separator(;)]>` | Tag=tag1;Tag=tag2;Tag=tag3;Tag=tag4;Tag=tag5 |
|
||||
| unique(FMT) **†** | Reduce list members to a unique set. Entries are compared to each other after applying the given format. Duplicate entries (after format is applied) are removed, keeping the first occurrence. | `<tag[unique()]>`<hr>`<tag[unique({S:1L})`<br>`separator(;)]>` | Tag1, Tag2, Tag3<hr>tag1 |
|
||||
| sort(S) | Sorts the elements by their value.<br><br>*Sorting direction:*<br>uppercase = ascending<br>lowercase = descending<br><br>Default is unsorted | `<tag[sort(s)`<br>`separator(;)]>` | Tag5;Tag4;Tag3;Tag2;Tag1 |
|
||||
| max(#) | Only use the first # of entries | `<tag[max(1)]>` | Tag1 |
|
||||
| slice(#) | Only use the nth entry of the list | `<tag[slice(2)]>` | Tag2 |
|
||||
| slice(#..) | Only use entries of the list starting from # | `<tag[slice(2..)]>` | Tag2, Tag3, Tag4, Tag5 |
|
||||
| slice(..#) | Like max(#). Only use the first # of entries | `<tag[slice(..1)]>` | Tag1 |
|
||||
| slice(#..#) | Only use entries of the list starting from # and ending at # (inclusive) | `<tag[slice(2..4)]>` | Tag2, Tag3, Tag4 |
|
||||
| slice(-#..-#) | Numbers may be specified negative. In that case positions ar counted from the end with -1 pointing at the last member | `<tag[slice(-3..-2)]>` | Tag3, Tag4 |
|
||||
| count(FMT) **‡** | Instead of returning some or all members of the list, print out the number of entries using the specified [format](#number-formatters). | `<tag[count()]>`<hr>`<tag[count(00)]>` | 5<hr>05 |
|
||||
| filter(FMT [CHECK](#checks) VALUE) **†** | Filter list entries based on a condition. Each item is first formatted using the specified text format (or the default format if FMT is omitted), then compared against VALUE using the specified [CHECK](#checks). Only matching entries are included in the output.<br><br>**Syntax:** `filter(FORMAT CHECK VALUE)` or `filter(CHECK VALUE)`<br>- `FORMAT`: Optional text format to apply to each entry (e.g., `{S}`, `{S:L}`, `{S:3}`); defaults to `{S}`<br>- `CHECK`: Comparison operator (e.g., `=`, `!=`, `~`)<br>- `VALUE`: The value to compare against | `<tag[filter({S} ~ '[3-9]')]>`<hr>`<tag[filter({S} != 'Ignore')]>`<hr>`<tag[filter(~ '[A-Z]')]` | Tag3, Tag4, Tag5<hr>Tag1, Tag2, Tag4, Tag5<hr>TagA, TagB, TagC |
|
||||
|
||||
**†** For further information on format templates, please refer to the [Format templates](#format-templates) section.
|
||||
|
||||
@@ -159,15 +160,16 @@ Text formatting can change length and case of the text. Use \<#\>, \<#\>\<case\>
|
||||
|
||||
### Series List Formatters
|
||||
|
||||
| Formatter | Description | Example Usage | Example Result |
|
||||
|---------------------------------| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |-------------------------------------------------------------------------------------------| ------------------------------------------------------------------------------------------------------------------- |
|
||||
| separator() | Specify the text used to join<br>multiple series names.<br><br>Default is ", " | `<series[separator(; )]>` | Sherlock Holmes; Some Other Series |
|
||||
| format(\{N \| # \| ID\}) **†** | Formats the series properties<br>using the name series tags.<br>See [Series Formatter Usage](#series-formatters) above. | `<series[format({N}, {#})`<br>`separator(; )]>`<hr>`<series[format({ID}-{N}, {#:00.0})]>` | Sherlock Holmes, 1-6; Book Collection, 1<hr>B08376S3R2-Sherlock Holmes, 01.0-06.0, B000000000-Book Collection, 01.0 |
|
||||
| unique(FMT) **†** | Reduce list members to a unique set. Entries are compared to each other after applying the given format. Duplicate entries (after format is applied) are removed, keeping the first occurrence. | `<series[unique()]>`<hr>`<series[unique({N:L})`<br>`separator(; )]>` | Sherlock Holmes; Some Other Series<hr>sherlock holmes; some other series |
|
||||
| sort(N \| # \| ID) | Sorts the series by name, number or ID.<br><br>These terms define the primary, secondary, tertiary, … sorting order.<br>You may combine multiple terms in sequence to specify multi‑level sorting.<br><br>*Sorting direction:*<br>uppercase = ascending<br>lowercase = descending<br><br>Default is unsorted | `<series[sort(N)`<br>`separator(; )]>` | Book Collection, 1; Sherlock Holmes, 1-6 |
|
||||
| max(#) | Only use the first # of series | `<series[max(1)]>` | Sherlock Holmes |
|
||||
| slice(#..#) | Only use entries of the series list starting from # and ending at # (inclusive)<br><br>See [Text List Formatter Usage](#Text-List-Formatters) above for details on all the variants of `slice()` | `<series[slice(..-2)]>` | Sherlock Holmes |
|
||||
| count(FMT) **‡** | Instead of returning some or all members of the list, print out the number of series using the specified [format](#number-formatters). | `<series[count()]>`<hr>`<series[count(00)]>` | 2<hr>02 |
|
||||
| Formatter | Description | Example Usage | Example Result |
|
||||
|-------------------------------------------| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |-------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| separator() | Specify the text used to join<br>multiple series names.<br><br>Default is ", " | `<series[separator(; )]>` | Sherlock Holmes; Some Other Series |
|
||||
| format(\{N \| # \| ID\}) **†** | Formats the series properties<br>using the name series tags.<br>See [Series Formatter Usage](#series-formatters) above. | `<series[format({N}, {#})`<br>`separator(; )]>`<hr>`<series[format({ID}-{N}, {#:00.0})]>` | Sherlock Holmes, 1-6; Book Collection, 1<hr>B08376S3R2-Sherlock Holmes, 01.0-06.0, B000000000-Book Collection, 01.0 |
|
||||
| unique(FMT) **†** | Reduce list members to a unique set. Entries are compared to each other after applying the given format. Duplicate entries (after format is applied) are removed, keeping the first occurrence. | `<series[unique()]>`<hr>`<series[unique({N:L})`<br>`separator(; )]>` | Sherlock Holmes; Some Other Series<hr>sherlock holmes; some other series |
|
||||
| sort(N \| # \| ID) | Sorts the series by name, number or ID.<br><br>These terms define the primary, secondary, tertiary, … sorting order.<br>You may combine multiple terms in sequence to specify multi‑level sorting.<br><br>*Sorting direction:*<br>uppercase = ascending<br>lowercase = descending<br><br>Default is unsorted | `<series[sort(N)`<br>`separator(; )]>` | Book Collection, 1; Sherlock Holmes, 1-6 |
|
||||
| max(#) | Only use the first # of series | `<series[max(1)]>` | Sherlock Holmes |
|
||||
| slice(#..#) | Only use entries of the series list starting from # and ending at # (inclusive)<br><br>See [Text List Formatter Usage](#Text-List-Formatters) above for details on all the variants of `slice()` | `<series[slice(..-2)]>` | Sherlock Holmes |
|
||||
| count(FMT) **‡** | Instead of returning some or all members of the list, print out the number of series using the specified [format](#number-formatters). | `<series[count()]>`<hr>`<series[count(00)]>` | 2<hr>02 |
|
||||
| filter(FMT [CHECK](#checks) VALUE) **†** | Filter list entries based on a condition. Each series is first formatted using the specified [Series Format](#series-formatters) (or the default format if FMT is omitted), then compared against VALUE using the specified [CHECK](#checks). Only matching entries are included in the output.<br><br>**Syntax:** `filter(FORMAT CHECK VALUE)` or `filter(CHECK VALUE)`<br>- `FORMAT`: Optional series format to apply to each entry (e.g., `{N}`, `{N:L}`, `{#}`); defaults to `{N}`<br>- `CHECK`: Comparison operator (e.g., `=`, `!=`, `~`)<br>- `VALUE`: The value to compare against | `<series[filter({N} = 'Holmes')]>`<hr>`<series[filter(~ 'Sherlock')]` | Sherlock Holmes<hr>Sherlock Holmes |
|
||||
|
||||
**†** For further information on format templates, please refer to the [Format templates](#format-templates) section.
|
||||
|
||||
@@ -183,15 +185,16 @@ Text formatting can change length and case of the text. Use \<#\>, \<#\>\<case\>
|
||||
|
||||
### Name List Formatters
|
||||
|
||||
| Formatter | Description | Example Usage | Example Result |
|
||||
|------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| separator() | Specify the text used to join<br>multiple people's names.<br><br>Default is ", " | `<author[separator(; )]>` | Arthur Conan Doyle; Stephen Fry |
|
||||
| format(\{T \| F \| M \| L \| S \| ID\}) **†** | Formats the human name using<br>the name part tags.<br>See [Name Formatter Usage](#name-formatters) above. | `<author[format({L:u}, {F})`<br>`separator(; )]>`<hr>`<author[format({L}, {F:1}.`<br>`_{ID}_) separator(; )]>` | DOYLE, Arthur; FRY, Stephen<hr>Doyle, A. \_B000AQ43GQ\_;<br>Fry, S. \_B000APAGVS\_ |
|
||||
| unique(FMT) **†** | Reduce list members to a unique set. Entries are compared to each other after applying the given format. Duplicate entries (after format is applied) are removed, keeping the first occurrence. | `<author[unique()]>`<hr>`<author[unique({L:L})`<br>`separator(; )]>` | Arthur Conan Doyle, Stephen Fry<hr>doyle; fry |
|
||||
| sort(T \| F \| M \| L \| S \| ID) | Sorts the names by title,<br> first, middle, or last name,<br>suffix or Audible Contributor ID<br><br>These terms define the primary, secondary, tertiary, … sorting order.<br>You may combine multiple terms in sequence to specify multi‑level sorting.<br><br>*Sorting direction:*<br>uppercase = ascending<br>lowercase = descending<br><br>Default is unsorted | `<author[sort(M)]>`<hr>`<author[sort(Fl)]>`<hr>`<author[sort(L FM ID)]>` | Stephen Fry, Arthur Conan Doyle<hr>Stephen King, Stephen Fry<hr>John P. Smith \_B000TTTBBB\_, John P. Smith \_B000TTTCCC\_, John S. Smith \_B000HHHVVV\_ |
|
||||
| max(#) | Only use the first # of names<br><br>Default is all names | `<author[max(1)]>` | Arthur Conan Doyle |
|
||||
| slice(#..#) | Only use entries of the names list starting from # and ending at # (inclusive)<br><br>See [Text List Formatter Usage](#Text-List-Formatters) above for details on all the variants of `slice()` | `<author[slice(..-2)]>` | Arthur Conan Doyle |
|
||||
| count(FMT) **‡** | Instead of returning some or all members of the list, print out the number of names using the specified [format](#number-formatters). | `<author[count()]>`<hr>`<author[count(00)]>` | 2<hr>02 |
|
||||
| Formatter | Description | Example Usage | Example Result |
|
||||
|-----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| separator() | Specify the text used to join<br>multiple people's names.<br><br>Default is ", " | `<author[separator(; )]>` | Arthur Conan Doyle; Stephen Fry |
|
||||
| format(\{T \| F \| M \| L \| S \| ID\}) **†** | Formats the human name using<br>the name part tags.<br>See [Name Formatter Usage](#name-formatters) above. | `<author[format({L:u}, {F})`<br>`separator(; )]>`<hr>`<author[format({L}, {F:1}.`<br>`_{ID}_) separator(; )]>` | DOYLE, Arthur; FRY, Stephen<hr>Doyle, A. \_B000AQ43GQ\_;<br>Fry, S. \_B000APAGVS\_ |
|
||||
| unique(FMT) **†** | Reduce list members to a unique set. Entries are compared to each other after applying the given format. Duplicate entries (after format is applied) are removed, keeping the first occurrence. | `<author[unique()]>`<hr>`<author[unique({L:L})`<br>`separator(; )]>` | Arthur Conan Doyle, Stephen Fry<hr>doyle; fry |
|
||||
| sort(T \| F \| M \| L \| S \| ID) | Sorts the names by title,<br> first, middle, or last name,<br>suffix or Audible Contributor ID<br><br>These terms define the primary, secondary, tertiary, … sorting order.<br>You may combine multiple terms in sequence to specify multi‑level sorting.<br><br>*Sorting direction:*<br>uppercase = ascending<br>lowercase = descending<br><br>Default is unsorted | `<author[sort(M)]>`<hr>`<author[sort(Fl)]>`<hr>`<author[sort(L FM ID)]>` | Stephen Fry, Arthur Conan Doyle<hr>Stephen King, Stephen Fry<hr>John P. Smith \_B000TTTBBB\_, John P. Smith \_B000TTTCCC\_, John S. Smith \_B000HHHVVV\_ |
|
||||
| max(#) | Only use the first # of names<br><br>Default is all names | `<author[max(1)]>` | Arthur Conan Doyle |
|
||||
| slice(#..#) | Only use entries of the names list starting from # and ending at # (inclusive)<br><br>See [Text List Formatter Usage](#Text-List-Formatters) above for details on all the variants of `slice()` | `<author[slice(..-2)]>` | Arthur Conan Doyle |
|
||||
| count(FMT) **‡** | Instead of returning some or all members of the list, print out the number of names using the specified [format](#number-formatters). | `<author[count()]>`<hr>`<author[count(00)]>` | 2<hr>02 |
|
||||
| filter(FMT [CHECK](#checks) VALUE) **†** | Filter list entries based on a condition. Each person is first formatted using the specified name format (or the default format if FMT is omitted), then compared against VALUE using the specified [CHECK](#checks). Only matching entries are included in the output.<br><br>**Syntax:** `filter(FORMAT CHECK VALUE)` or `filter(CHECK VALUE)`<br>- `FORMAT`: Optional name format to apply to each entry (e.g., `{L}`, `{M}`, `{L}, {F}`); defaults to `{T} {F} {M} {L} {S}`<br>- `CHECK`: Comparison operator (e.g., `=`, `!=`, `~`)<br>- `VALUE`: The value to compare against | `<author[filter({L} = 'Doyle')]>`<hr>`<author[filter({F} ~ '^Stephen')]>`<hr>`<narrator[filter(~ 'Fry')]` | Conan Doyle<hr>Stephen Fry<hr>Stephen Fry |
|
||||
|
||||
**†** For further information on format templates, please refer to the [Format templates](#format-templates) section.
|
||||
|
||||
@@ -314,9 +317,9 @@ string literal `O'Reilly`, you can use either `'O''Reilly'` or `"O'Reilly"`.
|
||||
|
||||
| String Checks | Unicode Operator | Description | Examples |
|
||||
|---------------|------------------|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------|
|
||||
| = | | Matches if values are equal (case-insensitive) | \<is tag[=Tag1]-\> |
|
||||
| != | | Matches if values are not equal (case-insensitive) | \<is first author[!=Arthur]-\><br>\<cmp "foo" != 'bar'-\> |
|
||||
| ~ | | Matches if the first parameter matches the regular expression specified by the second parameter (case-insensitive) | \<is title[~(\[XYZ\]).*\\1]-\> |
|
||||
| = | | Matches if values are equal (case-insensitive) | \<is tag[=Tag1]-\><br>\<author[filter({L} = 'Doyle')]> |
|
||||
| != | | Matches if values are not equal (case-insensitive) | \<is first author[!=Arthur]-\><br>\<cmp "foo" != 'bar'-\><br>\<tag[filter({S} != 'Ignore')]> |
|
||||
| ~ | | Matches if the first parameter matches the regular expression specified by the second parameter (case-insensitive) | \<is title[~(\[XYZ\]).*\\1]-\><br>\<tag[filter({S} ~ '[3-9]')]><br>\<narrator[filter({F} ~ '^Stephen')]> |
|
||||
|
||||
| Number Checks | Unicode Operator | Description | Examples |
|
||||
|---------------|------------------|----------------------------------------------------------------|-----------------------------------------------------------|
|
||||
|
||||
Reference in new issue
Block a user