<commit_before>﻿using LibTextPet.Plugins;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using TextPet.Commands;
using TextPet.Events;

namespace TextPet {
	/// <summary>
	/// Manages the command line interface for TextPet.
	/// </summary>
	internal sealed class CommandLineInterface {
		/// <summary>
		/// Gets the commands available to use in this command line interface.
		/// </summary>
		internal IList<CliCommand> Commands { get; private set; }
		/// <summary>
		/// Gets the TextPet core that is being acted on.
		/// </summary>
		private TextPetCore Core { get; }

		/// <summary>
		/// The IDs of the text archives that passed testing.
		/// </summary>
		private List<string> PassedIDs;
		/// <summary>
		/// The IDs of the text archives that failed testing.
		/// </summary>
		private List<string> FailedIDs;
		/// <summary>
		/// The current progress.
		/// </summary>
		private int CurrentProgress;
		/// <summary>
		/// The total progress.
		/// </summary>
		private int TotalProgress;
		/// <summary>
		/// Whether this command line interface is in test mode.
		/// </summary>
		private bool Testing;
		/// <summary>
		/// The current stack of loaded script files.
		/// </summary>
		private List<string> ScriptPaths;
		/// <summary>
		/// Whether printing should be (mostly) surpressed.
		/// </summary>
		internal bool Verbose;
		/// <summary>
		/// The singular name of the object currently being read/written.
		/// </summary>
		private string ObjectNameSingle;
		/// <summary>
		/// The multiple name of the objects currently being read/written.
		/// </summary>
		private string ObjectNameMultiple;

		/// <summary>
		/// Creates a new command line interface that acts on the specified TextPet core.
		/// </summary>
		/// <param name="core">The TextPet core to act on.</param>
		public CommandLineInterface(TextPetCore core) {
			this.Core = core;

			this.PassedIDs = new List<string>();
			this.FailedIDs = new List<string>();
			this.CurrentProgress = 0;
			this.TotalProgress = 0;
			this.Testing = false;
			this.ScriptPaths = new List<string>();
			this.Verbose = false;
			this.SetObjectNames(null, null);

			this.Commands = new CliCommand[] {
				new ClearCommand(this, this.Core),
				new DeleteCommand(this, this.Core),
				new FloodCommand(this, this.Core),
				new GameCommand(this, this.Core),
				new HelpCommand(this, this.Core),
				new InsertTextBoxesCommand(this, this.Core),
				new LoadPluginsCommand(this, this.Core),
				new LoadFileCommand(this, this.Core),
				new LoadFileIndexCommand(this, this.Core),
				new ReadTextArchivesCommand(this, this.Core),
				new RegexCommand(this, this.Core),
				new RenameCommand(this, this.Core),
				new RunScriptCommand(this, this.Core),
				new SearchCommand(this, this.Core),
				new SilentCommand(this, this.Core),
				new TestTextArchivesCommand(this, this.Core),
				new TrimCommand(this, this.Core),
				new VerboseCommand(this, this.Core),
				new WriteFileIndexCommand(this, this.Core),
				new WriteTextArchivesCommand(this, this.Core),
			};

			this.Core.BeginLoadingPlugins += Core_BeginReadWriting;
			this.Core.LoadedPlugin += Core_PluginLoaded;
			this.Core.GameInitialized += Core_GameInitialized;

			this.Core.ClearedTextArchives += Core_ClearedTextArchives;

			this.Core.BeginReadingTextArchives += Core_BeginReadWriting;
			this.Core.ReadingTextArchive += Core_ReadingTextArchive;
			this.Core.ReadTextArchive += Core_ReadWroteTextArchive;
			this.Core.FinishedReadingTextArchives += Core_FinishedReadingTextArchives;

			this.Core.BeginWritingTextArchives += Core_BeginReadWriting;
			this.Core.WritingTextArchive += Core_WritingTextArchive;
			this.Core.WroteTextArchive += Core_ReadWroteTextArchive;
			this.Core.FinishedWritingTextArchives += Core_FinishedWritingTextArchives;

			this.Core.BeginTestingTextArchives += Core_BeginReadWriting;
			this.Core.BeginTestingTextArchives += Core_BeginTestingTextArchives;
			this.Core.TestedTextArchive += Core_TestedTextArchive;
			this.Core.FinishedTestingTextArchives += Core_FinishedTestingTextArchives;
		}

