From b55fdeae343572f2dced85cbdcd85b83bff8d571 Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Sun, 9 Sep 2018 21:02:40 +0100
Subject: [PATCH] Work on the CLI. More to go, but it's taking shape nicely!

---
 SearchBox-CLI/Program.cs            | 127 ++++++++++++++++++++++++++--
 SearchBox-CLI/SearchBox-CLI.csproj  |   9 ++
 SearchBox-CLI/packages.config       |   4 +
 SearchBox/{IdMapper.cs => IdMap.cs} |  10 +++
 SearchBox/SearchBox.csproj          |   5 +-
 5 files changed, 149 insertions(+), 6 deletions(-)
 create mode 100644 SearchBox-CLI/packages.config
 rename SearchBox/{IdMapper.cs => IdMap.cs} (78%)

diff --git a/SearchBox-CLI/Program.cs b/SearchBox-CLI/Program.cs
index 07d323f..2c3caeb 100644
--- a/SearchBox-CLI/Program.cs
+++ b/SearchBox-CLI/Program.cs
@@ -1,15 +1,132 @@
 ﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Newtonsoft.Json;
+
 using SearchBox;
 
+
 namespace SearchBoxCLI
 {
-	class MainClass
+	enum OperatingModes
 	{
-		public static void Main(string[] args)
+		Query,
+		Index,
+		InvertedIndexAdd,
+		InvertedIndexRemove,
+		InvertedIndexUpdate
+	}
+
+	enum OutputModes
+	{
+		Json,
+		Text
+	}
+
+	class MainClass {
+		private static OperatingModes Mode = OperatingModes.Query;
+		private static string Name = string.Empty;
+		private static string InvIndexFilepath = string.Empty;
+		private static string IdMapFilepath = string.Empty;
+		private static TextReader Source = Console.In;
+		private static OutputModes OutputMode = OutputModes.Json;
+
+		public static int Main(string[] args)
 		{
-			string input = Console.In.ReadToEnd();
-			Index index = new Index(input);
-			Console.WriteLine(index);
+			List<string> extras = new List<string>();
+			for (int i = 0; i < args.Length; i++)
+			{
+				switch (args[i].TrimStart("-".ToCharArray()))
+				{
+					case "s":
+					case "source":
+						Source = new StreamReader(args[++i]);
+						break;
+
+					case "n":
+					case "name":
+						Name = args[++i];
+						break;
+
+					case "invindex":
+						InvIndexFilepath = args[++i];
+						break;
+
+					case "idmap":
+
+						break;
+
+					case "help":
+						Console.WriteLine("SearchBox");
+						Console.WriteLine("---------");
+						Console.WriteLine("A standalone full-text search engine.");
+						Console.WriteLine();
+						Console.WriteLine("Usage:");
+						Console.WriteLine("    ./SearchBox.exe {mode} [options]");
+						Console.WriteLine();
+						Console.WriteLine("Modes:");
+						Console.WriteLine("    query     Query a pre-existing inverted search index");
+						Console.WriteLine("    index     Generate a raw index of the source document.");
+						Console.WriteLine("    add       Add a named document to an inverted search index.");
+						Console.WriteLine("    remove    Remove a named document from an inverted search index.");
+						Console.WriteLine();
+						Console.WriteLine("Options:");
+						Console.WriteLine("    --source, -s    Specifies the source document {index, add}");
+						Console.WriteLine("    --name, -n      Sets the name of the source document {add, remove}");
+						Console.WriteLine("    --idmap, -i     Specifies the location of the id map, which is used to map document names onto their nuemical ids {add, remove}");
+						Console.WriteLine("    --invindex      Specifies the location of the inverted search index to use {add, remove}");
+						Console.WriteLine("    ");
+						break;
+
+					default:
+						Console.Error.WriteLine($"Error: Unknown property {args[i]}.");
+						return 1;
+				}
+			}
+
+			string modeText = extras.First(); extras.RemoveAt(0);
+			Mode = (OperatingModes)Enum.Parse(typeof(OperatingModes), modeText);
+
+			switch (Mode) {
+				case OperatingModes.Index: return HandleIndex();
+				case OperatingModes.InvertedIndexAdd: return HandleInvIndexAdd();
+			}
+
+			return 0;
+		}
+
+		private static int HandleInvIndexAdd()
+		{
+			if (!File.Exists(InvIndexFilepath))
+				File.WriteAllText(InvIndexFilepath, "[]");
+			if (!File.Exists(IdMapFilepath))
+				File.WriteAllText(InvIndexFilepath, "{}");
+
+			IdMap idMap = JsonConvert.DeserializeObject<IdMap>(File.ReadAllText(IdMapFilepath));
+			InvertedIndex invertedIndex = JsonConvert.DeserializeObject<InvertedIndex>(
+				File.ReadAllText(InvIndexFilepath)
+			);
+			Index newIndex = new Index(Source.ReadToEnd());
+			invertedIndex.AddIndex(newIndex);
+
+			return 0;
+		}
+
+		public static int HandleIndex()
+		{
+			Index index = new Index(Source.ReadToEnd());
+			switch (OutputMode)
+			{
+				case OutputModes.Json:
+					Console.WriteLine(JsonConvert.SerializeObject(index));
+					break;
+				case OutputModes.Text:
+					Console.WriteLine(index);
+					break;
+			}
+
+			return 0;
 		}
 	}
 }
