Date format naming templates
This commit is contained in:
parent
9309aea6d9
commit
3479dbc3f0
@ -10,6 +10,6 @@ namespace AaxDecrypter
|
||||
public int PartsPosition { get; set; }
|
||||
public int PartsTotal { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
public DateTime FileDate { get; } = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,11 +27,13 @@ namespace FileLiberator
|
||||
public static LibraryBookDto ToDto(this LibraryBook libraryBook) => new()
|
||||
{
|
||||
Account = libraryBook.Account,
|
||||
DateAdded = libraryBook.DateAdded,
|
||||
|
||||
AudibleProductId = libraryBook.Book.AudibleProductId,
|
||||
Title = libraryBook.Book.Title ?? "",
|
||||
Locale = libraryBook.Book.Locale,
|
||||
YearPublished = libraryBook.Book.DatePublished?.Year,
|
||||
DatePublished = libraryBook.Book.DatePublished,
|
||||
|
||||
Authors = libraryBook.Book.Authors.Select(c => c.Name).ToList(),
|
||||
|
||||
|
||||
@ -9,11 +9,15 @@ namespace FileManager
|
||||
/// <summary>Get valid filename. Advanced features incl. parameterized template</summary>
|
||||
public class FileNamingTemplate : NamingTemplate
|
||||
{
|
||||
public ReplacementCharacters ReplacementCharacters { get; }
|
||||
/// <param name="template">Proposed file name with optional html-styled template tags.</param>
|
||||
public FileNamingTemplate(string template) : base(template) { }
|
||||
public FileNamingTemplate(string template, ReplacementCharacters replacement) : base(template)
|
||||
{
|
||||
ReplacementCharacters = replacement ?? ReplacementCharacters.Default;
|
||||
}
|
||||
|
||||
/// <summary>Generate a valid path for this file or directory</summary>
|
||||
public LongPath GetFilePath(ReplacementCharacters replacements, string fileExtension, bool returnFirstExisting = false)
|
||||
public LongPath GetFilePath(string fileExtension, bool returnFirstExisting = false)
|
||||
{
|
||||
string fileName =
|
||||
Template.EndsWith(Path.DirectorySeparatorChar) || Template.EndsWith(Path.AltDirectorySeparatorChar) ?
|
||||
@ -22,7 +26,7 @@ namespace FileManager
|
||||
|
||||
List<string> pathParts = new();
|
||||
|
||||
var paramReplacements = ParameterReplacements.ToDictionary(r => $"<{formatKey(r.Key)}>", r => formatValue(r.Value, replacements));
|
||||
var paramReplacements = ParameterReplacements.ToDictionary(r => $"<{formatKey(r.Key)}>", r => formatValue(r.Value, ReplacementCharacters));
|
||||
|
||||
while (!string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
@ -54,7 +58,7 @@ namespace FileManager
|
||||
return FileUtility
|
||||
.GetValidFilename(
|
||||
Path.Join(directory, replaceFileName(fileNamePart, paramReplacements, LongPath.MaxFilenameLength - fileExtension.Length - 5)) + fileExtension,
|
||||
replacements,
|
||||
ReplacementCharacters,
|
||||
fileExtension,
|
||||
returnFirstExisting
|
||||
);
|
||||
|
||||
@ -50,7 +50,9 @@ namespace LibationAvalonia.Dialogs
|
||||
{
|
||||
var dataGrid = sender as DataGrid;
|
||||
|
||||
var item = (dataGrid.SelectedItem as Tuple<string, string>).Item1.Replace("\x200C", "").Replace("...", "");
|
||||
var item = (dataGrid.SelectedItem as Tuple<string, string, string>).Item3;
|
||||
if (string.IsNullOrWhiteSpace(item)) return;
|
||||
|
||||
var text = userEditTbox.Text;
|
||||
|
||||
userEditTbox.Text = text.Insert(Math.Min(Math.Max(0, userEditTbox.CaretIndex), text.Length), item);
|
||||
@ -84,13 +86,14 @@ namespace LibationAvalonia.Dialogs
|
||||
Template = templates;
|
||||
Description = templates.Description;
|
||||
ListItems
|
||||
= new AvaloniaList<Tuple<string, string>>(
|
||||
= new AvaloniaList<Tuple<string, string, string>>(
|
||||
Template
|
||||
.GetTemplateTags()
|
||||
.Select(
|
||||
t => new Tuple<string, string>(
|
||||
t => new Tuple<string, string, string>(
|
||||
$"<{t.TagName.Replace("->", "-\x200C>").Replace("<-", "<\x200C-")}>",
|
||||
t.Description)
|
||||
t.Description,
|
||||
t.DefaultValue)
|
||||
)
|
||||
);
|
||||
|
||||
@ -108,13 +111,13 @@ namespace LibationAvalonia.Dialogs
|
||||
}
|
||||
}
|
||||
|
||||
public string workingTemplateText => Template.Sanitize(UserTemplateText);
|
||||
public string workingTemplateText => Template.Sanitize(UserTemplateText, Configuration.Instance.ReplacementCharacters);
|
||||
private string _warningText;
|
||||
public string WarningText { get => _warningText; set => this.RaiseAndSetIfChanged(ref _warningText, value); }
|
||||
|
||||
public string Description { get; }
|
||||
|
||||
public AvaloniaList<Tuple<string, string>> ListItems { get; set; }
|
||||
public AvaloniaList<Tuple<string, string, string>> ListItems { get; set; }
|
||||
|
||||
public void resetTextBox(string value) => UserTemplateText = value;
|
||||
|
||||
@ -138,6 +141,8 @@ namespace LibationAvalonia.Dialogs
|
||||
var libraryBookDto = new LibraryBookDto
|
||||
{
|
||||
Account = "my account",
|
||||
DateAdded = new DateTime(2022, 6, 9, 0, 0, 0),
|
||||
DatePublished = new DateTime(2017, 2, 27, 0, 0, 0),
|
||||
AudibleProductId = "123456789",
|
||||
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
|
||||
Locale = "us",
|
||||
|
||||
@ -25,10 +25,14 @@ namespace LibationFileManager
|
||||
public int BitRate { get; set; }
|
||||
public int SampleRate { get; set; }
|
||||
public int Channels { get; set; }
|
||||
}
|
||||
public DateTime FileDate { get; set; } = DateTime.Now;
|
||||
public DateTime? DatePublished { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class LibraryBookDto : BookDto
|
||||
{
|
||||
public string Account { get; set; }
|
||||
{
|
||||
public DateTime? DateAdded { get; set; }
|
||||
public string Account { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,16 +7,19 @@ namespace LibationFileManager
|
||||
{
|
||||
public sealed class TemplateTags : Enumeration<TemplateTags>
|
||||
{
|
||||
public string TagName => DisplayName;
|
||||
public string TagName => DisplayName;
|
||||
public string DefaultValue { get; }
|
||||
public string Description { get; }
|
||||
public bool IsChapterOnly { get; }
|
||||
|
||||
private static int value = 0;
|
||||
private TemplateTags(string tagName, string description, bool isChapterOnly = false) : base(value++, tagName)
|
||||
private TemplateTags(string tagName, string description, bool isChapterOnly = false, string defaultValue = null) : base(value++, tagName)
|
||||
{
|
||||
Description = description;
|
||||
IsChapterOnly = isChapterOnly;
|
||||
}
|
||||
DefaultValue = defaultValue ?? $"<{tagName}>";
|
||||
|
||||
}
|
||||
|
||||
// putting these first is the incredibly lazy way to make them show up first in the EditTemplateDialog
|
||||
public static TemplateTags ChCount { get; } = new TemplateTags("ch count", "Number of chapters", true);
|
||||
@ -43,7 +46,9 @@ namespace LibationFileManager
|
||||
|
||||
// Special cases. Aren't mapped to replacements in Templates.cs
|
||||
// Included here for display by EditTemplateDialog
|
||||
public static TemplateTags Date { get; } = new TemplateTags("date[...]", "File date/time. e.g. yyyy-MM-dd HH-mm");
|
||||
public static TemplateTags IfSeries { get; } = new TemplateTags("if series->...<-if series", "Only include if part of a series");
|
||||
public static TemplateTags FileDate { get; } = new TemplateTags("file date [...]", "File date/time. e.g. yyyy-MM-dd HH-mm", false, $"<file date [{Templates.DEFAULT_DATE_FORMAT}]>");
|
||||
public static TemplateTags DatePublished { get; } = new TemplateTags("pub date [...]", "Publication date. e.g. yyyy-MM-dd", false, $"<pub date [{Templates.DEFAULT_DATE_FORMAT}]>");
|
||||
public static TemplateTags DateAdded { get; } = new TemplateTags("date added [...]", "Date added to you Audible account. e.g. yyyy-MM-dd", false, $"<date added [{Templates.DEFAULT_DATE_FORMAT}]>");
|
||||
public static TemplateTags IfSeries { get; } = new TemplateTags("if series->...<-if series", "Only include if part of a series", false, "<if series-><-if series>");
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Dinah.Core;
|
||||
using Dinah.Core.Collections.Generic;
|
||||
using FileManager;
|
||||
|
||||
namespace LibationFileManager
|
||||
@ -102,17 +103,21 @@ namespace LibationFileManager
|
||||
public string GetPortionFilename(LibraryBookDto libraryBookDto, string template, string fileExtension)
|
||||
=> string.IsNullOrWhiteSpace(template)
|
||||
? ""
|
||||
: getFileNamingTemplate(libraryBookDto, template, null, fileExtension)
|
||||
.GetFilePath(Configuration.Instance.ReplacementCharacters, fileExtension).PathWithoutPrefix;
|
||||
: getFileNamingTemplate(libraryBookDto, template, null, fileExtension, Configuration.Instance.ReplacementCharacters)
|
||||
.GetFilePath(fileExtension).PathWithoutPrefix;
|
||||
|
||||
private static Regex dateFormatRegex { get; } = new Regex(@"<date\[(.*?)\]>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public const string DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
|
||||
private static Regex fileDateTagRegex { get; } = new Regex(@"<file\s*?date\s*?(?:\s*?|\[(.*?)\])\s*?>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private static Regex dateAddedTagRegex { get; } = new Regex(@"<date\s*?added\s*?(?:\s*?|\[(.*?)\])\s*?>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private static Regex datePublishedTagRegex { get; } = new Regex(@"<pub\s*?date\s*?(?:\s*?|\[(.*?)\])\s*?>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private static Regex ifSeriesRegex { get; } = new Regex("<if series->(.*?)<-if series>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
internal static FileNamingTemplate getFileNamingTemplate(LibraryBookDto libraryBookDto, string template, string dirFullPath, string extension)
|
||||
internal static FileNamingTemplate getFileNamingTemplate(LibraryBookDto libraryBookDto, string template, string dirFullPath, string extension, ReplacementCharacters replacements)
|
||||
{
|
||||
ArgumentValidator.EnsureNotNullOrWhiteSpace(template, nameof(template));
|
||||
ArgumentValidator.EnsureNotNull(libraryBookDto, nameof(libraryBookDto));
|
||||
|
||||
replacements ??= Configuration.Instance.ReplacementCharacters;
|
||||
dirFullPath = dirFullPath?.Trim() ?? "";
|
||||
|
||||
// for non-series, remove <if series-> and <-if series> tags and everything in between
|
||||
@ -121,12 +126,16 @@ namespace LibationFileManager
|
||||
template,
|
||||
string.IsNullOrWhiteSpace(libraryBookDto.SeriesName) ? "" : "$1");
|
||||
|
||||
template = dateFormatRegex.Replace(template, dateMatchEvaluator);
|
||||
//Get date replacement parameters. Sanitizes the format text and replaces
|
||||
//the template with the sanitized text before creating FileNamingTemplate
|
||||
var fileDateParams = getSanitizeDateReplacementParameters(fileDateTagRegex, ref template, replacements, libraryBookDto.FileDate);
|
||||
var dateAddedParams = getSanitizeDateReplacementParameters(dateAddedTagRegex, ref template, replacements, libraryBookDto.DateAdded);
|
||||
var pubDateParams = getSanitizeDateReplacementParameters(datePublishedTagRegex, ref template, replacements, libraryBookDto.DatePublished);
|
||||
|
||||
var t = template + FileUtility.GetStandardizedExtension(extension);
|
||||
var fullfilename = dirFullPath == "" ? t : Path.Combine(dirFullPath, t);
|
||||
|
||||
var fileNamingTemplate = new FileNamingTemplate(fullfilename);
|
||||
var fileNamingTemplate = new FileNamingTemplate(fullfilename, replacements);
|
||||
|
||||
var title = libraryBookDto.Title ?? "";
|
||||
var titleShort = title.IndexOf(':') < 1 ? title : title.Substring(0, title.IndexOf(':'));
|
||||
@ -147,31 +156,92 @@ namespace LibationFileManager
|
||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.Locale, libraryBookDto.Locale);
|
||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.YearPublished, libraryBookDto.YearPublished?.ToString() ?? "1900");
|
||||
|
||||
return fileNamingTemplate;
|
||||
//Add the sanitized replacement parameters
|
||||
foreach (var param in fileDateParams)
|
||||
fileNamingTemplate.ParameterReplacements.AddIfNotContains(param);
|
||||
foreach (var param in dateAddedParams)
|
||||
fileNamingTemplate.ParameterReplacements.AddIfNotContains(param);
|
||||
foreach (var param in pubDateParams)
|
||||
fileNamingTemplate.ParameterReplacements.AddIfNotContains(param);
|
||||
|
||||
return fileNamingTemplate;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static string dateMatchEvaluator(Match match)
|
||||
#region DateTime Tags
|
||||
|
||||
/// <param name="template">the file naming template. Any found date tags will be sanitized,
|
||||
/// and the template's original date tag will be replaced with the sanitized tag.</param>
|
||||
/// <returns>A list of parameter replacement key-value pairs</returns>
|
||||
private static List<KeyValuePair<string, object>> getSanitizeDateReplacementParameters(Regex datePattern, ref string template, ReplacementCharacters replacements, DateTime? dateTime)
|
||||
{
|
||||
List<KeyValuePair<string, object>> dateParams = new();
|
||||
|
||||
foreach (Match dateTag in datePattern.Matches(template))
|
||||
{
|
||||
var sanitizedTag = sanitizeDateParameterTag(dateTag, replacements, out var sanitizedFormatter);
|
||||
if (tryFormatDateTime(dateTime, sanitizedFormatter, replacements, out var formattedDateString))
|
||||
{
|
||||
dateParams.Add(new(sanitizedTag, formattedDateString));
|
||||
template = template.Replace(dateTag.Value, sanitizedTag);
|
||||
}
|
||||
}
|
||||
return dateParams;
|
||||
}
|
||||
|
||||
/// <returns>a date parameter replacement tag with the format string sanitized</returns>
|
||||
private static string sanitizeDateParameterTag(Match dateTag, ReplacementCharacters replacements, out string sanitizedFormatter)
|
||||
{
|
||||
if (dateTag.Groups.Count < 2 || string.IsNullOrWhiteSpace(dateTag.Groups[1].Value))
|
||||
{
|
||||
sanitizedFormatter = DEFAULT_DATE_FORMAT;
|
||||
return dateTag.Value;
|
||||
}
|
||||
|
||||
var formatter = dateTag.Groups[1].Value;
|
||||
|
||||
sanitizedFormatter = replacements.ReplaceFilenameChars(formatter).Trim();
|
||||
|
||||
return dateTag.Value.Replace(formatter, sanitizedFormatter);
|
||||
}
|
||||
|
||||
private static bool tryFormatDateTime(DateTime? dateTime, string sanitizedFormatter, ReplacementCharacters replacements, out string formattedDateString)
|
||||
{
|
||||
if (!dateTime.HasValue)
|
||||
{
|
||||
formattedDateString = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return DateTime.Now.ToString(match.Groups[1].Value);
|
||||
formattedDateString = replacements.ReplaceFilenameChars(dateTime.Value.ToString(sanitizedFormatter)).Trim();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return match.Value;
|
||||
formattedDateString = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public virtual IEnumerable<TemplateTags> GetTemplateTags()
|
||||
=> TemplateTags.GetAll()
|
||||
// yeah, this line is a little funky but it works when you think through it. also: trust the unit tests
|
||||
.Where(t => IsChapterized || !t.IsChapterOnly);
|
||||
|
||||
public string Sanitize(string template)
|
||||
public string Sanitize(string template, ReplacementCharacters replacements)
|
||||
{
|
||||
var value = template ?? "";
|
||||
|
||||
// Replace invalid filename characters in the DateTime format provider so we don't trip any alarms.
|
||||
// Illegal filename characters in the formatter are allowed because they will be replaced by
|
||||
// getFileNamingTemplate()
|
||||
value = fileDateTagRegex.Replace(value, m => sanitizeDateParameterTag(m, replacements, out _));
|
||||
value = dateAddedTagRegex.Replace(value, m => sanitizeDateParameterTag(m, replacements, out _));
|
||||
value = datePublishedTagRegex.Replace(value, m => sanitizeDateParameterTag(m, replacements, out _));
|
||||
|
||||
// don't use alt slash
|
||||
value = value.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
@ -218,7 +288,7 @@ namespace LibationFileManager
|
||||
|
||||
// must be relative. no colons. all other path chars are valid enough to pass this check and will be handled on final save.
|
||||
if (ReplacementCharacters.ContainsInvalidPathChar(template.Replace("<", "").Replace(">", "")))
|
||||
return new[] { ERROR_INVALID_FILE_NAME_CHAR };
|
||||
return new[] { ERROR_INVALID_FILE_NAME_CHAR };
|
||||
|
||||
return Valid;
|
||||
}
|
||||
@ -229,8 +299,8 @@ namespace LibationFileManager
|
||||
#region to file name
|
||||
/// <summary>USES LIVE CONFIGURATION VALUES</summary>
|
||||
public string GetFilename(LibraryBookDto libraryBookDto, string baseDir = null)
|
||||
=> getFileNamingTemplate(libraryBookDto, Configuration.Instance.FolderTemplate, baseDir ?? AudibleFileStorage.BooksDirectory, null)
|
||||
.GetFilePath(Configuration.Instance.ReplacementCharacters, string.Empty);
|
||||
=> getFileNamingTemplate(libraryBookDto, Configuration.Instance.FolderTemplate, baseDir ?? AudibleFileStorage.BooksDirectory, null, Configuration.Instance.ReplacementCharacters)
|
||||
.GetFilePath(string.Empty);
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -252,8 +322,8 @@ namespace LibationFileManager
|
||||
#region to file name
|
||||
/// <summary>USES LIVE CONFIGURATION VALUES</summary>
|
||||
public string GetFilename(LibraryBookDto libraryBookDto, string dirFullPath, string extension, bool returnFirstExisting = false)
|
||||
=> getFileNamingTemplate(libraryBookDto, Configuration.Instance.FileTemplate, dirFullPath, extension)
|
||||
.GetFilePath(Configuration.Instance.ReplacementCharacters, extension, returnFirstExisting);
|
||||
=> getFileNamingTemplate(libraryBookDto, Configuration.Instance.FileTemplate, dirFullPath, extension, Configuration.Instance.ReplacementCharacters)
|
||||
.GetFilePath(extension, returnFirstExisting);
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -294,14 +364,21 @@ namespace LibationFileManager
|
||||
|
||||
replacements ??= Configuration.Instance.ReplacementCharacters;
|
||||
var fileExtension = Path.GetExtension(props.OutputFileName);
|
||||
var fileNamingTemplate = getFileNamingTemplate(libraryBookDto, template, fullDirPath, fileExtension);
|
||||
var fileNamingTemplate = getFileNamingTemplate(libraryBookDto, template, fullDirPath, fileExtension, replacements);
|
||||
|
||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChCount, props.PartsTotal);
|
||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChNumber, props.PartsPosition);
|
||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChNumber0, FileUtility.GetSequenceFormatted(props.PartsPosition, props.PartsTotal));
|
||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChTitle, props.Title ?? "");
|
||||
|
||||
return fileNamingTemplate.GetFilePath(replacements, fileExtension).PathWithoutPrefix;
|
||||
foreach (Match dateTag in fileDateTagRegex.Matches(fileNamingTemplate.Template))
|
||||
{
|
||||
var sanitizedTag = sanitizeDateParameterTag(dateTag, replacements, out string sanitizedFormatter);
|
||||
if (tryFormatDateTime(props.FileDate, sanitizedFormatter, replacements, out var formattedDateString))
|
||||
fileNamingTemplate.ParameterReplacements[sanitizedTag] = formattedDateString;
|
||||
}
|
||||
|
||||
return fileNamingTemplate.GetFilePath(fileExtension).PathWithoutPrefix;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -9,5 +9,8 @@ namespace LibationFileManager
|
||||
{
|
||||
public static void AddParameterReplacement(this NamingTemplate fileNamingTemplate, TemplateTags templateTags, object value)
|
||||
=> fileNamingTemplate.AddParameterReplacement(templateTags.TagName, value);
|
||||
|
||||
public static void AddUniqueParameterReplacement(this NamingTemplate namingTemplate, string key, object value)
|
||||
=> namingTemplate.ParameterReplacements[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ namespace LibationWinForms.Dialogs
|
||||
private string workingTemplateText
|
||||
{
|
||||
get => _workingTemplateText;
|
||||
set => _workingTemplateText = template.Sanitize(value);
|
||||
set => _workingTemplateText = template.Sanitize(value, Configuration.Instance.ReplacementCharacters);
|
||||
}
|
||||
|
||||
private void resetTextBox(string value) => this.templateTb.Text = workingTemplateText = value;
|
||||
@ -59,7 +59,7 @@ namespace LibationWinForms.Dialogs
|
||||
|
||||
// populate list view
|
||||
foreach (var tag in template.GetTemplateTags())
|
||||
listView1.Items.Add(new ListViewItem(new[] { $"<{tag.TagName}>", tag.Description }));
|
||||
listView1.Items.Add(new ListViewItem(new[] { $"<{tag.TagName}>", tag.Description }) { Tag = tag.DefaultValue });
|
||||
}
|
||||
|
||||
private void resetToDefaultBtn_Click(object sender, EventArgs e) => resetTextBox(template.DefaultTemplate);
|
||||
@ -73,6 +73,8 @@ namespace LibationWinForms.Dialogs
|
||||
var libraryBookDto = new LibraryBookDto
|
||||
{
|
||||
Account = "my account",
|
||||
DateAdded = new DateTime(2022, 6, 9, 0, 0, 0),
|
||||
DatePublished = new DateTime(2017, 2, 27, 0, 0, 0),
|
||||
AudibleProductId = "123456789",
|
||||
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
|
||||
Locale = "us",
|
||||
@ -207,9 +209,11 @@ namespace LibationWinForms.Dialogs
|
||||
|
||||
private void listView1_DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
var itemText = listView1.SelectedItems[0].Text.Replace("...", "");
|
||||
var text = templateTb.Text;
|
||||
var itemText = listView1.SelectedItems[0].Tag as string;
|
||||
|
||||
if (string.IsNullOrEmpty(itemText)) return;
|
||||
|
||||
var text = templateTb.Text;
|
||||
var selStart = Math.Min(Math.Max(0, templateTb.SelectionStart), text.Length);
|
||||
|
||||
templateTb.Text = text.Insert(selStart, itemText);
|
||||
|
||||
@ -36,10 +36,10 @@ namespace FileNamingTemplateTests
|
||||
extension = FileUtility.GetStandardizedExtension(extension);
|
||||
var fullfilename = Path.Combine(dirFullPath, template + extension);
|
||||
|
||||
var fileNamingTemplate = new FileNamingTemplate(fullfilename);
|
||||
var fileNamingTemplate = new FileNamingTemplate(fullfilename, Replacements);
|
||||
fileNamingTemplate.AddParameterReplacement("title", filename);
|
||||
fileNamingTemplate.AddParameterReplacement("id", metadataSuffix);
|
||||
return fileNamingTemplate.GetFilePath(Replacements, extension).PathWithoutPrefix;
|
||||
return fileNamingTemplate.GetFilePath(extension).PathWithoutPrefix;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@ -61,10 +61,10 @@ namespace FileNamingTemplateTests
|
||||
var estension = Path.GetExtension(originalPath);
|
||||
var t = Path.ChangeExtension(originalPath, null) + " - <chapter> - <title>" + estension;
|
||||
|
||||
var fileNamingTemplate = new FileNamingTemplate(t);
|
||||
var fileNamingTemplate = new FileNamingTemplate(t, Replacements);
|
||||
fileNamingTemplate.AddParameterReplacement("chapter", chapterCountLeadingZeros);
|
||||
fileNamingTemplate.AddParameterReplacement("title", suffix);
|
||||
return fileNamingTemplate.GetFilePath(Replacements, estension).PathWithoutPrefix;
|
||||
return fileNamingTemplate.GetFilePath(estension).PathWithoutPrefix;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@ -74,9 +74,9 @@ namespace FileNamingTemplateTests
|
||||
{
|
||||
if (Environment.OSVersion.Platform == platformID)
|
||||
{
|
||||
var fileNamingTemplate = new FileNamingTemplate(inStr);
|
||||
var fileNamingTemplate = new FileNamingTemplate(inStr, Replacements);
|
||||
fileNamingTemplate.AddParameterReplacement("title", @"s\l/a\s/h\e/s");
|
||||
fileNamingTemplate.GetFilePath(Replacements, "txt").PathWithoutPrefix.Should().Be(outStr);
|
||||
fileNamingTemplate.GetFilePath("txt").PathWithoutPrefix.Should().Be(outStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -26,11 +26,32 @@ namespace TemplatesTests
|
||||
=> new()
|
||||
{
|
||||
Account = "my account",
|
||||
DateAdded = new DateTime(2022, 6, 9, 0, 0, 0),
|
||||
DatePublished = new DateTime(2017, 2, 27, 0, 0, 0),
|
||||
FileDate = new DateTime(2023, 1, 28, 0, 0, 0),
|
||||
AudibleProductId = "asin",
|
||||
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
|
||||
Locale = "us",
|
||||
YearPublished = 2017,
|
||||
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
|
||||
YearPublished = 2017,
|
||||
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
|
||||
Narrators = new List<string> { "Stephen Fry" },
|
||||
SeriesName = seriesName ?? "",
|
||||
SeriesNumber = "1",
|
||||
BitRate = 128,
|
||||
SampleRate = 44100,
|
||||
Channels = 2
|
||||
};
|
||||
|
||||
public static LibraryBookDto GetLibraryBookWithNullDates(string seriesName = "Sherlock Holmes")
|
||||
=> new()
|
||||
{
|
||||
Account = "my account",
|
||||
FileDate = new DateTime(2023, 1, 28, 0, 0, 0),
|
||||
AudibleProductId = "asin",
|
||||
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
|
||||
Locale = "us",
|
||||
YearPublished = 2017,
|
||||
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
|
||||
Narrators = new List<string> { "Stephen Fry" },
|
||||
SeriesName = seriesName ?? "",
|
||||
SeriesNumber = "1",
|
||||
@ -71,14 +92,14 @@ namespace TemplatesTests
|
||||
[DataRow(null, @"C:\", "ext")]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void arg_null_exception(string template, string dirFullPath, string extension)
|
||||
=> Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension);
|
||||
=> Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension, Replacements);
|
||||
|
||||
[TestMethod]
|
||||
[DataRow("", @"C:\foo\bar", "ext")]
|
||||
[DataRow(" ", @"C:\foo\bar", "ext")]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void arg_exception(string template, string dirFullPath, string extension)
|
||||
=> Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension);
|
||||
=> Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension, Replacements);
|
||||
|
||||
[TestMethod]
|
||||
[DataRow("f.txt", @"C:\foo\bar", "", @"C:\foo\bar\f.txt", PlatformID.Win32NT)]
|
||||
@ -98,20 +119,126 @@ namespace TemplatesTests
|
||||
public void Tests(string template, string dirFullPath, string extension, string expected, PlatformID platformID)
|
||||
{
|
||||
if (Environment.OSVersion.Platform == platformID)
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension)
|
||||
.GetFilePath(Replacements, extension)
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension, Replacements)
|
||||
.GetFilePath(extension)
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow("<id> - <filedate[yy-MM-dd]>", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 23-01-28.m4b")]
|
||||
[DataRow("<id> - <filedate [ yy-MM-dd ] >", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 23-01-28.m4b")]
|
||||
[DataRow("<id> - <file date [yy-MM-dd] >", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 23-01-28.m4b")]
|
||||
[DataRow("<id> - <file date[yy-MM-dd]>", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 23-01-28.m4b")]
|
||||
[DataRow("<id> - <file date[]>", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 2023-01-28.m4b")]
|
||||
[DataRow("<id> - <filedate[]>", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 2023-01-28.m4b")]
|
||||
[DataRow("<id> - <filedate [ ] >", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 2023-01-28.m4b")]
|
||||
[DataRow("<id> - <filedate>", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 2023-01-28.m4b")]
|
||||
[DataRow("<id> - <filedate >", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 2023-01-28.m4b")]
|
||||
[DataRow("<id> - <file date>", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 2023-01-28.m4b")]
|
||||
[DataRow("<id> - <file date>", @"C:\foo\bar", "m4b", @"C:\foo\bar\asin - 2023-01-28.m4b")]
|
||||
public void DateFormat_pattern(string template, string dirFullPath, string extension, string expected)
|
||||
{
|
||||
if (Environment.OSVersion.Platform is not PlatformID.Win32NT)
|
||||
{
|
||||
dirFullPath = dirFullPath.Replace("C:", "").Replace('\\', '/');
|
||||
expected = expected.Replace("C:", "").Replace('\\', '/');
|
||||
}
|
||||
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension, Replacements)
|
||||
.GetFilePath(extension)
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow("<filedate[h]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate[h]>.m4b")]
|
||||
[DataRow("< filedate[yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\< filedate[yyyy]>.m4b")]
|
||||
[DataRow("<filedate yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate yyyy]>.m4b")]
|
||||
[DataRow("<filedate [yyyy>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate [yyyy>.m4b")]
|
||||
[DataRow("<filedate yyyy>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate yyyy>.m4b")]
|
||||
[DataRow("<filedate[yyyy]", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate[yyyy].m4b")]
|
||||
[DataRow("<fil edate[yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<fil edate[yyyy]>.m4b")]
|
||||
[DataRow("<filed ate[yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filed ate[yyyy]>.m4b")]
|
||||
public void DateFormat_invalid(string template, string dirFullPath, string extension, string expected)
|
||||
{
|
||||
if (Environment.OSVersion.Platform is not PlatformID.Win32NT)
|
||||
{
|
||||
dirFullPath = dirFullPath.Replace("C:", "").Replace('\\', '/');
|
||||
expected = expected.Replace("C:", "").Replace('\\', '/').Replace('<', '<').Replace('>','>');
|
||||
}
|
||||
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension, Replacements)
|
||||
.GetFilePath(extension)
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow("<filedate[yy-MM-dd]> <date added[yy-MM-dd]> <pubdate[yy-MM]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\23-01-28 22-06-09 17-02.m4b")]
|
||||
[DataRow("<filedate[yy-MM-dd]> <filedate[yy-MM-dd]> <filedate[yy-MM-dd]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\23-01-28 23-01-28 23-01-28.m4b")]
|
||||
[DataRow("<file date [ yy-MM-dd ] > <filedate [ yy-MM-dd ] > <file date [ yy-MM-dd] >", @"C:\foo\bar", ".m4b", @"C:\foo\bar\23-01-28 23-01-28 23-01-28.m4b")]
|
||||
public void DateFormat_multiple(string template, string dirFullPath, string extension, string expected)
|
||||
{
|
||||
if (Environment.OSVersion.Platform is not PlatformID.Win32NT)
|
||||
{
|
||||
dirFullPath = dirFullPath.Replace("C:", "").Replace('\\', '/');
|
||||
expected = expected.Replace("C:", "").Replace('\\', '/');
|
||||
}
|
||||
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension, Replacements)
|
||||
.GetFilePath(extension)
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow("<id> - <pubdate[MM/dd/yy HH:mm]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\asin - 02∕27∕17 00꞉00.m4b", PlatformID.Win32NT)]
|
||||
[DataRow("<id> - <pubdate[MM/dd/yy HH:mm]>", @"/foo/bar", ".m4b", @"/foo/bar/asin - 02∕27∕17 00:00.m4b", PlatformID.Unix)]
|
||||
[DataRow("<id> - <filedate[MM/dd/yy HH:mm]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\asin - 01∕28∕23 00꞉00.m4b", PlatformID.Win32NT)]
|
||||
[DataRow("<id> - <filedate[MM/dd/yy HH:mm]>", @"/foo/bar", ".m4b", @"/foo/bar/asin - 01∕28∕23 00:00.m4b", PlatformID.Unix)]
|
||||
[DataRow("<id> - <date added[MM/dd/yy HH:mm]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\asin - 06∕09∕22 00꞉00.m4b", PlatformID.Win32NT)]
|
||||
[DataRow("<id> - <date added[MM/dd/yy HH:mm]>", @"/foo/bar", ".m4b", @"/foo/bar/asin - 06∕09∕22 00:00.m4b", PlatformID.Unix)]
|
||||
public void DateFormat_illegal(string template, string dirFullPath, string extension, string expected, PlatformID platformID)
|
||||
{
|
||||
if (Environment.OSVersion.Platform == platformID)
|
||||
{
|
||||
Templates.File.HasWarnings(template).Should().BeTrue();
|
||||
Templates.File.HasWarnings(Templates.File.Sanitize(template, Replacements)).Should().BeFalse();
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension, Replacements)
|
||||
.GetFilePath(extension)
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
[DataRow("<filedate[yy-MM-dd]> <date added[yy-MM-dd]> <pubdate[yy-MM]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\23-01-28.m4b")]
|
||||
public void DateFormat_null(string template, string dirFullPath, string extension, string expected)
|
||||
{
|
||||
if (Environment.OSVersion.Platform is not PlatformID.Win32NT)
|
||||
{
|
||||
dirFullPath = dirFullPath.Replace("C:", "").Replace('\\', '/');
|
||||
expected = expected.Replace("C:", "").Replace('\\', '/');
|
||||
}
|
||||
|
||||
Templates.getFileNamingTemplate(GetLibraryBookWithNullDates(), template, dirFullPath, extension, Replacements)
|
||||
.GetFilePath(extension)
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow(@"C:\a\b", @"C:\a\b\foobar.ext", PlatformID.Win32NT)]
|
||||
[DataRow(@"/a/b", @"/a/b/foobar.ext", PlatformID.Unix)]
|
||||
public void IfSeries_empty(string directory, string expected, PlatformID platformID)
|
||||
{
|
||||
if (Environment.OSVersion.Platform == platformID)
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), "foo<if series-><-if series>bar", directory, "ext")
|
||||
.GetFilePath(Replacements, ".ext")
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), "foo<if series-><-if series>bar", directory, "ext", Replacements)
|
||||
.GetFilePath(".ext")
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
}
|
||||
@ -122,8 +249,8 @@ namespace TemplatesTests
|
||||
public void IfSeries_no_series(string directory, string expected, PlatformID platformID)
|
||||
{
|
||||
if (Environment.OSVersion.Platform == platformID)
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(null), "foo<if series->-<series>-<id>-<-if series>bar", directory, "ext")
|
||||
.GetFilePath(Replacements, ".ext")
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(null), "foo<if series->-<series>-<id>-<-if series>bar", directory, "ext", Replacements)
|
||||
.GetFilePath(".ext")
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
}
|
||||
@ -134,8 +261,8 @@ namespace TemplatesTests
|
||||
public void IfSeries_with_series(string directory, string expected, PlatformID platformID)
|
||||
{
|
||||
if (Environment.OSVersion.Platform == platformID)
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), "foo<if series->-<series>-<id>-<-if series>bar", directory, "ext")
|
||||
.GetFilePath(Replacements, ".ext")
|
||||
Templates.getFileNamingTemplate(GetLibraryBook(), "foo<if series->-<series>-<id>-<-if series>bar", directory, "ext", Replacements)
|
||||
.GetFilePath(".ext")
|
||||
.PathWithoutPrefix
|
||||
.Should().Be(expected);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user