Refactor Naming Template
This commit is contained in:
parent
39fe7b79d2
commit
18f69bc73d
@ -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;
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user