diff --git a/.vscode/launch.json b/.vscode/launch.json index 0a8ea35..5ac05c4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,9 +12,11 @@ "program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll", "args": [ "s", - "K", - ".kanbn" - ], + "M", + "L:/Git/Notes-Infineon/.Infineon", + "-d", + "L:/Git/Notes-Infineon/.Infineon/.vscode/helper" + ], "cwd": "${workspaceFolder}", "console": "integratedTerminal", "stopAtEntry": false diff --git a/.vscode/settings.json b/.vscode/settings.json index e6247ad..4b87e1d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -31,6 +31,7 @@ "onenote", "pged", "Phares", + "Reparse", "Rijndael", "Serilog", "SUBM", diff --git a/Helpers/HelperGit.cs b/Helpers/HelperGit.cs index c7a1e1b..09eec1e 100644 --- a/Helpers/HelperGit.cs +++ b/Helpers/HelperGit.cs @@ -43,22 +43,39 @@ internal static class HelperGit return result.Output; } + private static List GetOthersModifiedAndDeletedExcludingStandardFilesAsList(string repositoryDirectory, bool usePathCombine, CancellationToken cancellationToken) + { + List results = []; + Task task = RunAsync($"ls-files --others --modified --deleted --exclude-standard", repositoryDirectory, cancellationToken); + task.Wait(cancellationToken); + string[] files = task.Result.Split("\r\n"); + foreach (string file in files) + { + if (!usePathCombine) + results.Add(file); + else + results.Add(Path.GetFullPath(Path.Combine(repositoryDirectory, file))); + } + return results; + } + internal static ReadOnlyCollection GetOthersModifiedAndDeletedExcludingStandardFiles(string repositoryDirectory, bool usePathCombine, CancellationToken cancellationToken) { List results = []; + DirectoryInfo directoryInfo; string checkDirectory = Path.Combine(repositoryDirectory, ".git"); if (Directory.Exists(checkDirectory)) + results.AddRange(GetOthersModifiedAndDeletedExcludingStandardFilesAsList(repositoryDirectory, usePathCombine, cancellationToken)); + string[] subdirectories = Directory.GetDirectories(repositoryDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string subdirectory in subdirectories) { - Task task = RunAsync($"ls-files --others --modified --deleted --exclude-standard", repositoryDirectory, cancellationToken); - task.Wait(cancellationToken); - string[] files = task.Result.Split("\r\n"); - foreach (string file in files) - { - if (!usePathCombine) - results.Add(file); - else - results.Add(Path.GetFullPath(Path.Combine(repositoryDirectory, file))); - } + directoryInfo = new(subdirectory); + if (directoryInfo.LinkTarget is null) + continue; + checkDirectory = Path.Combine(directoryInfo.LinkTarget, ".git"); + if (!Directory.Exists(checkDirectory)) + continue; + results.AddRange(GetOthersModifiedAndDeletedExcludingStandardFilesAsList(directoryInfo.LinkTarget, usePathCombine, cancellationToken)); } return new(results); } diff --git a/Helpers/HelperKanbanMetadata.cs b/Helpers/HelperKanbanMetadata.cs index c80675d..dc88549 100644 --- a/Helpers/HelperKanbanMetadata.cs +++ b/Helpers/HelperKanbanMetadata.cs @@ -160,7 +160,7 @@ internal static partial class HelperKanbanMetadata results.Add(lines[i]); } } - results.Add($"status: \"{record.GroupCount}-{record.Group}\""); + results.Add($"status: {record.GroupCount}-{record.Group}"); results.Add("```"); results.Add(string.Empty); } @@ -201,7 +201,7 @@ internal static partial class HelperKanbanMetadata (lines, lineNumber) = HelperMarkdown.GetStatusAndFrontMatterYamlEndLineNumbers(record.FileInfo); if (lines.Count == 0) continue; - statusLine = $"status: \"{record.GroupCount}-{record.Group}\""; + statusLine = $"status: {record.GroupCount}-{record.Group}"; paramCase = lineNumber.H1 is null ? null : GetParamCase(lines[lineNumber.H1.Value]); match = lineNumber.H1 is null || paramCase is null ? null : Path.GetFileNameWithoutExtension(record.FileInfo.Name) == paramCase; if (lineNumber.FrontMatterYamlEnd is null) diff --git a/Helpers/HelperMarkdown.cs b/Helpers/HelperMarkdown.cs index 74b5e59..59072fc 100644 --- a/Helpers/HelperMarkdown.cs +++ b/Helpers/HelperMarkdown.cs @@ -14,8 +14,7 @@ internal static partial class HelperMarkdown { private record Input(string? Destination, - string Source, - string? StartAt); + string Source); private record Record(string Directory, string File, @@ -98,7 +97,7 @@ internal static partial class HelperMarkdown if (markdownFileH1AndRelativePath.MarkdownFile is null || markdownFileH1AndRelativePath.H1 is null || markdownFileH1AndRelativePath.RelativePath is null) { recursiveLines.Add($"???{indentation}{lines[i]}"); - logger.LogInformation("Didn't find {line} in <{file}>", lines[i], markdownFile.FileNameWithoutExtension); + logger.LogInformation("Didn't find '{line}' in <{file}>", lines[i], markdownFile.FileName); continue; } if (markdownFileH1AndRelativePath.Lines is null) @@ -516,13 +515,38 @@ internal static partial class HelperMarkdown return result; } - private static string[] GetFiles(AppSettings appSettings, string directory) + private static string[] GetFiles(AppSettings appSettings, string directory, SearchOption searchOption) { - string[] results = Directory.GetFiles(directory, "*.md", SearchOption.AllDirectories). + 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 = []; + FileInfo fileInfo; + List files = []; + DirectoryInfo directoryInfo; + string[] directories = Directory.GetDirectories(input.Source, "*", SearchOption.AllDirectories); + foreach (string directory in directories) + { + files.Clear(); + directoryInfo = new(directory); + files.AddRange(GetFiles(appSettings, directory, SearchOption.TopDirectoryOnly)); + if (directoryInfo.LinkTarget is not null) + files.AddRange(GetFiles(appSettings, directoryInfo.LinkTarget, SearchOption.AllDirectories)); + foreach (string file in files) + { + results.Add(file); + fileInfo = new(file); + if (fileInfo.LinkTarget is not null) + results.Add(fileInfo.LinkTarget); + } + } + return new(results); + } + private static ReadOnlyCollection GetFromMatterYamlLines(List lines, LineNumber lineNumber) { List results = []; @@ -549,65 +573,6 @@ internal static partial class HelperMarkdown return new(results); } - private static ReadOnlyDictionary GetRelativeToCollection(AppSettings appSettings, Input input, string[] files, ReadOnlyCollection gitOthersModifiedAndDeletedExcludingStandardFiles, bool force) - { - Dictionary results = []; - string h1; - string key; - string type; - bool gitCheck; - FileInfo fileInfo; - bool isKanbanIndex; - List lines; - bool isKanbanMarkdown; - LineNumber lineNumber; - MarkdownFile markdownFile; - string fileNameWithoutExtension; - ReadOnlyDictionary frontMatterYaml; - foreach (string file in files) - { // cSpell:disable - fileInfo = new(file); - if (fileInfo.DirectoryName is null) - continue; - key = Path.GetRelativePath(input.Source, file); - (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 - { - gitCheck = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(file); - if (!gitCheck) - 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, - isKanbanIndex, - isKanbanMarkdown, - fileInfo.LastWriteTime, - lineNumber, - type); - if (force || input.StartAt is null || file.StartsWith(input.StartAt)) - results.Add(key, new(markdownFile, lines.ToArray())); - else - results.Add(key, new(markdownFile, [])); - } // cSpell:restore - return new(results); - } - private static List GetKeys(ReadOnlyDictionary relativeToCollection) { List results = []; @@ -772,24 +737,17 @@ internal static partial class HelperMarkdown private static Input GetInput(List args) { Input result; - string? startAt = null; string? destination = null; string source = Path.GetFullPath(args[0]); for (int i = 1; i < args.Count; i++) { if (args[i].Length == 2 && i + 1 < args.Count) { - if (args[i][1] == 's') - startAt = Path.GetFullPath(args[i + 1]); - else if (args[i][1] == 'd') + if (args[i][1] == 'd') destination = Path.GetFullPath(args[i + 1]); i++; } } - if (startAt is not null && !Directory.Exists(startAt)) - throw new Exception($"Start at directory <{startAt}> doesn't exist!"); - if (startAt is not null && startAt.Length < source.Length) - throw new Exception($"Start at directory <{startAt}> must be a subdirectory!"); if (destination is not null) { string? root = Path.GetPathRoot(destination); @@ -798,7 +756,7 @@ internal static partial class HelperMarkdown if (!Directory.Exists(destination)) _ = Directory.CreateDirectory(destination); } - result = new(destination, source, startAt); + result = new(destination, source); return result; } @@ -949,7 +907,7 @@ internal static partial class HelperMarkdown markdownFileH1AndRelativePath = GetRelativePath(keyValuePairs, markdownFile, segmentsC[0]); if (markdownFileH1AndRelativePath.MarkdownFile is null || markdownFileH1AndRelativePath.H1 is null || markdownFileH1AndRelativePath.RelativePath is null) { - logger.LogInformation("Didn't find {line} in <{file}>", lines[i], markdownFile.FileNameWithoutExtension); + logger.LogInformation("Didn't find '{line}' in <{file}>", lines[i], markdownFile.FileName); continue; } line = $"{segmentsB[0]}[{markdownFileH1AndRelativePath.H1}]({markdownFileH1AndRelativePath.RelativePath.Replace('\\', '/')}){segmentsA[^1]}"; @@ -1024,7 +982,7 @@ internal static partial class HelperMarkdown markdownFileH1AndRelativePath = GetRelativePath(keyValuePairs, markdownFile, file); if (markdownFileH1AndRelativePath.MarkdownFile is null || markdownFileH1AndRelativePath.H1 is null || markdownFileH1AndRelativePath.RelativePath is null) { - logger.LogInformation("Didn't find {line} in <{file}>", lines[i], markdownFile.FileNameWithoutExtension); + logger.LogInformation("Didn't find '{line}' in <{file}>", lines[i], markdownFile.FileName); continue; } line = $"{string.Join('[', segmentsC, 0, segmentsC.Length - 1)}[{markdownFileH1AndRelativePath.H1}]({markdownFileH1AndRelativePath.RelativePath.Replace('\\', '/')}){segmentsB[^1]}"; @@ -1070,11 +1028,60 @@ internal static partial class HelperMarkdown return result; } - private static ReadOnlyDictionary GetRelativeToCollection(AppSettings appSettings, Input input, ReadOnlyCollection gitOthersModifiedAndDeletedExcludingStandardFiles, bool force = false) + private static ReadOnlyDictionary GetRelativeToCollection(AppSettings appSettings, Input input, ReadOnlyCollection gitOthersModifiedAndDeletedExcludingStandardFiles) { - ReadOnlyDictionary results; - string[] files = GetFiles(appSettings, input.Source); - results = GetRelativeToCollection(appSettings, input, files, gitOthersModifiedAndDeletedExcludingStandardFiles, force); + Dictionary results = []; + string h1; + string key; + string type; + bool gitCheck; + FileInfo fileInfo; + bool isKanbanIndex; + List lines; + bool isKanbanMarkdown; + LineNumber lineNumber; + MarkdownFile markdownFile; + string fileNameWithoutExtension; + ReadOnlyDictionary frontMatterYaml; + ReadOnlyCollection files = GetFiles(appSettings, input); + foreach (string file in files) + { // cSpell:disable + fileInfo = new(file); + if (fileInfo.DirectoryName is null) + continue; + key = !file.Contains(input.Source) ? file : Path.GetRelativePath(input.Source, file); + (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 + { + gitCheck = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(file); + if (!gitCheck) + 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, + isKanbanIndex, + isKanbanMarkdown, + fileInfo.LastWriteTime, + lineNumber, + type); + results.Add(key, new(markdownFile, lines.ToArray())); + } // cSpell:restore return new(results); } @@ -1090,8 +1097,6 @@ internal static partial class HelperMarkdown { if (relativeTo.Value.Lines.Length == 0) continue; - if (input.StartAt is null || !relativeTo.Value.MarkdownFile.File.StartsWith(input.StartAt) || Path.GetFileName(relativeTo.Value.MarkdownFile.Directory) != Path.GetFileName(input.StartAt)) - continue; indentations = []; recursiveLines = []; lines = relativeTo.Value.Lines; @@ -1102,23 +1107,9 @@ internal static partial class HelperMarkdown return results; } - private static void Write(Input input, List markdownFileAndLinesCollection, ReadOnlyCollection gitOthersModifiedAndDeletedExcludingStandardFiles) - { - bool gitCheck; - foreach (MarkdownFileAndLines markdownFileAndLines in markdownFileAndLinesCollection) - { - if (input.Destination is null) - continue; - gitCheck = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(markdownFileAndLines.MarkdownFile.File); - if (!gitCheck) - continue; - File.WriteAllLines(Path.Combine(input.Destination, markdownFileAndLines.MarkdownFile.FileName), markdownFileAndLines.Lines); - } - } - private static void SaveColumnToCards(Input input, ReadOnlyDictionary relativeToCollection) { - if (string.IsNullOrEmpty(input.StartAt) || string.IsNullOrEmpty(input.Destination)) + if (string.IsNullOrEmpty(input.Destination)) throw new NotSupportedException(); MarkdownFileAndLines? markdownFileAndLines = GetKanbanIndexMarkdownFileAndLines(relativeToCollection); if (markdownFileAndLines is not null && File.Exists(markdownFileAndLines.MarkdownFile.File)) @@ -1171,12 +1162,12 @@ internal static partial class HelperMarkdown if (markdownFile.IsKanbanMarkdown) continue; results.AddRange(lines); - typeLine = $"type: \"{appSettings.DefaultNoteType}\""; + typeLine = $"type: {appSettings.DefaultNoteType}"; h1Line = $"# {markdownFile.FileNameWithoutExtension}"; creationDateTime = markdownFile.CreationDateTime > markdownFile.LastWriteDateTime ? markdownFile.LastWriteDateTime : markdownFile.CreationDateTime; gitCheck = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(markdownFile.File); - createdLine = $"created: \"{creationDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}\""; - updatedLine = $"updated: \"{markdownFile.LastWriteDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}\""; + createdLine = $"created: {creationDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}"; + updatedLine = $"updated: {markdownFile.LastWriteDateTime.ToUniversalTime():yyyy-MM-ddTHH:mm:ss.fffZ}"; if (markdownFile.IsKanbanIndex) HelperKanbanMetadata.SetMetadata(markdownFile.Directory, new(lines), markdownFile.LineNumber, gitOthersModifiedAndDeletedExcludingStandardFiles); if (markdownFile.LineNumber.FrontMatterYamlEnd is null) @@ -1341,13 +1332,7 @@ internal static partial class HelperMarkdown relativeToCollection = GetRelativeToCollection(appSettings, input, gitOthersModifiedAndDeletedExcludingStandardFiles); logger.LogInformation("{updated} Markdown file(s) were updated", updated); } - if (!string.IsNullOrEmpty(input.StartAt) && !string.IsNullOrEmpty(input.Destination)) - { - relativeToCollection = GetRelativeToCollection(appSettings, input, gitOthersModifiedAndDeletedExcludingStandardFiles, force: true); - List markdownFileAndLinesCollection = GetRecursiveLines(appSettings, input, logger, relativeToCollection); - Write(input, markdownFileAndLinesCollection, gitOthersModifiedAndDeletedExcludingStandardFiles); - } - if (!string.IsNullOrEmpty(input.StartAt) && !string.IsNullOrEmpty(input.Destination)) + if (!string.IsNullOrEmpty(input.Destination)) SaveColumnToCards(input, relativeToCollection); }