file-folder-helper/Day/2024-Q2/Helper-2024-06-23.cs
2024-07-23 13:20:35 -07:00

192 lines
7.9 KiB
C#

using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
namespace File_Folder_Helper.Day;
internal static partial class Helper20240623
{
private record Record(int? CodeInsidersLine, string File, string[] Lines, int? StopLine, int? SubTasksLine);
private static List<Record> GetRecords(string sourceDirectory, string searchPattern, string codeInsiders, string subTasks)
{
List<Record> results = [];
int? stopLine;
string[] lines;
int? subTasksLine;
int? codeInsidersLine;
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
foreach (string file in files)
{
stopLine = null;
subTasksLine = null;
codeInsidersLine = null;
lines = File.ReadAllLines(file);
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].StartsWith(codeInsiders) && lines[i][^1] == '"')
{
if (lines.Length > i + 1 && lines[i + 1] == "```")
codeInsidersLine = i;
}
if (lines[i] != subTasks)
continue;
subTasksLine = i;
if (codeInsidersLine is null)
break;
if (lines.Length > i)
{
for (int j = i + 1; j < lines.Length; j++)
{
if (lines[j].Length > 0 && lines[j][0] == '#')
{
stopLine = j;
break;
}
}
}
stopLine ??= lines.Length;
break;
}
results.Add(new(codeInsidersLine, file, lines, stopLine, subTasksLine));
}
return results;
}
private static ReadOnlyCollection<string> GetSubTasks(string subTasks, string[] tasks, bool? foundDone, string fallbackLine, string checkFile)
{
List<string> results = [];
string? h1 = null;
bool foundSubTasks = false;
int tasksZeroLength = tasks[0].Length;
string[] lines = File.ReadAllLines(checkFile);
foreach (string line in lines)
{
if (line.StartsWith("# "))
h1 = line[2..];
if (!foundSubTasks && line == subTasks)
foundSubTasks = true;
if (!foundSubTasks)
continue;
if (line.Length <= tasksZeroLength || !line.StartsWith(tasks[0]) || line[tasksZeroLength] is not ' ' and not 'x' || line[tasksZeroLength + 1] != ']')
continue;
results.Add($" {line}");
}
if (h1 is null)
results.Insert(0, fallbackLine);
else
results.Insert(0, foundDone is null || !foundDone.Value ? $"- [ ] {h1}" : $"- [x] {h1}");
return new(results);
}
internal static void UpdateSubTasksInMarkdownFiles(ILogger<Worker> logger, List<string> args)
{
int lineCheck;
bool? foundDone;
string checkFile;
string[] segments;
List<string> lines;
string[] indexLines;
string fallbackLine;
string checkDirectory;
string done = args[7];
List<string> indexFiles;
string subTasks = args[3];
List<string> newLines = [];
List<string> oldLines = [];
string indexFile = args[5];
string searchPattern = args[2];
string directoryFilter = args[8];
ReadOnlyCollection<string> useLines;
string[] tasks = args[6].Split(',');
string codeInsiders = $"{args[4]} \"";
string sourceDirectory = Path.GetFullPath(args[0]);
List<Record> records = GetRecords(sourceDirectory, searchPattern, codeInsiders, subTasks);
foreach (Record record in from l in records orderby l.SubTasksLine is null, l.CodeInsidersLine is null select l)
{
if (record.SubTasksLine is null)
continue;
if (record.CodeInsidersLine is not null)
logger.LogInformation("<{file}> has [{subTasks}]", Path.GetFileNameWithoutExtension(record.File), subTasks);
else
{
logger.LogWarning("<{file}> has [{subTasks}] but doesn't have [{codeInsiders}]!", Path.GetFileNameWithoutExtension(record.File), subTasks, codeInsiders);
continue;
}
if (record.StopLine is null)
continue;
checkDirectory = record.Lines[record.CodeInsidersLine.Value][codeInsiders.Length..^1];
if (!Directory.Exists(checkDirectory))
{
logger.LogError("<{checkDirectory}> doesn't exist", Path.GetFileName(checkDirectory));
continue;
}
indexFiles = Directory.GetFiles(checkDirectory, indexFile, SearchOption.AllDirectories).ToList();
if (indexFiles.Count != 1)
{
for (int i = indexFiles.Count - 1; i > -1; i--)
{
if (!indexFiles[i].Contains(directoryFilter, StringComparison.CurrentCultureIgnoreCase))
indexFiles.RemoveAt(i);
}
if (indexFiles.Count != 1)
{
logger.LogError("<{checkDirectory}> doesn't have a [{indexFile}]", Path.GetFileName(checkDirectory), indexFile);
continue;
}
}
foundDone = null;
newLines.Clear();
oldLines.Clear();
indexLines = File.ReadAllLines(indexFiles[0]);
checkDirectory = Path.GetDirectoryName(indexFiles[0]) ?? throw new Exception();
for (int i = 0; i < indexLines.Length; i++)
{
if (indexLines[i] == done)
foundDone = true;
segments = indexLines[i].Split(tasks[1]);
if (segments.Length > 2 || !segments[0].StartsWith(tasks[0]))
continue;
fallbackLine = foundDone is null || !foundDone.Value ? $"- [ ] {segments[0][tasks[0].Length..]}" : $"- [x] {segments[0][tasks[0].Length..]}";
checkFile = Path.GetFullPath(Path.Combine(checkDirectory, segments[1][..^1]));
if (!File.Exists(checkFile))
{
newLines.Add(fallbackLine);
continue;
}
useLines = GetSubTasks(subTasks, tasks, foundDone, fallbackLine, checkFile);
newLines.AddRange(useLines);
}
if (newLines.Count == 0)
continue;
lineCheck = 0;
newLines.Insert(0, string.Empty);
for (int i = record.SubTasksLine.Value + 1; i < record.StopLine.Value - 1; i++)
oldLines.Add(record.Lines[i]);
if (newLines.Count == oldLines.Count)
{
for (int i = 0; i < newLines.Count; i++)
{
if (newLines[i] != record.Lines[record.SubTasksLine.Value + 1 + i])
continue;
lineCheck++;
}
if (lineCheck == newLines.Count)
continue;
}
checkDirectory = Path.Combine(checkDirectory, DateTime.Now.Ticks.ToString());
_ = Directory.CreateDirectory(checkDirectory);
Thread.Sleep(500);
Directory.Delete(checkDirectory);
lines = record.Lines.ToList();
for (int i = record.StopLine.Value - 1; i > record.SubTasksLine.Value + 1; i--)
lines.RemoveAt(i);
if (record.StopLine.Value == record.Lines.Length && lines[^1].Length == 0)
lines.RemoveAt(lines.Count - 1);
for (int i = 0; i < newLines.Count; i++)
lines.Insert(record.SubTasksLine.Value + 1 + i, newLines[i]);
File.WriteAllLines(record.File, lines);
}
}
}