file-folder-helper/Helpers/HelperKanbanMetadata.cs
Mike Phares 84cda2e57f GetRecursiveLines only when
StartAt and Destination are supplied
nuget-lower
HelperGenealogicalDataCommunication
2023-08-31 08:31:10 -07:00

146 lines
6.9 KiB
C#

using File_Folder_Helper.Models;
using Microsoft.Extensions.Logging;
using System.Text;
using System.Text.RegularExpressions;
namespace File_Folder_Helper.Helpers;
internal static partial class HelperKanbanMetadata
{
[GeneratedRegex("([A-Z]+(.))")]
private static partial Regex UpperCase();
[GeneratedRegex("[\\s!?.,@:;|\\\\/\"'`£$%\\^&*{}[\\]()<>~#+\\-=_¬]+")]
private static partial Regex InvalidCharacter();
private static string GetParamCase(string value)
{
string result;
StringBuilder stringBuilder = new(value);
Match[] matches = UpperCase().Matches(value).ToArray();
for (int i = matches.Length - 1; i > -1; i--)
_ = stringBuilder.Insert(matches[i].Index, '-');
string[] segments = InvalidCharacter().Split(stringBuilder.ToString().ToLower());
result = string.Join('-', segments).Trim('-');
return result;
}
private static void TestParamCases()
{
if (GetParamCase("PascalCase") != "pascal-case")
throw new Exception("PascalCase");
if (GetParamCase("camelCase") != "camel-case")
throw new Exception("camelCase");
if (GetParamCase("snake_case") != "snake-case")
throw new Exception("snake_case");
if (GetParamCase("No Case") != "no-case")
throw new Exception("No Case");
if (GetParamCase("With 2 numbers 3") != "with-2-numbers-3")
throw new Exception("With 2 numbers 3");
if (GetParamCase("Multiple spaces") != "multiple-spaces")
throw new Exception("Multiple spaces");
if (GetParamCase("Tab\tCharacter") != "tab-character")
throw new Exception("Tab\tCharacter");
if (GetParamCase("New\nLine") != "new-line")
throw new Exception("New\nLine");
if (GetParamCase("Punctuation, Characters") != "punctuation-characters")
throw new Exception("Punctuation, Characters");
if (GetParamCase("M!o?r.e, @p:u;n|c\\t/u\"a\'t`i£o$n% ^c&h*a{r}a[c]t(e)r<s> ~l#i+k-e= _t¬hese") != "m-o-r-e-p-u-n-c-t-u-a-t-i-o-n-c-h-a-r-a-c-t-e-r-s-l-i-k-e-t-hese")
throw new Exception("M!o?r.e, @p:u;n|c\\t/u\"a\'t`i£o$n% ^c&h*a{r}a[c]t(e)r<s> ~l#i+k-e= _t¬hese");
if (GetParamCase("This string ends with punctuation!") != "this-string-ends-with-punctuation")
throw new Exception("This string ends with punctuation!");
if (GetParamCase("?This string starts with punctuation") != "this-string-starts-with-punctuation")
throw new Exception("?This string starts with punctuation");
if (GetParamCase("#This string has punctuation at both ends&") != "this-string-has-punctuation-at-both-ends")
throw new Exception("#This string has punctuation at both ends&");
if (GetParamCase("軟件 測試") != "軟件-測試")
throw new Exception("軟件 測試");
if (GetParamCase("実験 試し") != "実験-試し")
throw new Exception("実験 試し");
if (GetParamCase("יקספּערמענאַל פּרובירן") != "יקספּערמענאַל-פּרובירן")
throw new Exception("יקספּערמענאַל פּרובירן");
if (GetParamCase("я надеюсь, что это сработает") != "я-надеюсь-что-это-сработает")
throw new Exception("я надеюсь, что это сработает");
}
private static List<(int, int, string, FileInfo)> GetCollectionFromIndex(string sourceDirectory, string[] lines)
{
List<(int, int, string, FileInfo)> results = new();
string line;
FileInfo fileInfo;
string[] segments;
int groupCount = 0;
string? group = null;
for (int i = 0; i < lines.Length; i++)
{
line = lines[i];
if (line.Length < 4)
continue;
if (line[..3] == "## ")
{
group = line[3..];
groupCount += 1;
continue;
}
if (group is null || line[..3] != "- [" || line[^1] != ')')
continue;
segments = line.Split("](");
if (segments.Length != 2)
continue;
fileInfo = new(Path.Combine(sourceDirectory, segments[1][..^1]));
if (!fileInfo.Exists)
continue;
results.Add((groupCount, i, group, fileInfo));
}
return results;
}
internal static void SetMetadata(ILogger log, AppSettings appSettings, string sourceDirectory)
{
bool? match;
string? paramCase;
string statusLine;
List<string> lines;
LineNumber lineNumber;
if (log is null)
throw new NullReferenceException();
TestParamCases();
string fullPath = Path.GetFullPath(sourceDirectory);
if (!Directory.Exists(fullPath))
_ = Directory.CreateDirectory(fullPath);
string indexFile = Path.Combine(fullPath, "index.md");
if (File.Exists(indexFile))
{
string[] indexFileLines = File.ReadAllLines(indexFile);
List<(int, int, string, FileInfo)> collectionFromIndex = GetCollectionFromIndex(sourceDirectory, indexFileLines);
foreach ((int groupCount, int itemLineNumber, string group, FileInfo fileInfo) in collectionFromIndex)
{
if (itemLineNumber == 0)
throw new NotSupportedException();
(lines, lineNumber) = HelperMarkdown.GetStatusAndFrontMatterYamlEndLineNumbers(fileInfo);
if (!lines.Any())
continue;
statusLine = $"status: \"{groupCount}-{group}\"";
paramCase = lineNumber.H1 is null ? null : GetParamCase(lines[lineNumber.H1.Value]);
indexFileLines[itemLineNumber] = $"{fileInfo.LastWriteTime.Ticks}~~~{indexFileLines[itemLineNumber]}";
match = lineNumber.H1 is null || paramCase is null ? null : Path.GetFileNameWithoutExtension(fileInfo.Name) == paramCase;
if (lineNumber.FrontMatterYamlEnd is null)
throw new NotSupportedException($"{nameof(SetMetadata)} must be executed first!");
if (lineNumber.H1 is not null && paramCase is not null && match is not null && !match.Value)
lines[lineNumber.H1.Value] = $"# {paramCase}";
if (lineNumber.Status is null)
lines.Insert(lineNumber.FrontMatterYamlEnd.Value, statusLine);
else
{
if ((match is null || match.Value) && lines[lineNumber.Status.Value] == statusLine)
continue;
lines[lineNumber.Status.Value] = statusLine;
}
File.WriteAllLines(fileInfo.FullName, lines);
}
File.WriteAllLines(indexFile, indexFileLines);
}
}
}