Add Enumerable initializers
This commit is contained in:
parent
40602c7626
commit
5917d059e4
@ -24,7 +24,11 @@ public class ConditionalTagClass<TClass> : TagClass
|
|||||||
{
|
{
|
||||||
public ConditionalTagClass(bool caseSensative = true) :base(typeof(TClass), caseSensative) { }
|
public ConditionalTagClass(bool caseSensative = true) :base(typeof(TClass), caseSensative) { }
|
||||||
|
|
||||||
public void RegisterCondition(ITemplateTag templateTag, Func<TClass, bool> propertyGetter)
|
/// <summary>
|
||||||
|
/// Register a conditional tag.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyGetter">A Func to get the condition's <see cref="bool"/> value from <see cref="TClass"/></param>
|
||||||
|
public void Add(ITemplateTag templateTag, Func<TClass, bool> propertyGetter)
|
||||||
{
|
{
|
||||||
var expr = Expression.Call(Expression.Constant(propertyGetter.Target), propertyGetter.Method, Parameter);
|
var expr = Expression.Call(Expression.Constant(propertyGetter.Target), propertyGetter.Method, Parameter);
|
||||||
|
|
||||||
@ -51,13 +55,11 @@ public class ConditionalTagClass<TClass> : TagClass
|
|||||||
propertyTag = this;
|
propertyTag = this;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
exactName = null;
|
exactName = null;
|
||||||
propertyTag = null;
|
propertyTag = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected override Expression GetTagExpression(string exactName, string formatter) => formatter == "!" ? Expression.Not(ExpressionValue) : ExpressionValue;
|
protected override Expression GetTagExpression(string exactName, string formatter) => formatter == "!" ? Expression.Not(ExpressionValue) : ExpressionValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ public class NamingTemplate
|
|||||||
{
|
{
|
||||||
public string TemplateText { get; private set; }
|
public string TemplateText { get; private set; }
|
||||||
public IEnumerable<ITemplateTag> TagsInUse => _tagsInUse;
|
public IEnumerable<ITemplateTag> TagsInUse => _tagsInUse;
|
||||||
public IEnumerable<ITemplateTag> TagsRegistered => Classes.SelectMany(p => p.TemplateTags).DistinctBy(f => f.TagName);
|
public IEnumerable<ITemplateTag> TagsRegistered => Classes.SelectMany(t => t).DistinctBy(t => t.TagName);
|
||||||
public IEnumerable<string> Warnings => errors.Concat(warnings);
|
public IEnumerable<string> Warnings => errors.Concat(warnings);
|
||||||
public IEnumerable<string> Errors => errors;
|
public IEnumerable<string> Errors => errors;
|
||||||
|
|
||||||
@ -183,6 +183,7 @@ public class NamingTemplate
|
|||||||
if (pc.StartsWith(template, out exactName, out propertyTag, out valueExpression))
|
if (pc.StartsWith(template, out exactName, out propertyTag, out valueExpression))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
exactName = null;
|
exactName = null;
|
||||||
valueExpression = null;
|
valueExpression = null;
|
||||||
propertyTag = null;
|
propertyTag = null;
|
||||||
@ -196,6 +197,7 @@ public class NamingTemplate
|
|||||||
if (pc.StartsWithClosing(template, out exactName, out closingPropertyTag))
|
if (pc.StartsWithClosing(template, out exactName, out closingPropertyTag))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
exactName = null;
|
exactName = null;
|
||||||
closingPropertyTag = null;
|
closingPropertyTag = null;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -17,9 +17,9 @@ public class PropertyTagClass<TClass> : TagClass
|
|||||||
/// <typeparam name="U">Type of the property from <see cref="TClass"/></typeparam>
|
/// <typeparam name="U">Type of the property from <see cref="TClass"/></typeparam>
|
||||||
/// <param name="propertyGetter">A Func to get the property value from <see cref="TClass"/></param>
|
/// <param name="propertyGetter">A Func to get the property value from <see cref="TClass"/></param>
|
||||||
/// <param name="formatter">Optional formatting function that accepts the <typeparamref name="U"/> property and a formatting string and returnes the value formatted to string</param>
|
/// <param name="formatter">Optional formatting function that accepts the <typeparamref name="U"/> property and a formatting string and returnes the value formatted to string</param>
|
||||||
public void RegisterProperty<U>(ITemplateTag templateTag, Func<TClass, U?> propertyGetter, PropertyFormatter<U> formatter = null)
|
public void Add<U>(ITemplateTag templateTag, Func<TClass, U?> propertyGetter, PropertyFormatter<U> formatter = null)
|
||||||
where U : struct
|
where U : struct
|
||||||
=> RegisterPropertyInternal(templateTag, propertyGetter, formatter);
|
=> RegisterProperty(templateTag, propertyGetter, formatter);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register a non-nullable value type property
|
/// Register a non-nullable value type property
|
||||||
@ -27,19 +27,19 @@ public class PropertyTagClass<TClass> : TagClass
|
|||||||
/// <typeparam name="U">Type of the property from <see cref="TClass"/></typeparam>
|
/// <typeparam name="U">Type of the property from <see cref="TClass"/></typeparam>
|
||||||
/// <param name="propertyGetter">A Func to get the property value from <see cref="TClass"/></param>
|
/// <param name="propertyGetter">A Func to get the property value from <see cref="TClass"/></param>
|
||||||
/// <param name="formatter">Optional formatting function that accepts the <typeparamref name="U"/> property and a formatting string and returnes the value formatted to string</param>
|
/// <param name="formatter">Optional formatting function that accepts the <typeparamref name="U"/> property and a formatting string and returnes the value formatted to string</param>
|
||||||
public void RegisterProperty<U>(ITemplateTag templateTag, Func<TClass, U> propertyGetter, PropertyFormatter<U> formatter = null)
|
public void Add<U>(ITemplateTag templateTag, Func<TClass, U> propertyGetter, PropertyFormatter<U> formatter = null)
|
||||||
where U : struct
|
where U : struct
|
||||||
=> RegisterPropertyInternal(templateTag, propertyGetter, formatter);
|
=> RegisterProperty(templateTag, propertyGetter, formatter);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register a string type property.
|
/// Register a string type property.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="propertyGetter">A Func to get the string property from <see cref="TClass"/></param>
|
/// <param name="propertyGetter">A Func to get the string property from <see cref="TClass"/></param>
|
||||||
/// <param name="formatter">Optional formatting function that accepts the string property and a formatting string and returnes the value formatted to string</param>
|
/// <param name="formatter">Optional formatting function that accepts the string property and a formatting string and returnes the value formatted to string</param>
|
||||||
public void RegisterProperty(ITemplateTag templateTag, Func<TClass, string> propertyGetter, PropertyFormatter<string> formatter = null)
|
public void Add(ITemplateTag templateTag, Func<TClass, string> propertyGetter, PropertyFormatter<string> formatter = null)
|
||||||
=> RegisterPropertyInternal(templateTag, propertyGetter, formatter);
|
=> RegisterProperty(templateTag, propertyGetter, formatter);
|
||||||
|
|
||||||
private void RegisterPropertyInternal(ITemplateTag templateTag, Delegate propertyGetter, Delegate formatter)
|
private void RegisterProperty(ITemplateTag templateTag, Delegate propertyGetter, Delegate formatter)
|
||||||
{
|
{
|
||||||
if (formatter?.Target is not null)
|
if (formatter?.Target is not null)
|
||||||
throw new ArgumentException($"{nameof(formatter)} must be a static method");
|
throw new ArgumentException($"{nameof(formatter)} must be a static method");
|
||||||
|
|||||||
@ -13,7 +13,7 @@ internal interface IPropertyTag
|
|||||||
Type ReturnType { get; }
|
Type ReturnType { get; }
|
||||||
|
|
||||||
/// <summary>The <see cref="Regex"/> used to match <see cref="TemplateTag"/> in template strings.</summary>
|
/// <summary>The <see cref="Regex"/> used to match <see cref="TemplateTag"/> in template strings.</summary>
|
||||||
public Regex NameMatcher { get; }
|
Regex NameMatcher { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determine if the template string starts with <see cref="TemplateTag"/>, and if it does parse the tag to an <see cref="Expression"/>
|
/// Determine if the template string starts with <see cref="TemplateTag"/>, and if it does parse the tag to an <see cref="Expression"/>
|
||||||
@ -52,13 +52,11 @@ internal abstract class TagBase : IPropertyTag
|
|||||||
propertyValue = GetTagExpression(exactName, match.Groups.Count == 2 ? match.Groups[1].Value.Trim() : "");
|
propertyValue = GetTagExpression(exactName, match.Groups.Count == 2 ? match.Groups[1].Value.Trim() : "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
exactName = null;
|
exactName = null;
|
||||||
propertyValue = null;
|
propertyValue = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
@ -6,17 +7,16 @@ using System.Text.RegularExpressions;
|
|||||||
|
|
||||||
namespace FileManager.NamingTemplate;
|
namespace FileManager.NamingTemplate;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>A collection of <see cref="IPropertyTag"/>s registered to a single <see cref="Type"/>.</summary>
|
/// <summary>A collection of <see cref="IPropertyTag"/>s registered to a single <see cref="Type"/>.</summary>
|
||||||
public abstract class TagClass
|
public abstract class TagClass : IEnumerable<ITemplateTag>
|
||||||
{
|
{
|
||||||
/// <summary>The <see cref="ParameterExpression"/> of the <see cref="TagClass"/>'s TClass type.</summary>
|
/// <summary>The <see cref="ParameterExpression"/> of the <see cref="TagClass"/>'s TClass type.</summary>
|
||||||
public ParameterExpression Parameter { get; }
|
public ParameterExpression Parameter { get; }
|
||||||
/// <summary>The <see cref="ITemplateTag"/>s registered with this <see cref="TagClass"/> </summary>
|
/// <summary>The <see cref="ITemplateTag"/>s registered with this <see cref="TagClass"/> </summary>
|
||||||
public IEnumerable<ITemplateTag> TemplateTags => PropertyTags.Select(p => p.TemplateTag);
|
public IEnumerator<ITemplateTag> GetEnumerator() => PropertyTags.Select(p => p.TemplateTag).GetEnumerator();
|
||||||
|
|
||||||
protected RegexOptions Options { get; } = RegexOptions.Compiled;
|
protected RegexOptions Options { get; } = RegexOptions.Compiled;
|
||||||
private protected List<IPropertyTag> PropertyTags { get; } = new();
|
private List<IPropertyTag> PropertyTags { get; } = new();
|
||||||
|
|
||||||
protected TagClass(Type classType, bool caseSensative = true)
|
protected TagClass(Type classType, bool caseSensative = true)
|
||||||
{
|
{
|
||||||
@ -42,6 +42,7 @@ public abstract class TagClass
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
propertyValue = null;
|
propertyValue = null;
|
||||||
propertyTag = null;
|
propertyTag = null;
|
||||||
exactName = null;
|
exactName = null;
|
||||||
@ -74,4 +75,6 @@ public abstract class TagClass
|
|||||||
if (!PropertyTags.Any(c => c.TemplateTag.TagName == propertyTag.TemplateTag.TagName))
|
if (!PropertyTags.Any(c => c.TemplateTag.TagName == propertyTag.TemplateTag.TagName))
|
||||||
PropertyTags.Add(propertyTag);
|
PropertyTags.Add(propertyTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ public class TemplatePart : IEnumerable<TemplatePart>
|
|||||||
public ITemplateTag TemplateTag { get; }
|
public ITemplateTag TemplateTag { get; }
|
||||||
|
|
||||||
/// <summary>The evaluated string.</summary>
|
/// <summary>The evaluated string.</summary>
|
||||||
public string Value { get; set; }
|
public string Value { get; }
|
||||||
|
|
||||||
private TemplatePart previous;
|
private TemplatePart previous;
|
||||||
private TemplatePart next;
|
private TemplatePart next;
|
||||||
|
|||||||
@ -6,7 +6,6 @@ using AaxDecrypter;
|
|||||||
using Dinah.Core;
|
using Dinah.Core;
|
||||||
using FileManager;
|
using FileManager;
|
||||||
using FileManager.NamingTemplate;
|
using FileManager.NamingTemplate;
|
||||||
using Serilog.Formatting;
|
|
||||||
|
|
||||||
namespace LibationFileManager
|
namespace LibationFileManager
|
||||||
{
|
{
|
||||||
@ -21,7 +20,7 @@ namespace LibationFileManager
|
|||||||
public const string ERROR_FULL_PATH_IS_INVALID = @"No colons or full paths allowed. Eg: should not start with C:\";
|
public const string ERROR_FULL_PATH_IS_INVALID = @"No colons or full paths allowed. Eg: should not start with C:\";
|
||||||
public const string WARNING_NO_CHAPTER_NUMBER_TAG = "Should include chapter number tag in template used for naming files which are split by chapter. Ie: <ch#> or <ch# 0>";
|
public const string WARNING_NO_CHAPTER_NUMBER_TAG = "Should include chapter number tag in template used for naming files which are split by chapter. Ie: <ch#> or <ch# 0>";
|
||||||
|
|
||||||
//Assign the properties in the static constructor will require all
|
//Assigning the properties in the static constructor will require all
|
||||||
//Templates users to have a valid configuration file. To allow tests
|
//Templates users to have a valid configuration file. To allow tests
|
||||||
//to work without access to Configuration, only load templates on demand.
|
//to work without access to Configuration, only load templates on demand.
|
||||||
private static FolderTemplate _folder;
|
private static FolderTemplate _folder;
|
||||||
@ -35,6 +34,7 @@ namespace LibationFileManager
|
|||||||
public static ChapterTitleTemplate ChapterTitle => _chapterTitle ??= GetTemplate<ChapterTitleTemplate>(Configuration.Instance.ChapterTitleTemplate);
|
public static ChapterTitleTemplate ChapterTitle => _chapterTitle ??= GetTemplate<ChapterTitleTemplate>(Configuration.Instance.ChapterTitleTemplate);
|
||||||
|
|
||||||
#region Template Parsing
|
#region Template Parsing
|
||||||
|
|
||||||
public static T GetTemplate<T>(string templateText) where T : Templates, ITemplate, new()
|
public static T GetTemplate<T>(string templateText) where T : Templates, ITemplate, new()
|
||||||
=> TryGetTemplate<T>(templateText, out var template) ? template : GetDefaultTemplate<T>();
|
=> TryGetTemplate<T>(templateText, out var template) ? template : GetDefaultTemplate<T>();
|
||||||
|
|
||||||
@ -55,21 +55,23 @@ namespace LibationFileManager
|
|||||||
[PropertyChangeFilter(nameof(Configuration.FolderTemplate))]
|
[PropertyChangeFilter(nameof(Configuration.FolderTemplate))]
|
||||||
(_,e) => _folder = GetTemplate<FolderTemplate>((string)e.NewValue);
|
(_,e) => _folder = GetTemplate<FolderTemplate>((string)e.NewValue);
|
||||||
|
|
||||||
Configuration.Instance.PropertyChanged
|
Configuration.Instance.PropertyChanged +=
|
||||||
+= [PropertyChangeFilter(nameof(Configuration.FileTemplate))]
|
[PropertyChangeFilter(nameof(Configuration.FileTemplate))]
|
||||||
(_, e) => _file = GetTemplate<FileTemplate>((string)e.NewValue);
|
(_, e) => _file = GetTemplate<FileTemplate>((string)e.NewValue);
|
||||||
|
|
||||||
Configuration.Instance.PropertyChanged
|
Configuration.Instance.PropertyChanged +=
|
||||||
+= [PropertyChangeFilter(nameof(Configuration.ChapterFileTemplate))]
|
[PropertyChangeFilter(nameof(Configuration.ChapterFileTemplate))]
|
||||||
(_, e) => _chapterFile = GetTemplate<ChapterFileTemplate>((string)e.NewValue);
|
(_, e) => _chapterFile = GetTemplate<ChapterFileTemplate>((string)e.NewValue);
|
||||||
|
|
||||||
Configuration.Instance.PropertyChanged
|
Configuration.Instance.PropertyChanged +=
|
||||||
+= [PropertyChangeFilter(nameof(Configuration.ChapterTitleTemplate))]
|
[PropertyChangeFilter(nameof(Configuration.ChapterTitleTemplate))]
|
||||||
(_, e) => _chapterTitle = GetTemplate<ChapterTitleTemplate>((string)e.NewValue);
|
(_, e) => _chapterTitle = GetTemplate<ChapterTitleTemplate>((string)e.NewValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Template Properties
|
#region Template Properties
|
||||||
|
|
||||||
public IEnumerable<TemplateTags> TagsRegistered => Template.TagsRegistered.Cast<TemplateTags>();
|
public IEnumerable<TemplateTags> TagsRegistered => Template.TagsRegistered.Cast<TemplateTags>();
|
||||||
public IEnumerable<TemplateTags> TagsInUse => Template.TagsInUse.Cast<TemplateTags>();
|
public IEnumerable<TemplateTags> TagsInUse => Template.TagsInUse.Cast<TemplateTags>();
|
||||||
public abstract string Name { get; }
|
public abstract string Name { get; }
|
||||||
@ -77,7 +79,6 @@ namespace LibationFileManager
|
|||||||
public string TemplateText => Template.TemplateText;
|
public string TemplateText => Template.TemplateText;
|
||||||
protected NamingTemplate Template { get; private set; }
|
protected NamingTemplate Template { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region validation
|
#region validation
|
||||||
@ -152,7 +153,7 @@ namespace LibationFileManager
|
|||||||
part.Insert(maxIndex, maxEntry.Remove(maxLength - 1, 1));
|
part.Insert(maxIndex, maxEntry.Remove(maxLength - 1, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Any
|
|
||||||
var fullPath = Path.Combine(pathParts.Select(fileParts => string.Join("", fileParts)).Prepend(baseDir).ToArray());
|
var fullPath = Path.Combine(pathParts.Select(fileParts => string.Join("", fileParts)).Prepend(baseDir).ToArray());
|
||||||
|
|
||||||
return FileUtility.GetValidFilename(fullPath, replacements, fileExtension, returnFirstExisting);
|
return FileUtility.GetValidFilename(fullPath, replacements, fileExtension, returnFirstExisting);
|
||||||
@ -163,7 +164,7 @@ namespace LibationFileManager
|
|||||||
/// returned as empty directories and are taken care of by Path.Combine()
|
/// returned as empty directories and are taken care of by Path.Combine()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A List of template directories. Each directory is a list of template part strings</returns>
|
/// <returns>A List of template directories. Each directory is a list of template part strings</returns>
|
||||||
private List<List<string>> GetPathParts(IEnumerable<string> templateParts)
|
private static List<List<string>> GetPathParts(IEnumerable<string> templateParts)
|
||||||
{
|
{
|
||||||
List<List<string>> directories = new();
|
List<List<string>> directories = new();
|
||||||
List<string> dir = new();
|
List<string> dir = new();
|
||||||
@ -190,64 +191,54 @@ namespace LibationFileManager
|
|||||||
|
|
||||||
#region Registered Template Properties
|
#region Registered Template Properties
|
||||||
|
|
||||||
private static readonly PropertyTagClass<LibraryBookDto> filePropertyTags = GetFilePropertyTags();
|
private static readonly PropertyTagClass<LibraryBookDto> filePropertyTags = new()
|
||||||
private static readonly ConditionalTagClass<LibraryBookDto> conditionalTags = GetConditionalTags();
|
|
||||||
private static readonly List<TagClass> chapterPropertyTags = GetChapterPropertyTags();
|
|
||||||
|
|
||||||
private static ConditionalTagClass<LibraryBookDto> GetConditionalTags()
|
|
||||||
{
|
{
|
||||||
ConditionalTagClass<LibraryBookDto> lbConditions = new();
|
{ TemplateTags.Id, lb => lb.AudibleProductId },
|
||||||
|
{ TemplateTags.Title, lb => lb.Title, StringFormatter },
|
||||||
|
{ TemplateTags.TitleShort, lb => lb.Title.IndexOf(':') < 1 ? lb.Title : lb.Title.Substring(0, lb.Title.IndexOf(':')), StringFormatter },
|
||||||
|
{ TemplateTags.Author, lb => lb.AuthorNames, StringFormatter },
|
||||||
|
{ TemplateTags.FirstAuthor, lb => lb.FirstAuthor, StringFormatter },
|
||||||
|
{ TemplateTags.Narrator, lb => lb.NarratorNames, StringFormatter },
|
||||||
|
{ TemplateTags.FirstNarrator, lb => lb.FirstNarrator, StringFormatter },
|
||||||
|
{ TemplateTags.Series, lb => lb.SeriesName, StringFormatter },
|
||||||
|
{ TemplateTags.SeriesNumber, lb => lb.SeriesNumber, IntegerFormatter },
|
||||||
|
{ TemplateTags.Language, lb => lb.Language, StringFormatter },
|
||||||
|
{ TemplateTags.LanguageShort, lb => getLanguageShort(lb.Language), StringFormatter },
|
||||||
|
{ TemplateTags.Bitrate, lb => lb.BitRate, IntegerFormatter },
|
||||||
|
{ TemplateTags.SampleRate, lb => lb.SampleRate, IntegerFormatter },
|
||||||
|
{ TemplateTags.Channels, lb => lb.Channels, IntegerFormatter },
|
||||||
|
{ TemplateTags.Account, lb => lb.Account, StringFormatter },
|
||||||
|
{ TemplateTags.Locale, lb => lb.Locale, StringFormatter },
|
||||||
|
{ TemplateTags.YearPublished, lb => lb.YearPublished, IntegerFormatter },
|
||||||
|
{ TemplateTags.DatePublished, lb => lb.DatePublished, DateTimeFormatter },
|
||||||
|
{ TemplateTags.DateAdded, lb => lb.DateAdded, DateTimeFormatter },
|
||||||
|
{ TemplateTags.FileDate, lb => lb.FileDate, DateTimeFormatter },
|
||||||
|
};
|
||||||
|
|
||||||
lbConditions.RegisterCondition(TemplateTags.IfSeries, lb => lb.IsSeries);
|
private static readonly List<TagClass> chapterPropertyTags = new()
|
||||||
lbConditions.RegisterCondition(TemplateTags.IfPodcast, lb => lb.IsPodcast);
|
|
||||||
lbConditions.RegisterCondition(TemplateTags.IfBookseries, lb => lb.IsSeries && !lb.IsPodcast);
|
|
||||||
|
|
||||||
return lbConditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PropertyTagClass<LibraryBookDto> GetFilePropertyTags()
|
|
||||||
{
|
{
|
||||||
PropertyTagClass<LibraryBookDto> lbProperties = new();
|
new PropertyTagClass<LibraryBookDto>()
|
||||||
lbProperties.RegisterProperty(TemplateTags.Id, lb => lb.AudibleProductId);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Title, lb => lb.Title, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.TitleShort, lb => lb.Title.IndexOf(':') < 1 ? lb.Title : lb.Title.Substring(0, lb.Title.IndexOf(':')), StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Author, lb => lb.AuthorNames, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.FirstAuthor, lb => lb.FirstAuthor, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Narrator, lb => lb.NarratorNames, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.FirstNarrator, lb => lb.FirstNarrator, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Series, lb => lb.SeriesName, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.SeriesNumber, lb => lb.SeriesNumber, IntegerFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Language, lb => lb.Language, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.LanguageShort, lb => getLanguageShort(lb.Language), StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Bitrate, lb => lb.BitRate, IntegerFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.SampleRate, lb => lb.SampleRate, IntegerFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Channels, lb => lb.Channels, IntegerFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Account, lb => lb.Account, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.Locale, lb => lb.Locale, StringFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.YearPublished, lb => lb.YearPublished, IntegerFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.DatePublished, lb => lb.DatePublished, DateTimeFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.DateAdded, lb => lb.DateAdded, DateTimeFormatter);
|
|
||||||
lbProperties.RegisterProperty(TemplateTags.FileDate, lb => lb.FileDate, DateTimeFormatter);
|
|
||||||
return lbProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<TagClass> GetChapterPropertyTags()
|
|
||||||
{
|
{
|
||||||
PropertyTagClass<LibraryBookDto> lbProperties = new();
|
{ TemplateTags.Title, lb => lb.Title, StringFormatter },
|
||||||
PropertyTagClass<MultiConvertFileProperties> multiConvertProperties = new();
|
{ TemplateTags.TitleShort, lb => lb?.Title?.IndexOf(':') > 0 ? lb.Title.Substring(0, lb.Title.IndexOf(':')) : lb.Title, StringFormatter },
|
||||||
|
{ TemplateTags.Series, lb => lb.SeriesName, StringFormatter },
|
||||||
lbProperties.RegisterProperty(TemplateTags.Title, lb => lb.Title, StringFormatter);
|
},
|
||||||
lbProperties.RegisterProperty(TemplateTags.TitleShort, lb => lb?.Title?.IndexOf(':') > 0 ? lb.Title.Substring(0, lb.Title.IndexOf(':')) : lb.Title, StringFormatter);
|
new PropertyTagClass<MultiConvertFileProperties>()
|
||||||
lbProperties.RegisterProperty(TemplateTags.Series, lb => lb.SeriesName, StringFormatter);
|
{
|
||||||
|
{ TemplateTags.ChCount, lb => lb.PartsTotal, IntegerFormatter },
|
||||||
multiConvertProperties.RegisterProperty(TemplateTags.ChCount, lb => lb.PartsTotal, IntegerFormatter);
|
{ TemplateTags.ChNumber, lb => lb.PartsPosition, IntegerFormatter },
|
||||||
multiConvertProperties.RegisterProperty(TemplateTags.ChNumber, lb => lb.PartsPosition, IntegerFormatter);
|
{ TemplateTags.ChNumber0, m => m.PartsPosition.ToString("D" + ((int)Math.Log10(m.PartsTotal) + 1)) },
|
||||||
multiConvertProperties.RegisterProperty(TemplateTags.ChNumber0, m => m.PartsPosition.ToString("D" + ((int)Math.Log10(m.PartsTotal) + 1)));
|
{ TemplateTags.ChTitle, m => m.Title, StringFormatter },
|
||||||
multiConvertProperties.RegisterProperty(TemplateTags.ChTitle, m => m.Title, StringFormatter);
|
{ TemplateTags.FileDate, lb => lb.FileDate, DateTimeFormatter }
|
||||||
multiConvertProperties.RegisterProperty(TemplateTags.FileDate, lb => lb.FileDate, DateTimeFormatter);
|
|
||||||
|
|
||||||
return new List<TagClass> { lbProperties, multiConvertProperties };
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly ConditionalTagClass<LibraryBookDto> conditionalTags = new()
|
||||||
|
{
|
||||||
|
{TemplateTags.IfSeries, lb => lb.IsSeries },
|
||||||
|
{TemplateTags.IfPodcast, lb => lb.IsPodcast },
|
||||||
|
{TemplateTags.IfBookseries, lb => lb.IsSeries && !lb.IsPodcast },
|
||||||
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -298,17 +289,12 @@ namespace LibationFileManager
|
|||||||
=> TemplateText?.Length >= 2 && Path.IsPathFullyQualified(TemplateText) ? base.Errors.Append(ERROR_FULL_PATH_IS_INVALID) : base.Errors;
|
=> TemplateText?.Length >= 2 && Path.IsPathFullyQualified(TemplateText) ? base.Errors.Append(ERROR_FULL_PATH_IS_INVALID) : base.Errors;
|
||||||
|
|
||||||
protected override List<string> GetTemplatePartsStrings(List<TemplatePart> parts, ReplacementCharacters replacements)
|
protected override List<string> GetTemplatePartsStrings(List<TemplatePart> parts, ReplacementCharacters replacements)
|
||||||
{
|
=> parts
|
||||||
foreach (var tp in parts)
|
.Select(tp => tp.TemplateTag is null
|
||||||
{
|
|
||||||
//FolderTemplate literals can have directory separator characters
|
//FolderTemplate literals can have directory separator characters
|
||||||
if (tp.TemplateTag is null)
|
? replacements.ReplacePathChars(tp.Value.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))
|
||||||
tp.Value = replacements.ReplacePathChars(tp.Value.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
|
: replacements.ReplaceFilenameChars(tp.Value)
|
||||||
else
|
).ToList();
|
||||||
tp.Value = replacements.ReplaceFilenameChars(tp.Value);
|
|
||||||
}
|
|
||||||
return parts.Select(p => p.Value).ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileTemplate : Templates, ITemplate
|
public class FileTemplate : Templates, ITemplate
|
||||||
@ -324,8 +310,7 @@ namespace LibationFileManager
|
|||||||
public override string Name => "Chapter File Template";
|
public override string Name => "Chapter File Template";
|
||||||
public override string Description => Configuration.GetDescription(nameof(Configuration.ChapterFileTemplate));
|
public override string Description => Configuration.GetDescription(nameof(Configuration.ChapterFileTemplate));
|
||||||
public static string DefaultTemplate { get; } = "<title> [<id>] - <ch# 0> - <ch title>";
|
public static string DefaultTemplate { get; } = "<title> [<id>] - <ch# 0> - <ch title>";
|
||||||
public static IEnumerable<TagClass> TagClass { get; }
|
public static IEnumerable<TagClass> TagClass { get; } = chapterPropertyTags.Append(filePropertyTags).Append(conditionalTags);
|
||||||
= chapterPropertyTags.Append(filePropertyTags).Append(conditionalTags);
|
|
||||||
|
|
||||||
public override IEnumerable<string> Warnings
|
public override IEnumerable<string> Warnings
|
||||||
=> Template.TagsInUse.Any(t => t.TagName.In(TemplateTags.ChNumber.TagName, TemplateTags.ChNumber0.TagName))
|
=> Template.TagsInUse.Any(t => t.TagName.In(TemplateTags.ChNumber.TagName, TemplateTags.ChNumber0.TagName))
|
||||||
@ -338,8 +323,7 @@ namespace LibationFileManager
|
|||||||
public override string Name => "Chapter Title Template";
|
public override string Name => "Chapter Title Template";
|
||||||
public override string Description => Configuration.GetDescription(nameof(Configuration.ChapterTitleTemplate));
|
public override string Description => Configuration.GetDescription(nameof(Configuration.ChapterTitleTemplate));
|
||||||
public static string DefaultTemplate => "<ch#> - <title short>: <ch title>";
|
public static string DefaultTemplate => "<ch#> - <title short>: <ch title>";
|
||||||
public static IEnumerable<TagClass> TagClass { get; }
|
public static IEnumerable<TagClass> TagClass { get; } = chapterPropertyTags.Append(conditionalTags);
|
||||||
= chapterPropertyTags.Append(conditionalTags);
|
|
||||||
|
|
||||||
protected override IEnumerable<string> GetTemplatePartsStrings(List<TemplatePart> parts, ReplacementCharacters replacements)
|
protected override IEnumerable<string> GetTemplatePartsStrings(List<TemplatePart> parts, ReplacementCharacters replacements)
|
||||||
=> parts.Select(p => p.Value);
|
=> parts.Select(p => p.Value);
|
||||||
|
|||||||
@ -41,12 +41,39 @@ namespace NamingTemplateTests
|
|||||||
[TestClass]
|
[TestClass]
|
||||||
public class GetPortionFilename
|
public class GetPortionFilename
|
||||||
{
|
{
|
||||||
PropertyTagClass<PropertyClass1> props1 = new();
|
PropertyTagClass<PropertyClass1> props1 = new()
|
||||||
PropertyTagClass<PropertyClass2> props2 = new();
|
{
|
||||||
PropertyTagClass<PropertyClass3> props3 = new();
|
{ new TemplateTag { TagName = "item1" }, i => i.Item1 },
|
||||||
ConditionalTagClass<PropertyClass1> conditional1 = new();
|
{ new TemplateTag { TagName = "item2" }, i => i.Item2 },
|
||||||
ConditionalTagClass<PropertyClass2> conditional2 = new();
|
{ new TemplateTag { TagName = "item3" }, i => i.Item3 }
|
||||||
ConditionalTagClass<PropertyClass3> conditional3 = new();
|
};
|
||||||
|
|
||||||
|
PropertyTagClass<PropertyClass2> props2 = new()
|
||||||
|
{
|
||||||
|
{ new TemplateTag { TagName = "item1" }, i => i.Item1 },
|
||||||
|
{ new TemplateTag { TagName = "item2" }, i => i.Item2 },
|
||||||
|
{ new TemplateTag { TagName = "item3" }, i => i.Item3 },
|
||||||
|
{ new TemplateTag { TagName = "item4" }, i => i.Item4 },
|
||||||
|
};
|
||||||
|
PropertyTagClass<PropertyClass3> props3 = new()
|
||||||
|
{
|
||||||
|
{ new TemplateTag { TagName = "item3_1" }, i => i.Item1 },
|
||||||
|
{ new TemplateTag { TagName = "item3_2" }, i => i.Item2 },
|
||||||
|
{ new TemplateTag { TagName = "item3_3" }, i => i.Item3 },
|
||||||
|
{ new TemplateTag { TagName = "item3_4" }, i => i.Item4 },
|
||||||
|
};
|
||||||
|
ConditionalTagClass<PropertyClass1> conditional1 = new()
|
||||||
|
{
|
||||||
|
{ new TemplateTag { TagName = "ifc1" }, i => i.Condition },
|
||||||
|
};
|
||||||
|
ConditionalTagClass<PropertyClass2> conditional2 = new()
|
||||||
|
{
|
||||||
|
{ new TemplateTag { TagName = "ifc2" }, i => i.Condition },
|
||||||
|
};
|
||||||
|
ConditionalTagClass<PropertyClass3> conditional3 = new()
|
||||||
|
{
|
||||||
|
{ new TemplateTag { TagName = "ifc3" }, i => i.Condition },
|
||||||
|
};
|
||||||
|
|
||||||
PropertyClass1 propertyClass1 = new()
|
PropertyClass1 propertyClass1 = new()
|
||||||
{
|
{
|
||||||
@ -74,27 +101,6 @@ namespace NamingTemplateTests
|
|||||||
Condition = true
|
Condition = true
|
||||||
};
|
};
|
||||||
|
|
||||||
public GetPortionFilename()
|
|
||||||
{
|
|
||||||
props1.RegisterProperty(new TemplateTag { TagName = "item1" }, i => i.Item1);
|
|
||||||
props1.RegisterProperty(new TemplateTag { TagName = "item2" }, i => i.Item2);
|
|
||||||
props1.RegisterProperty(new TemplateTag { TagName = "item3" }, i => i.Item3);
|
|
||||||
|
|
||||||
props2.RegisterProperty(new TemplateTag { TagName = "item1" }, i => i.Item1);
|
|
||||||
props2.RegisterProperty(new TemplateTag { TagName = "item2" }, i => i.Item2);
|
|
||||||
props2.RegisterProperty(new TemplateTag { TagName = "item3" }, i => i.Item3);
|
|
||||||
props2.RegisterProperty(new TemplateTag { TagName = "item4" }, i => i.Item4);
|
|
||||||
|
|
||||||
props3.RegisterProperty(new TemplateTag { TagName = "item3_1" }, i => i.Item1);
|
|
||||||
props3.RegisterProperty(new TemplateTag { TagName = "item3_2" }, i => i.Item2);
|
|
||||||
props3.RegisterProperty(new TemplateTag { TagName = "item3_3" }, i => i.Item3);
|
|
||||||
props3.RegisterProperty(new TemplateTag { TagName = "item3_4" }, i => i.Item4);
|
|
||||||
|
|
||||||
conditional1.RegisterCondition(new TemplateTag { TagName = "ifc1" }, i => i.Condition);
|
|
||||||
conditional2.RegisterCondition(new TemplateTag { TagName = "ifc2" }, i => i.Condition);
|
|
||||||
conditional3.RegisterCondition(new TemplateTag { TagName = "ifc3" }, i => i.Condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[DataRow("<item1>", "prop1_item1", 1)]
|
[DataRow("<item1>", "prop1_item1", 1)]
|
||||||
@ -154,10 +160,10 @@ namespace NamingTemplateTests
|
|||||||
[DataRow("<item2_2_null[l]>", "")]
|
[DataRow("<item2_2_null[l]>", "")]
|
||||||
public void formatting(string inStr, string outStr)
|
public void formatting(string inStr, string outStr)
|
||||||
{
|
{
|
||||||
props1.RegisterProperty(new TemplateTag { TagName = "int1" }, i => i.Int1, formatInt);
|
props1.Add(new TemplateTag { TagName = "int1" }, i => i.Int1, formatInt);
|
||||||
props3.RegisterProperty(new TemplateTag { TagName = "int2" }, i => i.Int2, formatInt);
|
props3.Add(new TemplateTag { TagName = "int2" }, i => i.Int2, formatInt);
|
||||||
props3.RegisterProperty(new TemplateTag { TagName = "item3_format" }, i => i.Item3, formatString);
|
props3.Add(new TemplateTag { TagName = "item3_format" }, i => i.Item3, formatString);
|
||||||
props2.RegisterProperty(new TemplateTag { TagName = "item2_2_null" }, i => i.Item2, formatString);
|
props2.Add(new TemplateTag { TagName = "item2_2_null" }, i => i.Item2, formatString);
|
||||||
|
|
||||||
var template = NamingTemplate.Parse(inStr, new TagClass[] { props1, props2, props3, conditional1, conditional2, conditional3 });
|
var template = NamingTemplate.Parse(inStr, new TagClass[] { props1, props2, props3, conditional1, conditional2, conditional3 });
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user