		/// <summary>
		/// Runs the specified commands in this command line interface.
		/// </summary>
		/// <param name="args">The commands to run, and their arguments.</param>
		public void Run(IList<string> args) {
			bool suppressDone = false;

			// Print usage if no arguments were provided.
			if (args.Count <= 0) {
				args = new string[] {
					"help"
				};
				suppressDone = true;
			}

			Run(args, suppressDone);
		}

		/// <summary>
		/// Runs the specified commands in this command line interface.
		/// </summary>
		/// <param name="args">The commands to run, and their arguments.</param>
		/// <param name="suppressDone">Whether the "done" message at the end should be suppressed.</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Console.WriteLine(System.String)")]
		private void Run(IList<string> args, bool suppressDone) {
			if (args == null) {
				args = new string[0];
			}

			int i = 0;
			while (i < args.Count) {
				// Reset object names.
				this.SetObjectNames(null, null);

				// Find a matching command.
				CliCommand cmd = null;
				foreach (CliCommand c in this.Commands) {
					if (StringComparer.OrdinalIgnoreCase.Equals(args[i], c.Name)) {
						cmd = c;
						break;
					}
				}

				// No commands found?
				if (cmd == null) {
					Console.WriteLine("ERROR: Unknown command \"" + args[i] + "\".");
					break;
				}

				if (cmd.RunString != null) {
					Console.WriteLine(cmd.RunString);
				}
				int j = i + 1 + cmd.Run(args, i + 1);
				// Just in case.
				if (j <= i) {
					Console.WriteLine("FATAL: Loop detected.");
					break;
				}<commit_msg>Add comments, finally<commit_after>﻿using LibTextPet.Plugins;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using TextPet.Commands;
using TextPet.Events;

namespace TextPet {
	/// <summary>
	/// Manages the command line interface for TextPet.
	/// </summary>
	internal sealed class CommandLineInterface {
		/// <summary>
		/// Gets the commands available to use in this command line interface.
		/// </summary>
		internal IList<CliCommand> Commands { get; private set; }
		/// <summary>
		/// Gets the TextPet core that is being acted on.
		/// </summary>
		private TextPetCore Core { get; }

		/// <summary>
		/// The IDs of the text archives that passed testing.
		/// </summary>
		private List<string> PassedIDs;
		/// <summary>
		/// The IDs of the text archives that failed testing.
		/// </summary>
		private List<string> FailedIDs;
		/// <summary>
		/// The current progress.
		/// </summary>
		private int CurrentProgress;
		/// <summary>
		/// The total progress.
		/// </summary>
		private int TotalProgress;
		/// <summary>
		/// Whether this command line interface is in test mode.
		/// </summary>
		private bool Testing;
		/// <summary>
		/// The current stack of loaded script files.
		/// </summary>
		private List<string> ScriptPaths;
		/// <summary>
		/// Whether printing should be (mostly) surpressed.
		/// </summary>
		internal bool Verbose;
		/// <summary>
		/// The singular name of the object currently being read/written.
		/// </summary>
		private string ObjectNameSingle;
		/// <summary>
		/// The multiple name of the objects currently being read/written.
		/// </summary>
		private string ObjectNameMultiple;

		/// <summary>
		/// Creates a new command line interface that acts on the specified TextPet core.
		/// </summary>
		/// <param name="core">The TextPet core to act on.</param>
		public CommandLineInterface(TextPetCore core) {
			this.Core = core;

			this.PassedIDs = new List<string>();
			this.FailedIDs = new List<string>();
			this.CurrentProgress = 0;
			this.TotalProgress = 0;
			this.Testing = false;
			this.ScriptPaths = new List<string>();
			this.Verbose = false;
			this.SetObjectNames(null, null);

			this.Commands = new CliCommand[] {
				new ClearCommand(this, this.Core),
				new DeleteCommand(this, this.Core),
				new FloodCommand(this, this.Core),
				new GameCommand(this, this.Core),
				new HelpCommand(this, this.Core),
				new InsertTextBoxesCommand(this, this.Core),
				new LoadPluginsCommand(this, this.Core),
				new LoadFileCommand(this, this.Core),
				new LoadFileIndexCommand(this, this.Core),
				new ReadTextArchivesCommand(this, this.Core),
				new RegexCommand(this, this.Core),
				new RenameCommand(this, this.Core),
				new RunScriptCommand(this, this.Core),
				new SearchCommand(this, this.Core),
				new SilentCommand(this, this.Core),
				new TestTextArchivesCommand(this, this.Core),
				new TrimCommand(this, this.Core),
				new VerboseCommand(this, this.Core),
				new WriteFileIndexCommand(this, this.Core),
				new WriteTextArchivesCommand(this, this.Core),
			};

			this.Core.BeginLoadingPlugins += Core_BeginReadWriting;
			this.Core.LoadedPlugin += Core_PluginLoaded;
			this.Core.GameInitialized += Core_GameInitialized;

			this.Core.ClearedTextArchives += Core_ClearedTextArchives;

			this.Core.BeginReadingTextArchives += Core_BeginReadWriting;
			this.Core.ReadingTextArchive += Core_ReadingTextArchive;
			this.Core.ReadTextArchive += Core_ReadWroteTextArchive;
			this.Core.FinishedReadingTextArchives += Core_FinishedReadingTextArchives;

			this.Core.BeginWritingTextArchives += Core_BeginReadWriting;
			this.Core.WritingTextArchive += Core_WritingTextArchive;
			this.Core.WroteTextArchive += Core_ReadWroteTextArchive;
			this.Core.FinishedWritingTextArchives += Core_FinishedWritingTextArchives;

			this.Core.BeginTestingTextArchives += Core_BeginReadWriting;
			this.Core.BeginTestingTextArchives += Core_BeginTestingTextArchives;
			this.Core.TestedTextArchive += Core_TestedTextArchive;
			this.Core.FinishedTestingTextArchives += Core_FinishedTestingTextArchives;
		}

		/// <summary>
		/// Runs the specified commands in this command line interface.
		/// </summary>
		/// <param name="args">The commands to run, and their arguments.</param>
		public void Run(IList<string> args) {
			bool suppressDone = false;

			// Print usage if no arguments were provided.
			if (args.Count <= 0) {
				args = new string[] {
					"help"
				};
				suppressDone = true;
			}

			Run(args, suppressDone);
		}

		/// <summary>
		/// Runs the specified commands in this command line interface.
		/// </summary>
		/// <param name="args">The commands to run, and their arguments.</param>
		/// <param name="suppressDone">Whether the "done" message at the end should be suppressed.</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Console.WriteLine(System.String)")]
		private void Run(IList<string> args, bool suppressDone) {
			if (args == null) {
				args = new string[0];
			}

			int i = 0;
			while (i < args.Count) {
				// Reset object names.
				this.SetObjectNames(null, null);

				if (args[i] == "/*") {
					bool terminated = false;
					while (i < args.Count) {
						if (args[i++] == "*/") {
							terminated = true;
							break;
						}
					}

					if (!terminated) {
						Console.WriteLine("ERROR: Non-terminated comment.");
						break;
					}
				}

				// Find a matching command.
				CliCommand cmd = null;
				foreach (CliCommand c in this.Commands) {
					if (StringComparer.OrdinalIgnoreCase.Equals(args[i], c.Name)) {
						cmd = c;
						break;
					}
				}

				// No commands found?
				if (cmd == null) {
					Console.WriteLine("ERROR: Unknown command \"" + args[i] + "\".");
					break;
				}

				if (cmd.RunString != null) {
					Console.WriteLine(cmd.RunString);
				}
				int j = i + 1 + cmd.Run(args, i + 1);
				// Just in case.
				if (j <= i) {
					Console.WriteLine("FATAL: Loop detected.");
					break;
				}
{'fraction_non_alphanumeric': 0.12708230249051625, 'fraction_numerical': 0.001814283358073561, 'mean_word_length': 3.243177046885934, 'pattern_counts': {'":': 0, '<': 104, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7635621', 'n_tokens_mistral': 4370, 'n_tokens_neox': 3597, 'n_words': 977}