Refactor Naming Template

This commit is contained in:
Mbucari 2023-02-06 15:24:18 -07:00
parent 39fe7b79d2
commit 18f69bc73d
7 changed files with 91 additions and 98 deletions

View File

@ -9,14 +9,14 @@ 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(t => t).DistinctBy(t => t.TagName); public IEnumerable<ITemplateTag> TagsRegistered => TagCollections.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;
private Delegate templateToString; private Delegate templateToString;
private readonly List<string> warnings = new(); private readonly List<string> warnings = new();
private readonly List<string> errors = new(); private readonly List<string> errors = new();
private readonly IEnumerable<TagCollection> Classes; private readonly IEnumerable<TagCollection> TagCollections;
private readonly List<ITemplateTag> _tagsInUse = new(); private readonly List<ITemplateTag> _tagsInUse = new();
public const string ERROR_NULL_IS_INVALID = "Null template is invalid."; public const string ERROR_NULL_IS_INVALID = "Null template is invalid.";
@ -25,21 +25,18 @@ public class NamingTemplate
public const string WARNING_NO_TAGS = "Should use tags. Eg: <title>"; public const string WARNING_NO_TAGS = "Should use tags. Eg: <title>";
/// <summary> /// <summary>
/// Invoke the <see cref="NamingTemplate"/> to /// Invoke the <see cref="NamingTemplate"/>
/// </summary> /// </summary>
/// <param name="propertyClasses">Instances of the TClass used in <see cref="PropertyTagCollection{TClass}"/> and <see cref="ConditionalTagCollection{TClass}"/></param> /// <param name="propertyClasses">Instances of the TClass used in <see cref="PropertyTagCollection{TClass}"/> and <see cref="ConditionalTagCollection{TClass}"/></param>
/// <returns></returns>
public TemplatePart Evaluate(params object[] propertyClasses) public TemplatePart Evaluate(params object[] propertyClasses)
{ {
//Match propertyClasses to the arguments required by templateToString.DynamicInvoke() // Match propertyClasses to the arguments required by templateToString.DynamicInvoke().
var delegateArgTypes = templateToString.GetType().GenericTypeArguments[..^1]; // First parameter is "this", so ignore it.
var delegateArgTypes = templateToString.Method.GetParameters().Skip(1);
object[] args = new object[delegateArgTypes.Length]; object[] args = delegateArgTypes.Join(propertyClasses, o => o.ParameterType, i => i.GetType(), (_, i) => i).ToArray();
for (int i = 0; i < delegateArgTypes.Length; i++) if (args.Length != delegateArgTypes.Count())
args[i] = propertyClasses.First(o => o.GetType() == delegateArgTypes[i]);
if (args.Any(a => a is null))
throw new ArgumentException($"This instance of {nameof(NamingTemplate)} requires the following arguments: {string.Join(", ", delegateArgTypes.Select(t => t.Name).Distinct())}"); throw new ArgumentException($"This instance of {nameof(NamingTemplate)} requires the following arguments: {string.Join(", ", delegateArgTypes.Select(t => t.Name).Distinct())}");
return ((TemplatePart)templateToString.DynamicInvoke(args)).FirstPart; return ((TemplatePart)templateToString.DynamicInvoke(args)).FirstPart;
@ -47,22 +44,17 @@ public class NamingTemplate
/// <summary>Parse a template string to a <see cref="NamingTemplate"/></summary> /// <summary>Parse a template string to a <see cref="NamingTemplate"/></summary>
/// <param name="template">The template string to parse</param> /// <param name="template">The template string to parse</param>
/// <param name="tagClasses">A collection of <see cref="TagCollection"/> with /// <param name="tagCollections">A collection of <see cref="TagCollection"/> with
/// properties registered to match to the <paramref name="template"/></param> /// properties registered to match to the <paramref name="template"/></param>
public static NamingTemplate Parse(string template, IEnumerable<TagCollection> tagClasses) public static NamingTemplate Parse(string template, IEnumerable<TagCollection> tagCollections)
{ {
var namingTemplate = new NamingTemplate(tagClasses); var namingTemplate = new NamingTemplate(tagCollections);
try try
{ {
BinaryNode intermediate = namingTemplate.IntermediateParse(template); BinaryNode intermediate = namingTemplate.IntermediateParse(template);
Expression evalTree = GetExpressionTree(intermediate); Expression evalTree = GetExpressionTree(intermediate);
List<ParameterExpression> parameters = new(); namingTemplate.templateToString = Expression.Lambda(evalTree, tagCollections.Select(tc => tc.Parameter)).Compile();
foreach (var tagclass in tagClasses)
parameters.Add(tagclass.Parameter);
namingTemplate.templateToString = Expression.Lambda(evalTree, parameters).Compile();
} }
catch(Exception ex) catch(Exception ex)
{ {
@ -73,7 +65,7 @@ public class NamingTemplate
private NamingTemplate(IEnumerable<TagCollection> properties) private NamingTemplate(IEnumerable<TagCollection> properties)
{ {
Classes = properties; TagCollections = properties;
} }
/// <summary>Builds an <see cref="Expression"/> tree that will evaluate to a <see cref="TemplatePart"/></summary> /// <summary>Builds an <see cref="Expression"/> tree that will evaluate to a <see cref="TemplatePart"/></summary>
@ -84,7 +76,7 @@ public class NamingTemplate
else if (node.IsConditional) return Expression.Condition(node.Expression, concatExpression(node), TemplatePart.Blank); else if (node.IsConditional) return Expression.Condition(node.Expression, concatExpression(node), TemplatePart.Blank);
else return concatExpression(node); else return concatExpression(node);
Expression concatExpression(BinaryNode node) static Expression concatExpression(BinaryNode node)
=> TemplatePart.CreateConcatenation(GetExpressionTree(node.LeftChild), GetExpressionTree(node.RightChild)); => TemplatePart.CreateConcatenation(GetExpressionTree(node.LeftChild), GetExpressionTree(node.RightChild));
} }
@ -100,8 +92,8 @@ public class NamingTemplate
TemplateText = templateString; TemplateText = templateString;
BinaryNode currentNode = BinaryNode.CreateRoot(); BinaryNode topNode = BinaryNode.CreateRoot();
BinaryNode topNode = currentNode; BinaryNode currentNode = topNode;
List<char> literalChars = new(); List<char> literalChars = new();
while (templateString.Length > 0) while (templateString.Length > 0)
@ -170,7 +162,7 @@ public class NamingTemplate
{ {
if (literalChars.Count != 0) if (literalChars.Count != 0)
{ {
currentNode = currentNode.AddNewNode(BinaryNode.CreateValue(new string(literalChars.ToArray()))); currentNode = currentNode.AddNewNode(BinaryNode.CreateValue(string.Concat(literalChars)));
literalChars.Clear(); literalChars.Clear();
} }
} }
@ -178,7 +170,7 @@ public class NamingTemplate
private bool StartsWith(string template, out string exactName, out IPropertyTag propertyTag, out Expression valueExpression) private bool StartsWith(string template, out string exactName, out IPropertyTag propertyTag, out Expression valueExpression)
{ {
foreach (var pc in Classes) foreach (var pc in TagCollections)
{ {
if (pc.StartsWith(template, out exactName, out propertyTag, out valueExpression)) if (pc.StartsWith(template, out exactName, out propertyTag, out valueExpression))
return true; return true;
@ -192,7 +184,7 @@ public class NamingTemplate
private bool StartsWithClosing(string template, out string exactName, out IClosingPropertyTag closingPropertyTag) private bool StartsWithClosing(string template, out string exactName, out IClosingPropertyTag closingPropertyTag)
{ {
foreach (var pc in Classes) foreach (var pc in TagCollections)
{ {
if (pc.StartsWithClosing(template, out exactName, out closingPropertyTag)) if (pc.StartsWithClosing(template, out exactName, out closingPropertyTag))
return true; return true;

View File

@ -44,6 +44,7 @@ public class PropertyTagCollection<TClass> : TagCollection
/// <summary> /// <summary>
/// Register a nullable value type <typeparamref name="TClass"/> property. /// Register a nullable value type <typeparamref name="TClass"/> property.
/// </summary> /// </summary>
/// <typeparam name="TProperty">Type of the property from <see cref="TClass"/></typeparam>
/// <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="toString">ToString function that accepts the <typeparamref name="TProperty"/> property and returnes a string</param> /// <param name="toString">ToString function that accepts the <typeparamref name="TProperty"/> property and returnes a string</param>
public void Add<TProperty>(ITemplateTag templateTag, Func<TClass, TProperty?> propertyGetter, Func<TProperty, string> toString) public void Add<TProperty>(ITemplateTag templateTag, Func<TClass, TProperty?> propertyGetter, Func<TProperty, string> toString)
@ -64,6 +65,7 @@ public class PropertyTagCollection<TClass> : TagCollection
/// <summary> /// <summary>
/// Register a <typeparamref name="TClass"/> property. /// Register a <typeparamref name="TClass"/> property.
/// </summary> /// </summary>
/// <typeparam name="TProperty">Type of the property from <see cref="TClass"/></typeparam>
/// <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="toString">ToString function that accepts the <typeparamref name="TProperty"/> property and returnes a string</param> /// <param name="toString">ToString function that accepts the <typeparamref name="TProperty"/> property and returnes a string</param>
public void Add<TProperty>(ITemplateTag templateTag, Func<TClass, TProperty> propertyGetter, Func<TProperty, string> toString) public void Add<TProperty>(ITemplateTag templateTag, Func<TClass, TProperty> propertyGetter, Func<TProperty, string> toString)
@ -75,17 +77,26 @@ public class PropertyTagCollection<TClass> : TagCollection
ArgumentValidator.EnsureNotNull(templateTag, nameof(templateTag)); ArgumentValidator.EnsureNotNull(templateTag, nameof(templateTag));
ArgumentValidator.EnsureNotNull(propertyGetter, nameof(propertyGetter)); ArgumentValidator.EnsureNotNull(propertyGetter, nameof(propertyGetter));
formatter ??= GetDefaultFormatter<TPropertyValue>();
if (formatter is null)
RegisterWithToString<TProperty, TPropertyValue>(templateTag, propertyGetter, null);
else
{
var expr = Expression.Call(Expression.Constant(propertyGetter.Target), propertyGetter.Method, Parameter); var expr = Expression.Call(Expression.Constant(propertyGetter.Target), propertyGetter.Method, Parameter);
AddPropertyTag(PropertyTag.Create(templateTag, Options, expr, formatter));
if ((formatter ??= GetDefaultFormatter<TPropertyValue>()) is null)
AddPropertyTag(new PropertyTag<TPropertyValue>(templateTag, Options, expr, ToStringFunc));
else
AddPropertyTag(new PropertyTag<TPropertyValue>(templateTag, Options, expr, formatter));
} }
private void RegisterWithToString<TProperty, TPropertyValue>
(ITemplateTag templateTag, Func<TClass, TProperty> propertyGetter, Func<TPropertyValue, string> toString)
{
ArgumentValidator.EnsureNotNull(templateTag, nameof(templateTag));
ArgumentValidator.EnsureNotNull(propertyGetter, nameof(propertyGetter));
var expr = Expression.Call(Expression.Constant(propertyGetter.Target), propertyGetter.Method, Parameter);
AddPropertyTag(new PropertyTag<TPropertyValue>(templateTag, Options, expr, toString ?? ToStringFunc));
} }
private static string ToStringFunc<T>(T propertyValue) => propertyValue?.ToString() ?? "";
private PropertyFormatter<T> GetDefaultFormatter<T>() private PropertyFormatter<T> GetDefaultFormatter<T>()
{ {
try try
@ -93,54 +104,35 @@ public class PropertyTagCollection<TClass> : TagCollection
var del = defaultFormatters.FirstOrDefault(kvp => kvp.Key == typeof(T)).Value; var del = defaultFormatters.FirstOrDefault(kvp => kvp.Key == typeof(T)).Value;
return del is null ? null : Delegate.CreateDelegate(typeof(PropertyFormatter<T>), del.Target, del.Method) as PropertyFormatter<T>; return del is null ? null : Delegate.CreateDelegate(typeof(PropertyFormatter<T>), del.Target, del.Method) as PropertyFormatter<T>;
} }
catch catch { return null; }
{
return null;
}
} }
private void RegisterWithToString<TProperty, TPropertyValue> private class PropertyTag<TPropertyValue> : TagBase
(ITemplateTag templateTag, Func<TClass, TProperty> propertyGetter, Func<TPropertyValue, string> toString)
{ {
static string ToStringFunc(TPropertyValue value) => value?.ToString() ?? ""; private Func<Expression, string, Expression> CreateToStringExpression { get; }
ArgumentValidator.EnsureNotNull(templateTag, nameof(templateTag));
ArgumentValidator.EnsureNotNull(propertyGetter, nameof(propertyGetter));
var expr = Expression.Call(Expression.Constant(propertyGetter.Target), propertyGetter.Method, Parameter); public PropertyTag(ITemplateTag templateTag, RegexOptions options, Expression propertyGetter, PropertyFormatter<TPropertyValue> formatter)
AddPropertyTag(PropertyTag.Create(templateTag, Options, expr, toString ?? ToStringFunc)); : base(templateTag, propertyGetter)
}
private class PropertyTag : TagBase
{ {
private Func<Expression, string, Expression> CreateToStringExpression { get; init; } NameMatcher = new Regex(@$"^<{templateTag.TagName.Replace(" ", "\\s*?")}\s*?(?:\[([^\[\]]*?)\]\s*?)?>", options);
private PropertyTag(ITemplateTag templateTag, Expression propertyGetter) : base(templateTag, propertyGetter) { }
public static PropertyTag Create<TPropertyValue>(ITemplateTag templateTag, RegexOptions options, Expression propertyGetter, PropertyFormatter<TPropertyValue> formatter)
{
return new PropertyTag(templateTag, propertyGetter)
{
NameMatcher = new Regex(@$"^<{templateTag.TagName.Replace(" ", "\\s*?")}\s*?(?:\[([^\[\]]*?)\]\s*?)?>", options),
CreateToStringExpression = (expVal, format) => CreateToStringExpression = (expVal, format) =>
Expression.Call( Expression.Call(
formatter.Target is null ? null : Expression.Constant(formatter.Target), formatter.Target is null ? null : Expression.Constant(formatter.Target),
formatter.Method, formatter.Method,
Expression.Constant(templateTag), Expression.Constant(templateTag),
expVal, expVal,
Expression.Constant(format)) Expression.Constant(format));
};
} }
public static PropertyTag Create<TPropertyValue>(ITemplateTag templateTag, RegexOptions options, Expression propertyGetter, Func<TPropertyValue, string> toString) public PropertyTag(ITemplateTag templateTag, RegexOptions options, Expression propertyGetter, Func<TPropertyValue, string> toString)
: base(templateTag, propertyGetter)
{ {
return new PropertyTag(templateTag, propertyGetter) NameMatcher = new Regex(@$"^<{templateTag.TagName.Replace(" ", "\\s*?")}>", options);
{
NameMatcher = new Regex(@$"^<{templateTag.TagName}>", options),
CreateToStringExpression = (expVal, _) => CreateToStringExpression = (expVal, _) =>
Expression.Call( Expression.Call(
toString.Target is null ? null : Expression.Constant(toString.Target), toString.Target is null ? null : Expression.Constant(toString.Target),
toString.Method, toString.Method,
expVal) expVal);
};
} }
protected override Expression GetTagExpression(string exactName, string formatString) protected override Expression GetTagExpression(string exactName, string formatString)

View File

@ -29,7 +29,7 @@ namespace LibationAvalonia.Dialogs
var editor = TemplateEditor<Templates.FileTemplate>.CreateFilenameEditor(Configuration.Instance.Books, Configuration.Instance.FileTemplate); var editor = TemplateEditor<Templates.FileTemplate>.CreateFilenameEditor(Configuration.Instance.Books, Configuration.Instance.FileTemplate);
_viewModel = new(Configuration.Instance, editor); _viewModel = new(Configuration.Instance, editor);
_viewModel.resetTextBox(editor.EditingTemplate.TemplateText); _viewModel.resetTextBox(editor.EditingTemplate.TemplateText);
Title = $"Edit {editor.EditingTemplate.Name}"; Title = $"Edit {editor.TemplateName}";
DataContext = _viewModel; DataContext = _viewModel;
} }
} }
@ -40,7 +40,7 @@ namespace LibationAvalonia.Dialogs
_viewModel = new EditTemplateViewModel(Configuration.Instance, templateEditor); _viewModel = new EditTemplateViewModel(Configuration.Instance, templateEditor);
_viewModel.resetTextBox(templateEditor.EditingTemplate.TemplateText); _viewModel.resetTextBox(templateEditor.EditingTemplate.TemplateText);
Title = $"Edit {templateEditor.EditingTemplate.Name}"; Title = $"Edit {templateEditor.TemplateName}";
DataContext = _viewModel; DataContext = _viewModel;
} }
@ -82,7 +82,7 @@ namespace LibationAvalonia.Dialogs
{ {
config = configuration; config = configuration;
TemplateEditor = templates; TemplateEditor = templates;
Description = templates.EditingTemplate.Description; Description = templates.TemplateDescription;
ListItems ListItems
= new AvaloniaList<Tuple<string, string, string>>( = new AvaloniaList<Tuple<string, string, string>>(
TemplateEditor TemplateEditor

View File

@ -12,6 +12,8 @@ namespace LibationFileManager
bool IsFilePath { get; } bool IsFilePath { get; }
LongPath BaseDirectory { get; } LongPath BaseDirectory { get; }
string DefaultTemplate { get; } string DefaultTemplate { get; }
string TemplateName { get; }
string TemplateDescription { get; }
Templates Folder { get; } Templates Folder { get; }
Templates File { get; } Templates File { get; }
Templates Name { get; } Templates Name { get; }
@ -28,6 +30,8 @@ namespace LibationFileManager
public bool IsFilePath => EditingTemplate is not Templates.ChapterTitleTemplate; public bool IsFilePath => EditingTemplate is not Templates.ChapterTitleTemplate;
public LongPath BaseDirectory { get; private init; } public LongPath BaseDirectory { get; private init; }
public string DefaultTemplate { get; private init; } public string DefaultTemplate { get; private init; }
public string TemplateName { get; private init; }
public string TemplateDescription { get; private init; }
public Templates Folder { get; private set; } public Templates Folder { get; private set; }
public Templates File { get; private set; } public Templates File { get; private set; }
public Templates Name { get; private set; } public Templates Name { get; private set; }
@ -99,7 +103,10 @@ namespace LibationFileManager
{ {
_editingTemplate = template, _editingTemplate = template,
BaseDirectory = baseDir, BaseDirectory = baseDir,
DefaultTemplate = T.DefaultTemplate DefaultTemplate = T.DefaultTemplate,
TemplateName = T.Name,
TemplateDescription = T.Description
}; };
if (!templateEditor.IsFolder && !templateEditor.IsFilePath) if (!templateEditor.IsFolder && !templateEditor.IsFilePath)
@ -118,7 +125,9 @@ namespace LibationFileManager
var templateEditor = new TemplateEditor<T> var templateEditor = new TemplateEditor<T>
{ {
_editingTemplate = nameTemplate, _editingTemplate = nameTemplate,
DefaultTemplate = T.DefaultTemplate DefaultTemplate = T.DefaultTemplate,
TemplateName = T.Name,
TemplateDescription = T.Description
}; };
if (templateEditor.IsFolder || templateEditor.IsFilePath) if (templateEditor.IsFolder || templateEditor.IsFilePath)

View File

@ -11,6 +11,8 @@ namespace LibationFileManager
{ {
public interface ITemplate public interface ITemplate
{ {
static abstract string Name { get; }
static abstract string Description { get; }
static abstract string DefaultTemplate { get; } static abstract string DefaultTemplate { get; }
static abstract IEnumerable<TagCollection> TagCollections { get; } static abstract IEnumerable<TagCollection> TagCollections { get; }
} }
@ -42,12 +44,12 @@ namespace LibationFileManager
{ {
var namingTemplate = NamingTemplate.Parse(templateText, T.TagCollections); var namingTemplate = NamingTemplate.Parse(templateText, T.TagCollections);
template = new() { Template = namingTemplate }; template = new() { NamingTemplate = namingTemplate };
return !namingTemplate.Errors.Any(); return !namingTemplate.Errors.Any();
} }
private static T GetDefaultTemplate<T>() where T : Templates, ITemplate, new() private static T GetDefaultTemplate<T>() where T : Templates, ITemplate, new()
=> new() { Template = NamingTemplate.Parse(T.DefaultTemplate, T.TagCollections) }; => new() { NamingTemplate = NamingTemplate.Parse(T.DefaultTemplate, T.TagCollections) };
static Templates() static Templates()
{ {
@ -72,21 +74,19 @@ namespace LibationFileManager
#region Template Properties #region Template Properties
public IEnumerable<TemplateTags> TagsRegistered => Template.TagsRegistered.Cast<TemplateTags>(); public IEnumerable<TemplateTags> TagsRegistered => NamingTemplate.TagsRegistered.Cast<TemplateTags>();
public IEnumerable<TemplateTags> TagsInUse => Template.TagsInUse.Cast<TemplateTags>(); public IEnumerable<TemplateTags> TagsInUse => NamingTemplate.TagsInUse.Cast<TemplateTags>();
public abstract string Name { get; } public string TemplateText => NamingTemplate.TemplateText;
public abstract string Description { get; } protected NamingTemplate NamingTemplate { get; private set; }
public string TemplateText => Template.TemplateText;
protected NamingTemplate Template { get; private set; }
#endregion #endregion
#region validation #region validation
public virtual IEnumerable<string> Errors => Template.Errors; public virtual IEnumerable<string> Errors => NamingTemplate.Errors;
public bool IsValid => !Errors.Any(); public bool IsValid => !Errors.Any();
public virtual IEnumerable<string> Warnings => Template.Warnings; public virtual IEnumerable<string> Warnings => NamingTemplate.Warnings;
public bool HasWarnings => Warnings.Any(); public bool HasWarnings => Warnings.Any();
#endregion #endregion
@ -97,7 +97,7 @@ namespace LibationFileManager
{ {
ArgumentValidator.EnsureNotNull(libraryBookDto, nameof(libraryBookDto)); ArgumentValidator.EnsureNotNull(libraryBookDto, nameof(libraryBookDto));
ArgumentValidator.EnsureNotNull(multiChapProps, nameof(multiChapProps)); ArgumentValidator.EnsureNotNull(multiChapProps, nameof(multiChapProps));
return string.Join("", Template.Evaluate(libraryBookDto, multiChapProps).Select(p => p.Value)); return string.Concat(NamingTemplate.Evaluate(libraryBookDto, multiChapProps).Select(p => p.Value));
} }
public LongPath GetFilename(LibraryBookDto libraryBookDto, string baseDir, string fileExtension, ReplacementCharacters replacements = null, bool returnFirstExisting = false) public LongPath GetFilename(LibraryBookDto libraryBookDto, string baseDir, string fileExtension, ReplacementCharacters replacements = null, bool returnFirstExisting = false)
@ -128,7 +128,7 @@ namespace LibationFileManager
{ {
fileExtension = FileUtility.GetStandardizedExtension(fileExtension); fileExtension = FileUtility.GetStandardizedExtension(fileExtension);
var parts = Template.Evaluate(dtos).ToList(); var parts = NamingTemplate.Evaluate(dtos).ToList();
var pathParts = GetPathParts(GetTemplatePartsStrings(parts, replacements)); var pathParts = GetPathParts(GetTemplatePartsStrings(parts, replacements));
//Remove 1 character from the end of the longest filename part until //Remove 1 character from the end of the longest filename part until
@ -154,7 +154,7 @@ namespace LibationFileManager
} }
} }
var fullPath = Path.Combine(pathParts.Select(fileParts => string.Join("", fileParts)).Prepend(baseDir).ToArray()); var fullPath = Path.Combine(pathParts.Select(fileParts => string.Concat(fileParts)).Prepend(baseDir).ToArray());
return FileUtility.GetValidFilename(fullPath, replacements, fileExtension, returnFirstExisting); return FileUtility.GetValidFilename(fullPath, replacements, fileExtension, returnFirstExisting);
} }
@ -286,8 +286,8 @@ namespace LibationFileManager
public class FolderTemplate : Templates, ITemplate public class FolderTemplate : Templates, ITemplate
{ {
public override string Name => "Folder Template"; public static string Name { get; }= "Folder Template";
public override string Description => Configuration.GetDescription(nameof(Configuration.FolderTemplate)); public static string Description { get; } = Configuration.GetDescription(nameof(Configuration.FolderTemplate));
public static string DefaultTemplate { get; } = "<title short> [<id>]"; public static string DefaultTemplate { get; } = "<title short> [<id>]";
public static IEnumerable<TagCollection> TagCollections => new TagCollection[] { filePropertyTags, conditionalTags }; public static IEnumerable<TagCollection> TagCollections => new TagCollection[] { filePropertyTags, conditionalTags };
@ -305,29 +305,29 @@ namespace LibationFileManager
public class FileTemplate : Templates, ITemplate public class FileTemplate : Templates, ITemplate
{ {
public override string Name => "File Template"; public static string Name { get; } = "File Template";
public override string Description => Configuration.GetDescription(nameof(Configuration.FileTemplate)); public static string Description { get; } = Configuration.GetDescription(nameof(Configuration.FileTemplate));
public static string DefaultTemplate { get; } = "<title> [<id>]"; public static string DefaultTemplate { get; } = "<title> [<id>]";
public static IEnumerable<TagCollection> TagCollections { get; } = new TagCollection[] { filePropertyTags, conditionalTags }; public static IEnumerable<TagCollection> TagCollections { get; } = new TagCollection[] { filePropertyTags, conditionalTags };
} }
public class ChapterFileTemplate : Templates, ITemplate public class ChapterFileTemplate : Templates, ITemplate
{ {
public override string Name => "Chapter File Template"; public static string Name { get; } = "Chapter File Template";
public override string Description => Configuration.GetDescription(nameof(Configuration.ChapterFileTemplate)); public static string Description { get; } = 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<TagCollection> TagCollections { get; } = chapterPropertyTags.Append(filePropertyTags).Append(conditionalTags); public static IEnumerable<TagCollection> TagCollections { get; } = 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)) => NamingTemplate.TagsInUse.Any(t => t.TagName.In(TemplateTags.ChNumber.TagName, TemplateTags.ChNumber0.TagName))
? base.Warnings ? base.Warnings
: base.Warnings.Append(WARNING_NO_CHAPTER_NUMBER_TAG); : base.Warnings.Append(WARNING_NO_CHAPTER_NUMBER_TAG);
} }
public class ChapterTitleTemplate : Templates, ITemplate public class ChapterTitleTemplate : Templates, ITemplate
{ {
public override string Name => "Chapter Title Template"; public static string Name { get; } = "Chapter Title Template";
public override string Description => Configuration.GetDescription(nameof(Configuration.ChapterTitleTemplate)); public static string Description { get; } = 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<TagCollection> TagCollections { get; } = chapterPropertyTags.Append(conditionalTags); public static IEnumerable<TagCollection> TagCollections { get; } = chapterPropertyTags.Append(conditionalTags);

View File

@ -37,9 +37,9 @@ namespace LibationWinForms.Dialogs
warningsLbl.Text = ""; warningsLbl.Text = "";
this.Text = $"Edit {templateEditor.EditingTemplate.Name}"; this.Text = $"Edit {templateEditor.TemplateName}";
this.templateLbl.Text = templateEditor.EditingTemplate.Description; this.templateLbl.Text = templateEditor.TemplateDescription;
resetTextBox(templateEditor.EditingTemplate.TemplateText); resetTextBox(templateEditor.EditingTemplate.TemplateText);
// populate list view // populate list view

View File

@ -131,7 +131,7 @@ namespace NamingTemplateTests
template.Warnings.Should().HaveCount(numTags > 0 ? 0 : 1); template.Warnings.Should().HaveCount(numTags > 0 ? 0 : 1);
template.Errors.Should().HaveCount(0); template.Errors.Should().HaveCount(0);
var templateText = string.Join("", template.Evaluate(propertyClass3, propertyClass2, propertyClass1).Select(v => v.Value)); var templateText = string.Concat(template.Evaluate(propertyClass3, propertyClass2, propertyClass1).Select(v => v.Value));
templateText.Should().Be(outStr); templateText.Should().Be(outStr);
} }
@ -186,7 +186,7 @@ namespace NamingTemplateTests
template.Warnings.Should().HaveCount(0); template.Warnings.Should().HaveCount(0);
template.Errors.Should().HaveCount(0); template.Errors.Should().HaveCount(0);
var templateText = string.Join("", template.Evaluate(propertyClass3, propertyClass2, propertyClass1).Select(v => v.Value)); var templateText = string.Concat(template.Evaluate(propertyClass3, propertyClass2, propertyClass1).Select(v => v.Value));
templateText.Should().Be(outStr); templateText.Should().Be(outStr);