Relative path enhancement

Switch to Card
Not Mapped
This commit is contained in:
2023-09-28 11:42:29 -07:00
parent f810af3ebe
commit b1e63df70b
5 changed files with 369 additions and 334 deletions

View File

@ -11,40 +11,6 @@ namespace File_Folder_Helper.Helpers;
internal static partial class HelperMarkdown
{
[GeneratedRegex("(~~)?(#)([a-zA-Z0-9]{6})(~~)?( )")]
private static partial Regex HtmlColor();
private record Input(string Source,
string? StartAt,
string? Destination);
private record Record(string Directory,
string File,
string[] Lines);
private record MarkdownFileAndLines(MarkdownFile MarkdownFile,
string[] Lines);
private record MarkdownExtra(ReadOnlyCollection<string>? Assignees,
ReadOnlyCollection<H2HexColor>? H2HexColorCollection,
ReadOnlyCollection<H2NoCheckboxes>? H2NoCheckboxesCollection,
ReadOnlyCollection<H2WithCheckboxes>? H2WithCheckboxesCollection,
string? RequestedDateTime);
private record MarkdownFileH1AndRelativePath(MarkdownFile? MarkdownFile, string[]? Lines, string? H1, string? RelativePath);
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(Dictionary<string, JsonElement>))]
internal partial class DictionaryStringAndJsonElementSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(ReadOnlyDictionary<string, List<MarkdownFile>>))]
internal partial class ColumnAndLinksSourceGenerationContext : JsonSerializerContext
{
}
private static void SetRecursiveLines(AppSettings appSettings, ILogger<Worker> logger, ReadOnlyDictionary<string, List<MarkdownFileAndLines>> keyValuePairs, string linkTitle, MarkdownFile markdownFile, string[] lines, List<char> indentations, List<string> recursiveLines)
{
if (recursiveLines is null)
@ -182,6 +148,9 @@ internal static partial class HelperMarkdown
return result;
}
[GeneratedRegex("(~~)?(#)([a-zA-Z0-9]{6})(~~)?( )")]
private static partial Regex HtmlColor();
private static List<MarkdownFileAndLines> GetMarkdownFileAndLines(string file, List<MarkdownFileAndLines> markdownFiles)
{
List<MarkdownFileAndLines> results = new();
@ -240,7 +209,7 @@ internal static partial class HelperMarkdown
line = lines[i];
if (line.Length < 3)
continue;
if (line[..3] == "---")
if (h1LineNumber is null && line[..3] == "---")
{
frontMatterYamlEndLineNumber = i;
continue;
@ -280,6 +249,90 @@ internal static partial class HelperMarkdown
return (lines.ToList(), lineNumber);
}
private static MarkdownExtra GetMarkdownExtra(MarkdownFileAndLines markdownFileAndLines)
{
MarkdownExtra result;
int skip;
Match match;
string line;
int completed;
int notCompleted;
List<string> lines;
string? effort = null;
List<string> assignees = new();
string? requestedDateTime = null;
ReadOnlyCollection<Group> groups;
List<H2HexColor> h2HexColors = new();
List<H2NoCheckboxes> h2NoCheckboxes = new();
List<H2WithCheckboxes> h2WithCheckboxes = new();
if (markdownFileAndLines.MarkdownFile.LineNumber.FrontMatterYamlEnd is not null)
{
for (int i = 1; i < markdownFileAndLines.Lines.Length; i++)
{
line = markdownFileAndLines.Lines[i];
if (line.Length < 3)
continue;
if (line.Length > 8 && line[..8] == "effort: ")
{
effort = line[7..].Trim().Trim('"');
continue;
}
if (line.Length > 10 && line[..10] == "assigned: ")
{
foreach (string item in line[10..].Split(',', StringSplitOptions.RemoveEmptyEntries))
assignees.Add(item.Trim().Trim('"'));
continue;
}
if (line.Length > 11 && line[..11] == "requested: ")
{
requestedDateTime = line[10..].Trim().Trim('"');
continue;
}
if (line.Length > 3 && line[0] == '#' && line[1] == '#' && line[2] == ' ')
{
completed = 0;
notCompleted = 0;
match = HtmlColor().Match(line[3..]);
if (line.Length > 3 && match.Success)
{
groups = match.Groups.AsReadOnly();
skip = 3 + groups.Skip(1).Sum(l => l.Length);
h2HexColors.Add(new(line[skip..], $"#{groups.First(l => l.Value.Length == 6)}"));
continue;
}
lines = new();
if (i + 1 == markdownFileAndLines.Lines.Length)
continue;
for (int j = i + 1; j < markdownFileAndLines.Lines.Length; j++)
{
line = markdownFileAndLines.Lines[j];
if (line.Length == 0)
continue;
if (line.Length > 2 && line[0] == '#')
break;
lines.Add(line);
if (line.Length < 5 || line[0] != '-' || line[1] != ' ' || line[2] != '[')
continue;
if (line[3] == ' ' && line[4] == ']')
notCompleted++;
else if (line[3] is 'x' or 'X' && line[4] == ']')
completed++;
}
if (completed != 0 || notCompleted != 0)
h2WithCheckboxes.Add(new(completed,
markdownFileAndLines.Lines[i][3..],
notCompleted,
notCompleted + completed));
else if (lines.Count > 0)
h2NoCheckboxes.Add(new(markdownFileAndLines.Lines[i][3..], new(lines)));
continue;
}
}
}
result = new(new(assignees), effort, new(h2HexColors), new(h2NoCheckboxes), new(h2WithCheckboxes), requestedDateTime);
return result;
}
private static List<MarkdownFileAndLines> Distinct(IEnumerable<MarkdownFileAndLines>? markdownFileAndLinesCollection)
{
List<MarkdownFileAndLines> results = new();
@ -521,20 +574,15 @@ internal static partial class HelperMarkdown
File.WriteAllLines(file, new string[] { "---", $"type: \"{type}\"", "---", string.Empty, $"# {h1}" });
lines = File.ReadAllLines(file).ToList();
}
markdownFile = new(null,
fileInfo.CreationTime,
markdownFile = new(fileInfo.CreationTime,
fileInfo.DirectoryName,
fileInfo.Extension,
file,
fileInfo.Name,
fileNameWithoutExtension,
h1,
null,
null,
null,
fileInfo.LastWriteTime,
lineNumber,
null,
type);
if (force || input.StartAt is null || file.StartsWith(input.StartAt))
results.Add(key, new(markdownFile, lines.ToArray()));
@ -544,6 +592,115 @@ internal static partial class HelperMarkdown
return new(results);
}
private static ReadOnlyDictionary<string, List<Card>> GetColumnsToCards(Input input, ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection)
{
Dictionary<string, List<Card>> results = new();
Card card;
string key;
string[] lines;
string[] segmentsA;
string? column = null;
List<Card> cards = new();
MarkdownFile markdownFile;
MarkdownExtra markdownExtra;
List<string> allKeys = new();
MarkdownFileAndLines? markdownFileAndLines;
foreach (KeyValuePair<string, MarkdownFileAndLines> relativeTo in relativeToCollection)
allKeys.Add(relativeTo.Key);
foreach (KeyValuePair<string, MarkdownFileAndLines> relativeTo in relativeToCollection)
{
if (relativeTo.Value.Lines.Length == 0)
continue;
lines = relativeTo.Value.Lines;
markdownFile = relativeTo.Value.MarkdownFile;
if (markdownFile.FileNameWithoutExtension != "index" || markdownFile.Type != "Kanban")
continue;
if (!File.Exists(markdownFile.File))
continue;
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].Length < 4 || lines[i][0] != '#' || lines[i][1] != '#' || lines[i][2] != ' ')
continue;
if (cards.Count > 1)
{
if (column is null)
throw new NullReferenceException(nameof(column));
results.Add(column, cards);
cards = new();
}
column = lines[i][3..].TrimEnd();
if (lines.Length == i + 1)
continue;
for (int j = i + 1; j < lines.Length; j++)
{
if (lines[j].Length < 5)
continue;
if (lines[j].Length >= 4 && lines[j][0] == '#' && lines[j][1] == '#' && lines[j][2] == ' ')
break;
segmentsA = lines[j].Split("](");
if (segmentsA.Length != 2 || segmentsA[1][^1] != ')')
continue;
key = Path.GetRelativePath(input.Source, Path.Combine(markdownFile.Directory, segmentsA[1][..^1]));
if (!allKeys.Remove(key))
throw new NotSupportedException();
if (!relativeToCollection.TryGetValue(key, out markdownFileAndLines))
continue;
markdownExtra = GetMarkdownExtra(markdownFileAndLines);
card = new(markdownExtra.Assignees,
markdownFileAndLines.MarkdownFile.CreationDateTime,
markdownFileAndLines.MarkdownFile.Directory,
markdownExtra.Effort,
markdownFileAndLines.MarkdownFile.Extension,
markdownFileAndLines.MarkdownFile.File,
markdownFileAndLines.MarkdownFile.FileName,
markdownFileAndLines.MarkdownFile.FileNameWithoutExtension,
markdownFileAndLines.MarkdownFile.H1,
markdownExtra.H2HexColorCollection,
markdownExtra.H2NoCheckboxesCollection,
markdownExtra.H2WithCheckboxesCollection,
markdownFileAndLines.MarkdownFile.LastWriteDateTime,
markdownFileAndLines.MarkdownFile.LineNumber,
markdownExtra.RequestedDateTime,
markdownFileAndLines.MarkdownFile.Type);
cards.Add(card);
}
}
foreach (string notLinkedKey in allKeys)
{
key = notLinkedKey;
if (!relativeToCollection.TryGetValue(key, out markdownFileAndLines))
continue;
if (markdownFileAndLines.MarkdownFile.LineNumber.FrontMatterYamlEnd is null)
continue;
markdownExtra = GetMarkdownExtra(markdownFileAndLines);
card = new(markdownExtra.Assignees,
markdownFileAndLines.MarkdownFile.CreationDateTime,
markdownFileAndLines.MarkdownFile.Directory,
markdownExtra.Effort,
markdownFileAndLines.MarkdownFile.Extension,
markdownFileAndLines.MarkdownFile.File,
markdownFileAndLines.MarkdownFile.FileName,
markdownFileAndLines.MarkdownFile.FileNameWithoutExtension,
markdownFileAndLines.MarkdownFile.H1,
markdownExtra.H2HexColorCollection,
markdownExtra.H2NoCheckboxesCollection,
markdownExtra.H2WithCheckboxesCollection,
markdownFileAndLines.MarkdownFile.LastWriteDateTime,
markdownFileAndLines.MarkdownFile.LineNumber,
markdownExtra.RequestedDateTime,
markdownFileAndLines.MarkdownFile.Type);
cards.Add(card);
}
if (cards.Count > 1)
{
column = "Not Linked";
results.Add(column, cards);
cards = new();
}
}
return new(results);
}
private static MarkdownFileAndLines? GetMarkdownFile(ReadOnlyDictionary<string, List<MarkdownFileAndLines>> keyValuePairs, MarkdownFile markdownFile, string file)
{
MarkdownFileAndLines? result;
@ -976,6 +1133,18 @@ internal static partial class HelperMarkdown
}
}
private static void SaveColumnToCards(Input input, ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection)
{
if (string.IsNullOrEmpty(input.StartAt) || string.IsNullOrEmpty(input.Destination))
throw new NotSupportedException();
ReadOnlyDictionary<string, List<Card>> columnsToCards = GetColumnsToCards(input, relativeToCollection);
if (columnsToCards.Count > 0)
{
string json = JsonSerializer.Serialize(columnsToCards, ColumnsAndCardsSourceGenerationContext.Default.ReadOnlyDictionaryStringListCard);
File.WriteAllText(Path.Combine(input.Destination, $"{nameof(columnsToCards)}.json"), json);
}
}
private static List<Record> GetWithLinksForHugo(AppSettings appSettings, Input input)
{
List<Record> results = new();
@ -1056,6 +1225,43 @@ internal static partial class HelperMarkdown
}
}
private record Input(string Source,
string? StartAt,
string? Destination);
private record Record(string Directory,
string File,
string[] Lines);
private record MarkdownFile(DateTime CreationDateTime,
string Directory,
string Extension,
string File,
string FileName,
string FileNameWithoutExtension,
string H1,
DateTime LastWriteDateTime,
LineNumber LineNumber,
string Type);
private record MarkdownFileAndLines(MarkdownFile MarkdownFile,
string[] Lines);
private record MarkdownExtra(ReadOnlyCollection<string>? Assignees,
string? Effort,
ReadOnlyCollection<H2HexColor>? H2HexColorCollection,
ReadOnlyCollection<H2NoCheckboxes>? H2NoCheckboxesCollection,
ReadOnlyCollection<H2WithCheckboxes>? H2WithCheckboxesCollection,
string? RequestedDateTime);
private record MarkdownFileH1AndRelativePath(MarkdownFile? MarkdownFile, string[]? Lines, string? H1, string? RelativePath);
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(Dictionary<string, JsonElement>))]
internal partial class DictionaryStringAndJsonElementSourceGenerationContext : JsonSerializerContext
{
}
private static (string type, string h1) GetTypeAndH1(AppSettings appSettings, string h1, List<string> lines, LineNumber lineNumber)
{
string type = lineNumber.Type is null ? appSettings.DefaultNoteType : lines[lineNumber.Type.Value][5..].Trim().Trim('"');
@ -1192,179 +1398,7 @@ internal static partial class HelperMarkdown
Write(input, markdownFileAndLinesCollection);
}
if (!string.IsNullOrEmpty(input.StartAt) && !string.IsNullOrEmpty(input.Destination))
Save(input, relativeToCollection);
string directory = Path.Combine(Environment.CurrentDirectory, ".vscode");
if (!Directory.Exists(directory))
{
string json;
MarkdownFile markdownFile = relativeToCollection.ElementAt(0).Value.MarkdownFile;
json = JsonSerializer.Serialize(markdownFile, MarkdownFileSourceGenerationContext.Default.MarkdownFile);
if (json != "{}")
{
json = JsonSerializer.Serialize(relativeToCollection.Select(l => l.Value.MarkdownFile).ToArray(), MarkdownFileCollectionSourceGenerationContext.Default.MarkdownFileArray);
File.WriteAllText($"{DateTime.Now.Ticks}.json", json);
}
}
}
private static void Save(Input input, ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection)
{
if (string.IsNullOrEmpty(input.StartAt) || string.IsNullOrEmpty(input.Destination))
throw new NotSupportedException();
ReadOnlyDictionary<string, List<MarkdownFile>> columnsToLinks = GetColumnsToLinks(input, relativeToCollection);
if (columnsToLinks.Count > 0)
{
string json = JsonSerializer.Serialize(columnsToLinks, ColumnAndLinksSourceGenerationContext.Default.ReadOnlyDictionaryStringListMarkdownFile);
File.WriteAllText(Path.Combine(input.Destination, $"{nameof(columnsToLinks)}.json"), json);
}
}
private static ReadOnlyDictionary<string, List<MarkdownFile>> GetColumnsToLinks(Input input, ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection)
{
Dictionary<string, List<MarkdownFile>> results = new();
string key;
string[] lines;
string[] segmentsA;
string? column = null;
MarkdownFile markdownFile;
MarkdownExtra markdownExtra;
List<MarkdownFile> links = new();
MarkdownFileAndLines? markdownFileAndLines;
foreach (KeyValuePair<string, MarkdownFileAndLines> relativeTo in relativeToCollection)
{
if (relativeTo.Value.Lines.Length == 0)
continue;
lines = relativeTo.Value.Lines;
markdownFile = relativeTo.Value.MarkdownFile;
if (markdownFile.FileNameWithoutExtension != "index" && markdownFile.Directory.EndsWith(".kanbn"))
continue;
if (!File.Exists(markdownFile.File))
continue;
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].Length < 4 || lines[i][0] != '#' || lines[i][1] != '#' || lines[i][2] != ' ')
continue;
if (links.Count > 1)
{
if (column is null)
throw new NullReferenceException(nameof(column));
results.Add(column, links);
links = new();
}
column = lines[i][3..].TrimEnd();
if (lines.Length == i + 1)
continue;
for (int j = i + 1; j < lines.Length; j++)
{
if (lines[j].Length < 5)
continue;
if (lines[j].Length >= 4 && lines[j][0] == '#' && lines[j][1] == '#' && lines[j][2] == ' ')
break;
segmentsA = lines[j].Split("](");
if (segmentsA.Length != 2 || segmentsA[1][^1] != ')')
continue;
key = Path.GetRelativePath(input.Source, Path.Combine(input.Source, segmentsA[1][..^1]));
if (!relativeToCollection.TryGetValue(key, out markdownFileAndLines))
continue;
markdownExtra = GetMarkdownExtra(markdownFileAndLines);
markdownFile = new(markdownExtra.Assignees,
markdownFileAndLines.MarkdownFile.CreationDateTime,
markdownFileAndLines.MarkdownFile.Directory,
markdownFileAndLines.MarkdownFile.Extension,
markdownFileAndLines.MarkdownFile.File,
markdownFileAndLines.MarkdownFile.FileName,
markdownFileAndLines.MarkdownFile.FileNameWithoutExtension,
markdownFileAndLines.MarkdownFile.H1,
markdownExtra.H2HexColorCollection,
markdownExtra.H2NoCheckboxesCollection,
markdownExtra.H2WithCheckboxesCollection,
markdownFileAndLines.MarkdownFile.LastWriteDateTime,
markdownFileAndLines.MarkdownFile.LineNumber,
markdownExtra.RequestedDateTime,
markdownFileAndLines.MarkdownFile.Type);
links.Add(markdownFile);
}
}
}
return new(results);
}
private static MarkdownExtra GetMarkdownExtra(MarkdownFileAndLines markdownFileAndLines)
{
MarkdownExtra result;
int skip;
Match match;
string line;
int completed;
int notCompleted;
List<string> lines;
List<string> assignees = new();
string? requestedDateTime = null;
ReadOnlyCollection<Group> groups;
List<H2HexColor> h2HexColors = new();
List<H2NoCheckboxes> h2NoCheckboxes = new();
List<H2WithCheckboxes> h2WithCheckboxes = new();
if (markdownFileAndLines.MarkdownFile.LineNumber.FrontMatterYamlEnd is not null)
{
for (int i = 1; i < markdownFileAndLines.Lines.Length; i++)
{
line = markdownFileAndLines.Lines[i];
if (line.Length < 3)
continue;
if (line.Length > 10 && line[..10] == "assigned: ")
{
foreach (string item in line[10..].Split(','))
assignees.Add(item.Trim().Trim('"'));
continue;
}
if (line.Length > 11 && line[..11] == "requested: ")
{
requestedDateTime = line[10..].Trim().Trim('"');
continue;
}
if (line.Length > 3 && line[0] == '#' && line[1] == '#' && line[2] == ' ')
{
completed = 0;
notCompleted = 0;
match = HtmlColor().Match(line[3..]);
if (line.Length > 3 && match.Success)
{
groups = match.Groups.AsReadOnly();
skip = 3 + groups.Skip(1).Sum(l => l.Length);
h2HexColors.Add(new(line[skip..], $"#{groups.First(l => l.Value.Length == 6)}"));
continue;
}
lines = new();
if (i + 1 == markdownFileAndLines.Lines.Length)
continue;
for (int j = i + 1; j < markdownFileAndLines.Lines.Length; j++)
{
line = markdownFileAndLines.Lines[j];
if (line.Length == 0)
continue;
if (line.Length > 2 && line[0] == '#')
break;
lines.Add(line);
if (line.Length < 5 || line[0] != '-' || line[1] != ' ' || line[2] != '[')
continue;
if (line[3] == ' ' && line[4] == ']')
notCompleted++;
else if (line[3] is 'x' or 'X' && line[4] == ']')
completed++;
}
if (completed != 0 || notCompleted != 0)
h2WithCheckboxes.Add(new(completed,
markdownFileAndLines.Lines[i][3..],
notCompleted,
notCompleted + completed));
else if (lines.Count > 0)
h2NoCheckboxes.Add(new(markdownFileAndLines.Lines[i][3..], new(lines)));
continue;
}
}
}
result = new(new(assignees), new(h2HexColors), new(h2NoCheckboxes), new(h2WithCheckboxes), requestedDateTime);
return result;
SaveColumnToCards(input, relativeToCollection);
}
internal static void MarkdownConvertLinksForHugo(AppSettings appSettings, ILogger<Worker> logger, List<string> args)