From 728f45f613d096775ed567ec43887bf2d61d5270 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Fri, 12 Jul 2024 09:41:17 -0700 Subject: [PATCH] Sort HelperMarkdown --- .vscode/tasks.json | 96 ++--- Helpers/HelperMarkdown.cs | 761 ++++++++++++++++---------------------- 2 files changed, 342 insertions(+), 515 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 5338b78..3489de8 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -105,94 +105,50 @@ ], "problemMatcher": "$msCompile" }, - { - "label": "File-Folder-Helper AOT s H Run Data Repository", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository'", - "problemMatcher": [] - }, { "label": "File-Folder-Helper AOT s J Verdaccio", "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s J 'L:/Verdaccio/storage'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s M Self .Kanbn Tasks", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s M L:/DevOps/Mesa_FI/File-Folder-Helper L:/DevOps/Mesa_FI/File-Folder-Helper/.kanbn/tasks", + "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe", + "args": [ + "s", + "J", + "L:/Verdaccio/storage", + ], "problemMatcher": [] }, { "label": "File-Folder-Helper AOT s S BaGet", "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s S 'L:/BaGet/packages'", + "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe", + "args": [ + "s", + "S", + "L:/BaGet/packages", + ], "problemMatcher": [] }, { "label": "File-Folder-Helper AOT s X SortCodeMethods", "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s X L:/DevOps/Mesa_FI/File-Folder-Helper Day-Helper-2024-01-08 L:/DevOps/Mesa_FI/File-Folder-Helper/Day/2024-Q2", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H MET08ANLYSDIFAAST230", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository\\MET08ANLYSDIFAAST230\\Source\\MET08ANLYSDIFAAST230'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H MET08DDUPSFS6420", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository\\MET08DDUPSFS6420\\Source\\MET08DDUPSFS6420'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H MET08DDUPSP1TBI", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository\\MET08DDUPSP1TBI\\Source\\MET08DDUPSP1TBI'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H MET08RESIHGCV", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository\\MET08RESIHGCV\\Source\\MET08RESIHGCV'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H MET08RESIMAPCDE", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository\\MET08RESIMAPCDE\\Source\\MET08RESIMAPCDE'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H MET08RESISRP2100", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository\\MET08RESISRP2100\\Source\\MET08RESISRP2100'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H MET08THFTIRQS408M", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository\\MET08THFTIRQS408M\\Source\\MET08THFTIRQS408M'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H MET08THFTIRSTRATUS", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\Metrology\\Run Data Repository\\MET08THFTIRSTRATUS\\Source\\MET08THFTIRSTRATUS'", - "problemMatcher": [] - }, - { - "label": "File-Folder-Helper AOT s H WaferCounter", - "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s H '\\\\messa01ec.infineon.com\\apps\\WaferCounter\\BackupFiles'", + "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe", + "args": [ + "s", + "X", + "L:/DevOps/Mesa_FI/File-Folder-Helper", + "Day-Helper-2024-01-08", + "L:/DevOps/Mesa_FI/File-Folder-Helper/Helpers" + ], "problemMatcher": [] }, { "label": "File-Folder-Helper AOT s F Staging _Logs", "type": "shell", - "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe s F '\\\\messv02ecc1.ec.local\\EC_EAFLog\\Staging\\_ Logs'", + "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe", + "args": [ + "s", + "F", + "'\\\\messv02ecc1.ec.local\\EC_EAFLog\\Staging\\_ Logs'", + ], "problemMatcher": [] }, { diff --git a/Helpers/HelperMarkdown.cs b/Helpers/HelperMarkdown.cs index 229e285..444681f 100644 --- a/Helpers/HelperMarkdown.cs +++ b/Helpers/HelperMarkdown.cs @@ -55,248 +55,9 @@ internal static partial class HelperMarkdown { } - private static void SetRecursiveLines(AppSettings appSettings, ILogger logger, Input input, ReadOnlyDictionary> keyValuePairs, string linkTitle, MarkdownFile markdownFile, string[] lines, List indentations, List recursiveLines) - { - if (recursiveLines is null) - throw new Exception(); - string file; - string[] segmentsA; - string[] segmentsB; - string segmentsALast; - bool fencedCodeBlock = false; - string indentation = new(indentations.ToArray()); - MarkdownFileH1AndRelativePath markdownFileH1AndRelativePath; - for (int i = 0; i < lines.Length; i++) - { - if (indentations.Count > 15) - { - recursiveLines.Add("```Error```"); - break; - } - if (lines[i].Length < 1) - continue; - if (lines[i].Length > 4 && lines[i][..3] == "```") - fencedCodeBlock = !fencedCodeBlock; - if (fencedCodeBlock) - continue; - if (lines[i][0] == '#') - { - if (lines[i] == $"# {linkTitle}") - continue; - recursiveLines.Add($"{indentation}{lines[i]}"); - continue; - } - segmentsA = lines[i].Split("]("); - if (segmentsA.Length != 2) - continue; - segmentsALast = segmentsA[^1]; - if (appSettings.ExcludeSchemes.Any(l => segmentsALast.StartsWith(l))) - continue; - segmentsB = segmentsALast.Split(")"); - if (segmentsB.Length != 2) - continue; - file = Path.GetFullPath(Path.Combine(markdownFile.Directory, segmentsB[0])); - markdownFileH1AndRelativePath = GetRelativePath(keyValuePairs, markdownFile, file); - if (markdownFileH1AndRelativePath.MarkdownFile is null || markdownFileH1AndRelativePath.H1 is null || markdownFileH1AndRelativePath.RelativePath is null) - { - recursiveLines.Add($"???{indentation}{lines[i]}"); - logger.LogInformation("`{line}' in <{file}>", lines[i], markdownFile.FileName); - if (input.UseProcessStart && File.Exists(markdownFile.File)) - _ = Process.Start(new ProcessStartInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs", "VSCodium", "VSCodium.exe"), markdownFile.File) { WorkingDirectory = input.Source }); - continue; - } - if (markdownFileH1AndRelativePath.Lines is null) - continue; - indentations.Add('\t'); - recursiveLines.Add($"{indentation}{lines[i]}"); - SetRecursiveLines(appSettings, logger, input, keyValuePairs, segmentsA[0].Split('[')[^1], markdownFileH1AndRelativePath.MarkdownFile, markdownFileH1AndRelativePath.Lines, indentations, recursiveLines); - } - if (indentations.Count > 0) - indentations.RemoveAt(0); - } - - private static List GetFrontMatterLines(string[] parsedLines) - { - List results = []; - string afterTrim; - string[] segments; - StringBuilder stringBuilder = new(); - for (int i = 0; i < parsedLines.Length; i++) - { - afterTrim = parsedLines[i].Trim(); - if (string.IsNullOrEmpty(afterTrim) || afterTrim[0] is '{' or '}') - continue; - segments = afterTrim.Split(": "); - if (segments.Length != 2) - { - if (results[^1][^1] == '[') - { - _ = stringBuilder.Clear(); - _ = stringBuilder.Append(results[^1]); - results.RemoveAt(results.Count - 1); - for (int j = i; j < parsedLines.Length; j++) - { - i = j; - afterTrim = parsedLines[j].Trim(); - if (afterTrim == "],") - _ = stringBuilder.Append(afterTrim[..^1]); - else if (afterTrim[^1] == ',') - _ = stringBuilder.Append(afterTrim).Append(' '); - else - _ = stringBuilder.Append(afterTrim); - if (afterTrim is "]" or "],") - { - results.Add(stringBuilder.ToString()); - break; - } - } - continue; - } - results.Clear(); - break; - } - if (afterTrim[^1] != ',') - results.Add(afterTrim[1..].Replace("\": ", ": ")); - else - results.Add(afterTrim[1..^1].Replace("\": ", ": ")); - } - return results; - } - - /// - /// Determines files text file's encoding by analyzing its byte order mark (BOM). - /// Defaults to ASCII when detection of the text file's endianness fails. - /// - /// The text file to analyze. - /// The detected encoding. - private static Encoding? GetEncoding(string filename) - { - Encoding? result; - byte[] bom = new byte[4]; - using FileStream file = new(filename, FileMode.Open, FileAccess.Read); - _ = file.Read(bom, 0, 4); - if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76) -#pragma warning disable SYSLIB0001 - result = Encoding.UTF7; -#pragma warning restore SYSLIB0001 - if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) - result = Encoding.UTF8; - if (bom[0] == 0xff && bom[1] == 0xfe && bom[2] == 0 && bom[3] == 0) - result = Encoding.UTF32; //UTF-32LE - if (bom[0] == 0xff && bom[1] == 0xfe) - result = Encoding.Unicode; //UTF-16LE - if (bom[0] == 0xfe && bom[1] == 0xff) - result = Encoding.BigEndianUnicode; //UTF-16BE - if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff) - result = new UTF32Encoding(true, true); //UTF-32BE - else - result = null; - return result; - } - [GeneratedRegex("(~~)?(#)([a-zA-Z0-9]{6})(~~)?( )")] private static partial Regex HtmlColor(); - private static List GetMarkdownFileAndLines(string file, List markdownFiles) - { - List results = []; - List distinct = []; - string? directory = Path.GetDirectoryName(file); - foreach (MarkdownFileAndLines markdownFileAndLines in markdownFiles) - { - if (string.IsNullOrEmpty(directory) || markdownFileAndLines.MarkdownFile.Directory != directory) - continue; - if (distinct.Contains(markdownFileAndLines.MarkdownFile.File)) - continue; - distinct.Add(markdownFileAndLines.MarkdownFile.File); - results.Add(markdownFileAndLines); - } - return results; - } - - private static (string?, Dictionary?, List) Get(List jsonLines) - { - string? result; - List results; - string jsonLinesLast = jsonLines[^1]; - jsonLines.RemoveAt(jsonLines.Count - 1); - jsonLines.Add(jsonLinesLast[..^1]); - jsonLines.Insert(0, "{"); - jsonLines.Add("}"); - Dictionary? keyValuePairs; - result = string.Join(Environment.NewLine, jsonLines); - keyValuePairs = JsonSerializer.Deserialize(result, DictionaryStringAndJsonElementSourceGenerationContext.Default.DictionaryStringJsonElement); - if (keyValuePairs is null) - throw new NullReferenceException(nameof(keyValuePairs)); - result = JsonSerializer.Serialize(keyValuePairs, DictionaryStringAndJsonElementSourceGenerationContext.Default.DictionaryStringJsonElement); - string[] parsedLines = result.Split(Environment.NewLine).ToArray(); - results = GetFrontMatterLines(parsedLines); - if (results.Count == 0) - { - result = null; - keyValuePairs = null; - } - return (result, keyValuePairs, results); - } - - internal static (List, LineNumber) GetStatusAndFrontMatterYamlEndLineNumbers(FileInfo fileInfo) - { - string line; - int? h1LineNumber = null; - int? typeLineNumber = null; - int? statusLineNumber = null; - int? createdLineNumber = null; - int? updatedLineNumber = null; - int? frontMatterYamlEndLineNumber = null; - Encoding? encoding = GetEncoding(fileInfo.FullName) ?? Encoding.Default; - string[] lines = File.ReadAllLines(fileInfo.FullName, encoding); - for (int i = 0; i < lines.Length; i++) - { - line = lines[i]; - if (line.Length < 3) - continue; - if (i == 0 && line[..3] == "---") - continue; - if (h1LineNumber is null && line[..3] == "---") - { - frontMatterYamlEndLineNumber = i; - continue; - } - if (line.Length > 6 && line[..6] == "type: ") - { - typeLineNumber = i; - continue; - } - if (line.Length > 8 && line[..8] == "status: ") - { - statusLineNumber = i; - continue; - } - if (line.Length > 9 && line[..9] == "created: ") - { - createdLineNumber = i; - continue; - } - if (line.Length > 9 && line[..9] == "updated: ") - { - updatedLineNumber = i; - continue; - } - if (h1LineNumber is null && line.Length > 2 && line[0] == '#' && line[1] == ' ') - { - h1LineNumber = i; - continue; - } - } - LineNumber lineNumber = new(createdLineNumber, - h1LineNumber, - frontMatterYamlEndLineNumber, - statusLineNumber, - typeLineNumber, - updatedLineNumber); - return (lines.ToList(), lineNumber); - } - private static MarkdownExtra GetMarkdownExtra(MarkdownFileAndLines markdownFileAndLines) { MarkdownExtra result; @@ -381,6 +142,129 @@ internal static partial class HelperMarkdown return result; } + private static List GetMarkdownFileAndLines(string file, List markdownFiles) + { + List results = []; + List distinct = []; + string? directory = Path.GetDirectoryName(file); + foreach (MarkdownFileAndLines markdownFileAndLines in markdownFiles) + { + if (string.IsNullOrEmpty(directory) || markdownFileAndLines.MarkdownFile.Directory != directory) + continue; + if (distinct.Contains(markdownFileAndLines.MarkdownFile.File)) + continue; + distinct.Add(markdownFileAndLines.MarkdownFile.File); + results.Add(markdownFileAndLines); + } + return results; + } + + private static string[] GetFiles(AppSettings appSettings, string directory, SearchOption searchOption) + { + string[] results = Directory.GetFiles(directory, "*.md", searchOption). + Where(l => !appSettings.ExcludeDirectoryNames.Any(m => l.Contains(m))).ToArray(); + return results; + } + + /// + /// Determines files text file's encoding by analyzing its byte order mark (BOM). + /// Defaults to ASCII when detection of the text file's endianness fails. + /// + /// The text file to analyze. + /// The detected encoding. + private static Encoding? GetEncoding(string filename) + { + Encoding? result; + byte[] bom = new byte[4]; + using FileStream file = new(filename, FileMode.Open, FileAccess.Read); + _ = file.Read(bom, 0, 4); + if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76) +#pragma warning disable SYSLIB0001 + result = Encoding.UTF7; +#pragma warning restore SYSLIB0001 + if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) + result = Encoding.UTF8; + if (bom[0] == 0xff && bom[1] == 0xfe && bom[2] == 0 && bom[3] == 0) + result = Encoding.UTF32; //UTF-32LE + if (bom[0] == 0xff && bom[1] == 0xfe) + result = Encoding.Unicode; //UTF-16LE + if (bom[0] == 0xfe && bom[1] == 0xff) + result = Encoding.BigEndianUnicode; //UTF-16BE + if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff) + result = new UTF32Encoding(true, true); //UTF-32BE + else + result = null; + return result; + } + + private static ReadOnlyCollection GetFromMatterYamlLines(List lines, LineNumber lineNumber) + { + List results = []; + if (lineNumber.FrontMatterYamlEnd is not null && lines.Count >= lineNumber.FrontMatterYamlEnd.Value) + { + for (int i = 1; i < lineNumber.FrontMatterYamlEnd.Value; i++) + results.Add(lines[i]); + } + return new(results); + } + + private static List GetKeys(ReadOnlyDictionary relativeToCollection) + { + List results = []; + MarkdownFile markdownFile; + foreach (KeyValuePair relativeTo in relativeToCollection) + { + markdownFile = relativeTo.Value.MarkdownFile; + if (markdownFile.IsKanbanMarkdown) + continue; + results.Add(relativeTo.Key); + } + return results; + } + + private static void SetCards(Input input, ReadOnlyDictionary relativeToCollection, List notLinkedKey, MarkdownFile markdownFile, string[] lines, List cards, List allKeys, int i) + { + Card card; + string key; + string[] segmentsA; + MarkdownExtra markdownExtra; + MarkdownFileAndLines? markdownFileAndLines; + 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 (!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); + if (allKeys.Remove(key)) + cards.Add(card); + else + notLinkedKey.Add(card); + } + } + private static List Distinct(IEnumerable? markdownFileAndLinesCollection) { List results = []; @@ -409,6 +293,94 @@ internal static partial class HelperMarkdown return results; } + private static ReadOnlyCollection GetFiles(AppSettings appSettings, Input input) + { + List results = []; + List files = []; + string[] directories = Directory.GetDirectories(input.Source, "*", SearchOption.AllDirectories); + foreach (string directory in directories) + { + files.Clear(); + files.AddRange(GetFiles(appSettings, directory, SearchOption.TopDirectoryOnly)); + foreach (string file in files) + results.Add(file); + } + return new(results); + } + + internal static (List, LineNumber) GetStatusAndFrontMatterYamlEndLineNumbers(FileInfo fileInfo) + { + string line; + int? h1LineNumber = null; + int? typeLineNumber = null; + int? statusLineNumber = null; + int? createdLineNumber = null; + int? updatedLineNumber = null; + int? frontMatterYamlEndLineNumber = null; + Encoding? encoding = GetEncoding(fileInfo.FullName) ?? Encoding.Default; + string[] lines = File.ReadAllLines(fileInfo.FullName, encoding); + for (int i = 0; i < lines.Length; i++) + { + line = lines[i]; + if (line.Length < 3) + continue; + if (i == 0 && line[..3] == "---") + continue; + if (h1LineNumber is null && line[..3] == "---") + { + frontMatterYamlEndLineNumber = i; + continue; + } + if (line.Length > 6 && line[..6] == "type: ") + { + typeLineNumber = i; + continue; + } + if (line.Length > 8 && line[..8] == "status: ") + { + statusLineNumber = i; + continue; + } + if (line.Length > 9 && line[..9] == "created: ") + { + createdLineNumber = i; + continue; + } + if (line.Length > 9 && line[..9] == "updated: ") + { + updatedLineNumber = i; + continue; + } + if (h1LineNumber is null && line.Length > 2 && line[0] == '#' && line[1] == ' ') + { + h1LineNumber = i; + continue; + } + } + LineNumber lineNumber = new(createdLineNumber, + h1LineNumber, + frontMatterYamlEndLineNumber, + statusLineNumber, + typeLineNumber, + updatedLineNumber); + return (lines.ToList(), lineNumber); + } + + private static ReadOnlyDictionary GetFromMatterYaml(List lines, LineNumber lineNumber) + { + Dictionary results = []; + IDeserializer deserializer = new DeserializerBuilder().Build(); + ReadOnlyCollection frontMatterYamlLines = GetFromMatterYamlLines(lines, lineNumber); + string frontMatterYaml = string.Join(Environment.NewLine, frontMatterYamlLines); + Dictionary? keyValuePairs = deserializer.Deserialize>(frontMatterYaml); + if (keyValuePairs is not null) + { + foreach (string key in keyValuePairs.Keys.OrderBy(l => l)) + results.Add(key, keyValuePairs[key]); + } + return new(results); + } + private static ReadOnlyDictionary> GetKeyValuePairs(ReadOnlyDictionary relativeToCollection) { Dictionary> results = []; @@ -518,68 +490,6 @@ internal static partial class HelperMarkdown return result; } - private static string[] GetFiles(AppSettings appSettings, string directory, SearchOption searchOption) - { - string[] results = Directory.GetFiles(directory, "*.md", searchOption). - Where(l => !appSettings.ExcludeDirectoryNames.Any(m => l.Contains(m))).ToArray(); - return results; - } - - private static ReadOnlyCollection GetFiles(AppSettings appSettings, Input input) - { - List results = []; - List files = []; - string[] directories = Directory.GetDirectories(input.Source, "*", SearchOption.AllDirectories); - foreach (string directory in directories) - { - files.Clear(); - files.AddRange(GetFiles(appSettings, directory, SearchOption.TopDirectoryOnly)); - foreach (string file in files) - results.Add(file); - } - return new(results); - } - - private static ReadOnlyCollection GetFromMatterYamlLines(List lines, LineNumber lineNumber) - { - List results = []; - if (lineNumber.FrontMatterYamlEnd is not null && lines.Count >= lineNumber.FrontMatterYamlEnd.Value) - { - for (int i = 1; i < lineNumber.FrontMatterYamlEnd.Value; i++) - results.Add(lines[i]); - } - return new(results); - } - - private static ReadOnlyDictionary GetFromMatterYaml(List lines, LineNumber lineNumber) - { - Dictionary results = []; - IDeserializer deserializer = new DeserializerBuilder().Build(); - ReadOnlyCollection frontMatterYamlLines = GetFromMatterYamlLines(lines, lineNumber); - string frontMatterYaml = string.Join(Environment.NewLine, frontMatterYamlLines); - Dictionary? keyValuePairs = deserializer.Deserialize>(frontMatterYaml); - if (keyValuePairs is not null) - { - foreach (string key in keyValuePairs.Keys.OrderBy(l => l)) - results.Add(key, keyValuePairs[key]); - } - return new(results); - } - - private static List GetKeys(ReadOnlyDictionary relativeToCollection) - { - List results = []; - MarkdownFile markdownFile; - foreach (KeyValuePair relativeTo in relativeToCollection) - { - markdownFile = relativeTo.Value.MarkdownFile; - if (markdownFile.IsKanbanMarkdown) - continue; - results.Add(relativeTo.Key); - } - return results; - } - private static MarkdownFileAndLines? GetKanbanIndexMarkdownFileAndLines(ReadOnlyDictionary keyValuePairs) { MarkdownFile markdownFile; @@ -600,49 +510,6 @@ internal static partial class HelperMarkdown return result; } - private static void SetCards(Input input, ReadOnlyDictionary relativeToCollection, List notLinkedKey, MarkdownFile markdownFile, string[] lines, List cards, List allKeys, int i) - { - Card card; - string key; - string[] segmentsA; - MarkdownExtra markdownExtra; - MarkdownFileAndLines? markdownFileAndLines; - 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 (!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); - if (allKeys.Remove(key)) - cards.Add(card); - else - notLinkedKey.Add(card); - } - } - private static ReadOnlyDictionary> GetColumnsToCards(Input input, ReadOnlyDictionary relativeToCollection, MarkdownFileAndLines markdownFileAndLines) { Dictionary> results = []; @@ -756,6 +623,105 @@ internal static partial class HelperMarkdown return result; } + private static ReadOnlyDictionary GetRelativeToCollection(AppSettings appSettings, Input input, ReadOnlyCollection gitOthersModifiedAndDeletedExcludingStandardFiles) + { + Dictionary results = []; + string h1; + string key; + string type; + FileInfo fileInfo; + bool isKanbanIndex; + List lines; + bool isWithinSource; + bool isKanbanMarkdown; + LineNumber lineNumber; + MarkdownFile markdownFile; + string fileNameWithoutExtension; + ReadOnlyDictionary frontMatterYaml; + bool isGitOthersModifiedAndDeletedExcludingStandard; + ReadOnlyCollection files = GetFiles(appSettings, input); + foreach (string file in files) + { // cSpell:disable + fileInfo = new(file); + if (fileInfo.DirectoryName is null) + continue; + key = Path.GetRelativePath(input.Source, file); + isWithinSource = file.Contains(input.Source); + isGitOthersModifiedAndDeletedExcludingStandard = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(file); + if (!isWithinSource && results.ContainsKey(key)) + continue; + (lines, lineNumber) = GetStatusAndFrontMatterYamlEndLineNumbers(fileInfo); + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName); + h1 = fileNameWithoutExtension.ToLower().Replace("%20", "-").Replace(' ', '-'); + frontMatterYaml = GetFromMatterYaml(lines, lineNumber); + if (lines.Count > 0) + (type, h1) = GetTypeAndH1(appSettings, h1, lines, lineNumber); + else + { + if (!isGitOthersModifiedAndDeletedExcludingStandard) + continue; + type = appSettings.DefaultNoteType; + File.WriteAllLines(file, ["---", $"type: {type}\"", "---", string.Empty, $"# {h1}"]); + lines = File.ReadAllLines(file).ToList(); + } + isKanbanMarkdown = fileInfo.Name.EndsWith(".knb.md"); + isKanbanIndex = fileNameWithoutExtension == "index" && type.StartsWith("kanb", StringComparison.OrdinalIgnoreCase); + markdownFile = new(fileInfo.CreationTime, + fileInfo.DirectoryName, + fileInfo.Extension, + file, + fileInfo.Name, + fileNameWithoutExtension, + frontMatterYaml, + h1, + isGitOthersModifiedAndDeletedExcludingStandard, + isKanbanIndex, + isKanbanMarkdown, + fileInfo.LastWriteTime, + lineNumber, + type); + results.Add(key, new(markdownFile, lines.ToArray())); + } // cSpell:restore + return new(results); + } + + private static int SortFrontMatter(AppSettings appSettings, ILogger logger, Input input, ReadOnlyDictionary relativeToCollection) + { + int result = 0; + List results = []; + string[] lines; + string frontMatterYaml; + MarkdownFile markdownFile; + string[] frontMatterYamlLines; + ISerializer serializer = new SerializerBuilder().WithIndentedSequences().Build(); + foreach (KeyValuePair relativeTo in relativeToCollection) + { + results.Clear(); + if (relativeTo.Value.Lines.Length < 2) + continue; + lines = relativeTo.Value.Lines; + markdownFile = relativeTo.Value.MarkdownFile; + if (markdownFile.IsKanbanMarkdown) + continue; + if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard) + continue; + if (markdownFile.LineNumber.FrontMatterYamlEnd is null) + continue; + frontMatterYaml = serializer.Serialize(markdownFile.FrontMatterYaml).Trim(); + frontMatterYamlLines = frontMatterYaml.Split(Environment.NewLine); + results.Add("---"); + results.AddRange(frontMatterYamlLines); + for (int i = markdownFile.LineNumber.FrontMatterYamlEnd.Value; i < lines.Length; i++) + results.Add(lines[i]); + if (results.Count == lines.Length && string.Join('\r', lines) == string.Join('\r', results)) + continue; + File.WriteAllLines(markdownFile.File, results); + File.SetLastWriteTime(markdownFile.File, markdownFile.LastWriteDateTime); + result += 1; + } + return result; + } + private static int CircularReference(ILogger logger, ReadOnlyDictionary relativeToCollection) { int result = 0; @@ -886,7 +852,7 @@ internal static partial class HelperMarkdown write = false; lines = relativeTo.Value.Lines; markdownFile = relativeTo.Value.MarkdownFile; - if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard) + if (!input.UseProcessStart && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard) continue; for (int i = 0; i < lines.Length; i++) { @@ -914,6 +880,8 @@ internal static partial class HelperMarkdown } if (!write) continue; + if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard) + continue; File.WriteAllLines(markdownFile.File, lines); result += 1; } @@ -947,7 +915,7 @@ internal static partial class HelperMarkdown markdownFile = relativeTo.Value.MarkdownFile; if (markdownFile.IsKanbanIndex) continue; - if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard) + if (!input.UseProcessStart && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard) continue; if (!File.Exists(markdownFile.File)) continue; @@ -1012,6 +980,8 @@ internal static partial class HelperMarkdown } if (!write) continue; + if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard) + continue; File.WriteAllLines(markdownFile.File, lines); result += 1; } @@ -1020,68 +990,6 @@ internal static partial class HelperMarkdown return result; } - private static ReadOnlyDictionary GetRelativeToCollection(AppSettings appSettings, Input input, ReadOnlyCollection gitOthersModifiedAndDeletedExcludingStandardFiles) - { - Dictionary results = []; - string h1; - string key; - string type; - FileInfo fileInfo; - bool isKanbanIndex; - List lines; - bool isWithinSource; - bool isKanbanMarkdown; - LineNumber lineNumber; - MarkdownFile markdownFile; - string fileNameWithoutExtension; - ReadOnlyDictionary frontMatterYaml; - bool isGitOthersModifiedAndDeletedExcludingStandard; - ReadOnlyCollection files = GetFiles(appSettings, input); - foreach (string file in files) - { // cSpell:disable - fileInfo = new(file); - if (fileInfo.DirectoryName is null) - continue; - key = Path.GetRelativePath(input.Source, file); - isWithinSource = file.Contains(input.Source); - isGitOthersModifiedAndDeletedExcludingStandard = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(file); - if (!isWithinSource && results.ContainsKey(key)) - continue; - (lines, lineNumber) = GetStatusAndFrontMatterYamlEndLineNumbers(fileInfo); - fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName); - h1 = fileNameWithoutExtension.ToLower().Replace("%20", "-").Replace(' ', '-'); - frontMatterYaml = GetFromMatterYaml(lines, lineNumber); - if (lines.Count > 0) - (type, h1) = GetTypeAndH1(appSettings, h1, lines, lineNumber); - else - { - if (!isGitOthersModifiedAndDeletedExcludingStandard) - continue; - type = appSettings.DefaultNoteType; - File.WriteAllLines(file, ["---", $"type: {type}\"", "---", string.Empty, $"# {h1}"]); - lines = File.ReadAllLines(file).ToList(); - } - isKanbanMarkdown = fileInfo.Name.EndsWith(".knb.md"); - isKanbanIndex = fileNameWithoutExtension == "index" && type.StartsWith("kanb", StringComparison.OrdinalIgnoreCase); - markdownFile = new(fileInfo.CreationTime, - fileInfo.DirectoryName, - fileInfo.Extension, - file, - fileInfo.Name, - fileNameWithoutExtension, - frontMatterYaml, - h1, - isGitOthersModifiedAndDeletedExcludingStandard, - isKanbanIndex, - isKanbanMarkdown, - fileInfo.LastWriteTime, - lineNumber, - type); - results.Add(key, new(markdownFile, lines.ToArray())); - } // cSpell:restore - return new(results); - } - private static void SaveColumnToCards(Input input, ReadOnlyDictionary relativeToCollection) { if (string.IsNullOrEmpty(input.Destination)) @@ -1223,43 +1131,6 @@ internal static partial class HelperMarkdown return new(result?.MarkdownFile, result?.Lines, result?.MarkdownFile.H1, result is null ? null : Path.GetRelativePath(markdownFile.Directory, Path.GetFullPath(result.MarkdownFile.File))); } - private static int SortFrontMatter(AppSettings appSettings, ILogger logger, Input input, ReadOnlyDictionary relativeToCollection) - { - int result = 0; - List results = []; - string[] lines; - string frontMatterYaml; - MarkdownFile markdownFile; - string[] frontMatterYamlLines; - ISerializer serializer = new SerializerBuilder().WithIndentedSequences().Build(); - foreach (KeyValuePair relativeTo in relativeToCollection) - { - results.Clear(); - if (relativeTo.Value.Lines.Length < 2) - continue; - lines = relativeTo.Value.Lines; - markdownFile = relativeTo.Value.MarkdownFile; - if (markdownFile.IsKanbanMarkdown) - continue; - if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard) - continue; - if (markdownFile.LineNumber.FrontMatterYamlEnd is null) - continue; - frontMatterYaml = serializer.Serialize(markdownFile.FrontMatterYaml).Trim(); - frontMatterYamlLines = frontMatterYaml.Split(Environment.NewLine); - results.Add("---"); - results.AddRange(frontMatterYamlLines); - for (int i = markdownFile.LineNumber.FrontMatterYamlEnd.Value; i < lines.Length; i++) - results.Add(lines[i]); - if (results.Count == lines.Length && string.Join('\r', lines) == string.Join('\r', results)) - continue; - File.WriteAllLines(markdownFile.File, results); - File.SetLastWriteTime(markdownFile.File, markdownFile.LastWriteDateTime); - result += 1; - } - return result; - } - internal static void MarkdownWikiLinkVerification(AppSettings appSettings, ILogger logger, List args, CancellationToken cancellationToken) { int updated;