BREAKING: switch all multi-char commands to POSIX --double-dash

Rename every multi-character option/command from single-dash to double-dash (--likes, --collect, --force, etc.) to follow the POSIX long-option convention. Single-character short options (-h, -V, -?) keep their single dash, as POSIX prescribes.

Breaking: existing invocations/scripts using single-dash forms now report Unknown Command and must be updated. Run profile (launchSettings.json) and CLI docs (copilot-instructions.md) updated to match.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
jim
2026-06-09 15:26:38 -05:00
co-authored by Claude Opus 4.8
parent a437fa87d3
commit 4df73367fb
3 changed files with 62 additions and 67 deletions
+52 -57
View File
@@ -55,31 +55,27 @@ namespace URLNotesGrabberCORE
break;
}
if (string.Equals(args[i], "-force", StringComparison.OrdinalIgnoreCase) ||
string.Equals(args[i], "--force", StringComparison.OrdinalIgnoreCase))
if (string.Equals(args[i], "--force", StringComparison.OrdinalIgnoreCase))
{
forceIgnoreCooldown = true;
continue;
}
if (string.Equals(args[i], "-api3", StringComparison.OrdinalIgnoreCase) ||
string.Equals(args[i], "--api3", StringComparison.OrdinalIgnoreCase))
if (string.Equals(args[i], "--api3", StringComparison.OrdinalIgnoreCase))
{
apiSectionName = "TumblrApi3";
apiExplicitlySet = true;
continue;
}
if (string.Equals(args[i], "-api4", StringComparison.OrdinalIgnoreCase) ||
string.Equals(args[i], "--api4", StringComparison.OrdinalIgnoreCase))
if (string.Equals(args[i], "--api4", StringComparison.OrdinalIgnoreCase))
{
apiSectionName = "TumblrApi4";
apiExplicitlySet = true;
continue;
}
if (string.Equals(args[i], "-api", StringComparison.OrdinalIgnoreCase) ||
string.Equals(args[i], "--api", StringComparison.OrdinalIgnoreCase))
if (string.Equals(args[i], "--api", StringComparison.OrdinalIgnoreCase))
{
if (i + 1 < args.Length && !string.IsNullOrWhiteSpace(args[i + 1]))
{
@@ -89,13 +85,12 @@ namespace URLNotesGrabberCORE
}
else
{
Console.WriteLine("--Missing API section after -api/--api. Using default TumblrApi.--");
Console.WriteLine("--Missing API section after --api. Using default TumblrApi.--");
}
continue;
}
if (string.Equals(args[i], "-start", StringComparison.OrdinalIgnoreCase) ||
string.Equals(args[i], "--start", StringComparison.OrdinalIgnoreCase))
if (string.Equals(args[i], "--start", StringComparison.OrdinalIgnoreCase))
{
if (i + 1 < args.Length && !string.IsNullOrWhiteSpace(args[i + 1]))
{
@@ -104,7 +99,7 @@ namespace URLNotesGrabberCORE
}
else
{
Console.WriteLine("--Missing blog name after -start/--start. Ignoring.--");
Console.WriteLine("--Missing blog name after --start. Ignoring.--");
}
continue;
}
@@ -179,7 +174,7 @@ namespace URLNotesGrabberCORE
Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown");
break;
case "-parse":
case "--parse":
string blogNameToParse = args[1];
int postsAdded = 0;
try
@@ -194,23 +189,23 @@ namespace URLNotesGrabberCORE
Console.WriteLine($"Total posts added: {postsAdded}");
break;
case "-test":
case "--test":
Console.WriteLine("Test command not implemented");
break;
case "-post":
case "--post":
TraverseDirectoryForCorruption(settings.GetValue<string>("PathInput"), settings.GetValue<string>("PathOutputBlogs"), contains);
break;
case "-posts": //write post's blogs to file
case "--posts": //write post's blogs to file
WritePostBlogsToFile(settings.GetValue<string>("PathOutputPosts"));
break;
case "-blogs": //write blogs to file
case "--blogs": //write blogs to file
WriteBlogsToFile(settings.GetValue<string>("PathOutputBlogs"));
break;
case "-collect": //collect notes from all posts
case "--collect": //collect notes from all posts
bool withoutNotesOnly = true;
DateTime? beforeDate = DateTime.Now;
bool explicitDateSupplied = false;
@@ -281,11 +276,11 @@ namespace URLNotesGrabberCORE
CollectNotes(settings.GetValue<string>("PathOutput"), withoutNotesOnly, beforeDate, managedCollectRun).GetAwaiter().GetResult();
break;
case "-blogsR": //collect notes from all posts
case "--blogsR": //collect notes from all posts
WriteBlogsToFile(settings.GetValue<string>("PathOutputBlogs"), true);
break;
case "-blogsO": //collect notes from all posts
case "--blogsO": //collect notes from all posts
int from = 1, to = 999999, top = 100;
if (args[1] is not null && args[2] is not null && args[3] is not null)
@@ -302,7 +297,7 @@ namespace URLNotesGrabberCORE
WriteBlogsToFile(settings.GetValue<string>("PathOutputBlogs"), false, from, to, top);
break;
case "-bop": //collect notes from all posts
case "--bop": //collect notes from all posts
from = 1; to = 999999; top = 100;
if (args[1] is not null && args[2] is not null && args[3] is not null)
@@ -319,54 +314,54 @@ namespace URLNotesGrabberCORE
WriteBlogsToFileAll(settings.GetValue<string>("PathOutputBlogs"), false, from, to, top);
break;
case "-replies": //update reply text
case "--replies": //update reply text
CollectMissingReplyText().GetAwaiter().GetResult();
break;
case "-likes":
case "--likes":
string likeBlog = args.Length > 1 ? args[1] : null;
int cooldownDays = settings.GetValue("LikesRefreshCooldownDays", 7);
CollectLikes(likeBlog, contains, cooldownDays, forceIgnoreCooldown).GetAwaiter().GetResult();
break;
case "-urldump":
case "--urldump":
DumpUrls(settings.GetValue<string>("PathOutputUrls"));
break;
case "-ingest":
case "--ingest":
exitCode = IngestMode.Run(config, args.Skip(1).ToArray());
break;
case "-output":
case "--output":
exitCode = OutputMode.Run(config);
break;
case "-revert":
case "--revert":
exitCode = RevertMode.Run(config, args.Length > 1 ? args[1] : null);
break;
case "-correct":
case "--correct":
{
bool applyChanges = args.Skip(1).Any(a => string.Equals(a, "-apply", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "--apply", StringComparison.OrdinalIgnoreCase));
bool applyChanges = args.Skip(1).Any(a => string.Equals(a, "--apply", StringComparison.OrdinalIgnoreCase));
var correctArgs = args.Skip(1)
.Where(a => !string.Equals(a, "-apply", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "--apply", StringComparison.OrdinalIgnoreCase))
.Where(a => !string.Equals(a, "--apply", StringComparison.OrdinalIgnoreCase))
.ToArray();
exitCode = CorrectMode.Run(config, correctArgs, applyChanges);
break;
}
case "-updatepaths":
case "--updatepaths":
{
string rootPath = args.Length > 1 ? args[1] : (settings.GetValue<string>("PathTTRoot") ?? settings.GetValue<string>("PathInput") ?? string.Empty);
exitCode = UpdateBlogPathsRunner.Run(rootPath);
break;
}
case "-importposts":
case "--importposts":
{
if (args.Length < 2)
{
Console.WriteLine("Usage: -importposts <path-to-legacy-posts.db>");
Console.WriteLine("Usage: --importposts <path-to-legacy-posts.db>");
exitCode = 2;
break;
}
@@ -398,53 +393,53 @@ namespace URLNotesGrabberCORE
Console.WriteLine("--\t End of options: treat every following token as a literal operand");
Console.WriteLine("-parse\t Parse .txt files with specified blogname");
Console.WriteLine("--parse\t Parse .txt files with specified blogname");
Console.WriteLine("-test\t Calls API for given blogname and postID");
Console.WriteLine("--test\t Calls API for given blogname and postID");
Console.WriteLine("-post\t Traverse the input directory tree checking .txt files for corruption");
Console.WriteLine("--post\t Traverse the input directory tree checking .txt files for corruption");
Console.WriteLine("-posts\t For each Post in DB, write blogname to file");
Console.WriteLine("--posts\t For each Post in DB, write blogname to file");
Console.WriteLine("-blogs\t For each Blog in DB, write blogname to file");
Console.WriteLine("--blogs\t For each Blog in DB, write blogname to file");
Console.WriteLine("-collect [0|1] [datetime]\t Collect Notes from API. 1=only posts without notes. 0=full re-check of all posts: a single resumable pass (interrupt & relaunch to resume; stops when complete, retrigger for a new pass). Optional datetime overrides the cutoff and runs as a one-off (bypasses resume tracking).");
Console.WriteLine("--collect [0|1] [datetime]\t Collect Notes from API. 1=only posts without notes. 0=full re-check of all posts: a single resumable pass (interrupt & relaunch to resume; stops when complete, retrigger for a new pass). Optional datetime overrides the cutoff and runs as a one-off (bypasses resume tracking).");
Console.WriteLine("-blogsR\t For each Note that is a REPLY, write blogname to file ");
Console.WriteLine("--blogsR\t For each Note that is a REPLY, write blogname to file ");
Console.WriteLine("-blogsO\t For each Blog in DB, write blogname to file, but limit via a passed start and stop range ");
Console.WriteLine("--blogsO\t For each Blog in DB, write blogname to file, but limit via a passed start and stop range ");
Console.WriteLine("-bop [from] [to] [top]\t Write ALL blog names to file, limited by FROM TO TOP range arguments");
Console.WriteLine("--bop [from] [to] [top]\t Write ALL blog names to file, limited by FROM TO TOP range arguments");
Console.WriteLine("-replies\t Fetch and update missing reply text for all replies in database");
Console.WriteLine("--replies\t Fetch and update missing reply text for all replies in database");
Console.WriteLine("-likes\t Fetch likes: initial backfill for new blogs, incremental refresh for blogs past cooldown. Optional blog name forces single-blog run.");
Console.WriteLine("--likes\t Fetch likes: initial backfill for new blogs, incremental refresh for blogs past cooldown. Optional blog name forces single-blog run.");
Console.WriteLine("-force\t (with -likes) Ignore cooldown and refresh every fully-backfilled blog");
Console.WriteLine("--force\t (with --likes) Ignore cooldown and refresh every fully-backfilled blog");
Console.WriteLine("-urldump\t Scan all posts' text columns and extract suspected URLs to configured file");
Console.WriteLine("--urldump\t Scan all posts' text columns and extract suspected URLs to configured file");
Console.WriteLine("-api3\t Use TumblrApi3 settings from appsettings.json");
Console.WriteLine("--api3\t Use TumblrApi3 settings from appsettings.json");
Console.WriteLine("-api4\t Use TumblrApi4 settings from appsettings.json");
Console.WriteLine("--api4\t Use TumblrApi4 settings from appsettings.json");
Console.WriteLine("-start [blogname]\t Start traversal alphabetically at this blog name");
Console.WriteLine("--start [blogname]\t Start traversal alphabetically at this blog name");
Console.WriteLine("-api [section]\t Use a specific API settings section from appsettings.json (e.g. TumblrApi3)");
Console.WriteLine("--api [section]\t Use a specific API settings section from appsettings.json (e.g. TumblrApi3)");
Console.WriteLine("-ingest [blogname]\t Ingest Tumblr .txt exports from appSettings:PathTTRoot into TL.db (all blogs, or single blog if name given)");
Console.WriteLine("--ingest [blogname]\t Ingest Tumblr .txt exports from appSettings:PathTTRoot into TL.db (all blogs, or single blog if name given)");
Console.WriteLine("-output\t Export posts from TL.db back to .txt files in each blog's TTFolderPath");
Console.WriteLine("--output\t Export posts from TL.db back to .txt files in each blog's TTFolderPath");
Console.WriteLine("-revert [blogname]\t Recursively scan the PathInput tree and restore *.bak back to *.txt (current .txt saved as next-free .bkN); optional blogname filters by path substring");
Console.WriteLine("--revert [blogname]\t Recursively scan the PathInput tree and restore *.bak back to *.txt (current .txt saved as next-free .bkN); optional blogname filters by path substring");
Console.WriteLine("-correct [bakPath]\t Dry-run: report multi-line field updates available from a BAK directory");
Console.WriteLine("--correct [bakPath]\t Dry-run: report multi-line field updates available from a BAK directory");
Console.WriteLine("-correct -apply [bakPath]\t Apply BAK-file corrections to matching posts (prompts yes/no)");
Console.WriteLine("--correct --apply [bakPath]\t Apply BAK-file corrections to matching posts (prompts yes/no)");
Console.WriteLine("-updatepaths [rootPath]\t Read .tumblr/.tmblrpriv metadata from <root>\\Index and set Blogs.TTFolderPath");
Console.WriteLine("--updatepaths [rootPath]\t Read .tumblr/.tmblrpriv metadata from <root>\\Index and set Blogs.TTFolderPath");
Console.WriteLine("-importposts [path-to-posts.db]\t One-time migration: copy legacy ThreeTxtFileHelper posts.db rows into TL.db");
Console.WriteLine("--importposts [path-to-posts.db]\t One-time migration: copy legacy ThreeTxtFileHelper posts.db rows into TL.db");
Console.WriteLine();
Console.WriteLine("Exit status: 0 = success; 1 = unexpected error; 2 = usage error (unknown command or bad/missing arguments)");