diff --git a/SearchBox-CLI/SearchBox-CLI.csproj b/SearchBox-CLI/SearchBox-CLI.csproj
index 7cbef2d..9560f3a 100644
--- a/SearchBox-CLI/SearchBox-CLI.csproj
+++ b/SearchBox-CLI/SearchBox-CLI.csproj
@@ -30,6 +30,12 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Program.cs" />
@@ -41,5 +47,8 @@
       <Name>SearchBox</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 </Project>
\ No newline at end of file
diff --git a/SearchBox-CLI/packages.config b/SearchBox-CLI/packages.config
new file mode 100644
index 0000000..f01737d
--- /dev/null
+++ b/SearchBox-CLI/packages.config
@@ -0,0 +1,4 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net47" />
+</packages>
\ No newline at end of file
diff --git a/SearchBox/IdMapper.cs b/SearchBox/IdMap.cs
similarity index 78%
rename from SearchBox/IdMapper.cs
rename to SearchBox/IdMap.cs
index 7bacc94..fb64550 100644
--- a/SearchBox/IdMapper.cs
+++ b/SearchBox/IdMap.cs
@@ -1,4 +1,6 @@
 ﻿using System;
+using System.Collections.Generic;
+using System.Text;
 using Stackoverflow.Utilities;
 
 namespace SearchBox
@@ -45,5 +47,13 @@ namespace SearchBox
 		{
 			map.RemoveBySecond(pageName);
 		}
+
+		public override string ToString()
+		{
+			StringBuilder result = new StringBuilder("Id Map:\n");
+			foreach (BiDictionary<int, string>.Pair pair in map)
+				result.AppendLine($"\t{pair.First}: {pair.Second}");
+			return result.ToString();
+		}
 	}
 }
diff --git a/SearchBox/SearchBox.csproj b/SearchBox/SearchBox.csproj
index 680178b..73c4bbf 100644
--- a/SearchBox/SearchBox.csproj
+++ b/SearchBox/SearchBox.csproj
@@ -33,6 +33,9 @@
     <Reference Include="UnidecodeSharpFork">
       <HintPath>..\packages\UnidecodeSharpFork.1.0.0\lib\UnidecodeSharpFork.dll</HintPath>
     </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Properties\AssemblyInfo.cs" />
@@ -43,7 +46,7 @@
     <Compile Include="Utilities\StringPlus.cs" />
     <Compile Include="StopwordTester.cs" />
     <Compile Include="InvertedIndex.cs" />
-    <Compile Include="IdMapper.cs" />
+    <Compile Include="IdMap.cs" />
     <Compile Include="Utilities\BiDictionary.cs" />
   </ItemGroup>
   <ItemGroup>
