diff --git a/Changelog.md b/Changelog.md
index 9453408..038027e 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,10 +2,10 @@
## v23.0
-- Calendar versioning, `YY.MINOR.MICRO`
-
+- Split versioning systems between kernal and terminal
+ - Calendar versioning, `YY.MINOR.MICRO`, for kernal
+ - Semantic versioning for terminal
- If the file system is activate, system activity will be logged
-
- Build number based on commit hash
Due to the huge time skip and architectural changes, I've (retroactively) switched to calendar versioning with ``v0.1`` now known as ``v20.1`` as well.
diff --git a/src/TOMAS.sln b/src/TOMAS.sln
index 5a713b9..1c437ae 100644
--- a/src/TOMAS.sln
+++ b/src/TOMAS.sln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tomas.Common", "Tomas.Common\Tomas.Common.csproj", "{C50F3A6F-CFF4-4725-A1A5-21C5A2BC3321}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tomas.Core", "Tomas.Core\Tomas.Core.csproj", "{C50F3A6F-CFF4-4725-A1A5-21C5A2BC3321}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{59C9B3FC-B1EE-4C23-9BD9-D33074BF1334}"
ProjectSection(SolutionItems) = preProject
diff --git a/src/Tomas.Common/GlobalUsing.cs b/src/Tomas.Core/GlobalUsing.cs
similarity index 69%
rename from src/Tomas.Common/GlobalUsing.cs
rename to src/Tomas.Core/GlobalUsing.cs
index c66f29a..2e2aee3 100644
--- a/src/Tomas.Common/GlobalUsing.cs
+++ b/src/Tomas.Core/GlobalUsing.cs
@@ -1,2 +1,3 @@
global using System.Diagnostics.CodeAnalysis;
+global using System.Diagnostics;
global using Tomas.Interface;
diff --git a/src/Tomas.Common/Programs/Clear.cs b/src/Tomas.Core/Programs/Clear.cs
similarity index 100%
rename from src/Tomas.Common/Programs/Clear.cs
rename to src/Tomas.Core/Programs/Clear.cs
diff --git a/src/Tomas.Common/Programs/Commands.cs b/src/Tomas.Core/Programs/Commands.cs
similarity index 100%
rename from src/Tomas.Common/Programs/Commands.cs
rename to src/Tomas.Core/Programs/Commands.cs
diff --git a/src/Tomas.Common/Programs/FenSay.cs b/src/Tomas.Core/Programs/FenSay.cs
similarity index 100%
rename from src/Tomas.Common/Programs/FenSay.cs
rename to src/Tomas.Core/Programs/FenSay.cs
diff --git a/src/Tomas.Common/Tomas.Common.csproj b/src/Tomas.Core/Tomas.Core.csproj
similarity index 51%
rename from src/Tomas.Common/Tomas.Common.csproj
rename to src/Tomas.Core/Tomas.Core.csproj
index 6a91aed..665370e 100644
--- a/src/Tomas.Common/Tomas.Common.csproj
+++ b/src/Tomas.Core/Tomas.Core.csproj
@@ -9,11 +9,4 @@
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
diff --git a/src/Tomas.Common/GitInfo.txt b/src/Tomas.Kernel/GitInfo.txt
similarity index 100%
rename from src/Tomas.Common/GitInfo.txt
rename to src/Tomas.Kernel/GitInfo.txt
diff --git a/src/Tomas.Kernel/GlobalUsing.cs b/src/Tomas.Kernel/GlobalUsing.cs
index b847d34..25fcb20 100644
--- a/src/Tomas.Kernel/GlobalUsing.cs
+++ b/src/Tomas.Kernel/GlobalUsing.cs
@@ -1,3 +1,5 @@
+global using System.Diagnostics.CodeAnalysis;
+global using System.Diagnostics;
global using Tomas.Common.Programs;
global using Tomas.Interface;
global using Tomas.Kernel.Programs;
diff --git a/src/Tomas.Kernel/Globalization/CST.cs b/src/Tomas.Kernel/Globalization/CST.cs
new file mode 100644
index 0000000..23dc7e3
--- /dev/null
+++ b/src/Tomas.Kernel/Globalization/CST.cs
@@ -0,0 +1,98 @@
+// This project is licensed under the BSD 3-Clause license.
+// See the LICENSE file in the project root for more information.
+
+namespace Tomas.Kernel.Globalization;
+
+public class CST
+{
+ const char CARET = '^';
+ const string LF = "\u000A";
+ const string CR = "\u000D";
+ const string CRLF = "\u000D\u000A";
+ const string LS = "\u2028";
+
+ ///
+ /// Gets the value from the digit-based key.
+ ///
+ /// Returns the entry
+ public static string Parse(string content, int key) => Parse(content, key.ToString());
+
+ ///
+ /// Gets the value from the string-based key.
+ ///
+ /// Returns the entry
+ public static string Parse(string content, string key)
+ {
+ var entries = NormalizeEntries(content);
+ return GetEntry(entries, key);
+ }
+
+ ///
+ /// Replaces the document's line endings with the native system line endings.
+ ///
+ /// This stage ensures there are no crashes during parsing.
+ /// The content of the document.
+ /// The document's content with native system line endings.
+ static IEnumerable NormalizeEntries(string content)
+ {
+ // Check if the document already uses native system line endings.
+ if (!content.Contains(Environment.NewLine))
+ {
+ // If not, check for and replace other line ending types.
+ if (content.Contains(LF))
+ content = content.Replace(LF, Environment.NewLine);
+
+ if (content.Contains(CR))
+ content = content.Replace(CR, Environment.NewLine);
+
+ if (content.Contains(CRLF))
+ content = content.Replace(CRLF, Environment.NewLine);
+
+ if (content.Contains(LS))
+ content = content.Replace(LS, Environment.NewLine);
+ }
+
+ // Split the content by the caret and newline characters.
+ var lines = content.Split(new[] { $"{CARET}{Environment.NewLine}" },
+ StringSplitOptions.RemoveEmptyEntries);
+
+ // Filter out any lines that start with "//", "#", "/*", or end with "*/".
+ return lines.Where(line =>
+ !line.StartsWith("//") &&
+ !line.StartsWith("#") &&
+ !line.StartsWith("/*") &&
+ !line.EndsWith("*/"))
+ .AsEnumerable();
+ }
+
+ ///
+ /// Retrieves the value for the specified key from the given entries.
+ ///
+ /// The entries to search through.
+ /// The key to search for.
+ /// The value for the specified key, or a default string if not found.
+ static string GetEntry(IEnumerable entries, string key)
+ {
+ // Iterate through the entries.
+ foreach (var entry in entries)
+ {
+ // If the line doesn't start with the key, keep searching.
+ if (!entry.StartsWith(key))
+ continue;
+
+ // Locate the index of the caret character.
+ var startIndex = entry.IndexOf(CARET);
+ // Get the line from the caret character to the end of the string.
+ var line = entry[startIndex..];
+
+ // Return the line with the caret characters trimmed.
+ return line.TrimStart(CARET).TrimEnd(CARET);
+ }
+
+ // If no entry is found, return a default string.
+ return "***MISSING***";
+ }
+
+}
+
+
diff --git a/src/Tomas.Kernel/Globalization/IUIText.cs b/src/Tomas.Kernel/Globalization/IUIText.cs
new file mode 100644
index 0000000..e4ddb37
--- /dev/null
+++ b/src/Tomas.Kernel/Globalization/IUIText.cs
@@ -0,0 +1,20 @@
+// This project is licensed under the BSD 3-Clause license.
+// See the LICENSE file in the project root for more information.
+
+namespace Tomas.Kernel.Globalization;
+
+public interface IUIText
+{
+ ///
+ /// The base directory for the language files.
+ ///
+ string[] BasePath { get; set; }
+
+ ///
+ /// Get the text for the given id and key.
+ ///
+ /// The id of the text.
+ /// The key of the text.
+ /// The text for the given id and key.
+ string GetText(int id, int key);
+}
diff --git a/src/Tomas.Kernel/Globalization/UIText.cs b/src/Tomas.Kernel/Globalization/UIText.cs
new file mode 100644
index 0000000..cf2bd26
--- /dev/null
+++ b/src/Tomas.Kernel/Globalization/UIText.cs
@@ -0,0 +1,101 @@
+// This project is licensed under the BSD 3-Clause license.
+// See the LICENSE file in the project root for more information.
+
+namespace Tomas.Kernel.Globalization;
+
+public class UIText : IUIText
+{
+ ///
+ /// The language of the text.
+ ///
+ string Language { get; set; } = "english";
+
+ ///
+ /// The base directory for the language files.
+ ///
+ public string[] BasePath { get; set; } = { AppContext.BaseDirectory, "uitext" };
+
+ ///
+ /// Constructor for the UIText class.
+ ///
+ public UIText() { }
+
+ ///
+ /// Constructor for the UIText class.
+ /// Loads the language file for the specified language.
+ ///
+ /// Language to load
+ public UIText(string language)
+ {
+ Language = language;
+ }
+
+ ///
+ /// Constructor for the UIText class.
+ /// Loads the language file for the specified language and base directory.
+ ///
+ /// Language to load
+ /// Base directory for the language files.
+ public UIText(string language, params string[] baseBath)
+ {
+ Language = language;
+ BasePath = baseBath;
+ }
+
+ ///
+ /// Get the text for the given id and key.
+ ///
+ /// The id of the text.
+ /// The key of the text.
+ /// The text for the given id and key.
+ public string GetText(int id, int key) => GetText(id, key.ToString());
+
+ ///
+ /// Get the text for the given id and key.
+ ///
+ /// The id of the text.
+ /// The key of the text.
+ /// The text for the given id and key.
+ public string GetText(int id, string key)
+ {
+ // Combine the base path and language path to get the full path of the language file.
+ var basePath = Path.Combine(BasePath);
+ var langPath = Path.Combine(basePath, $"{Language}.dir");
+
+ // Get all the files in the language directory.
+ var files = Directory.GetFiles(langPath);
+
+ // Iterate through the files in the language directory.
+ foreach (var file in files)
+ {
+ // Skip files that do not have the ".cst" extension.
+ if (!file.Contains(".cst"))
+ continue;
+
+ // Get the id of the current file.
+ var ids = Path.GetFileName(file);
+ var second = ids.IndexOf("_", 1, StringComparison.InvariantCultureIgnoreCase);
+
+ if (second == -1)
+ continue;
+
+ ids = ids.Substring(1, second - 1);
+
+ // If the id of the current file does not match the id passed to the function,
+ // skip to the next file.
+ if (ids != id.ToString())
+ continue;
+
+ // Read the content of the current file.
+ var content = File.ReadAllText(file);
+
+ // Return the text for the specified key.
+ return CST.Parse(content, key);
+ }
+
+ // If no text is found, return a default string.
+ return "***MISSING***";
+ }
+
+}
+
diff --git a/src/Tomas.Kernel/SysFS.cs b/src/Tomas.Kernel/SysFS.cs
index 73118b9..ae905f5 100644
--- a/src/Tomas.Kernel/SysFS.cs
+++ b/src/Tomas.Kernel/SysFS.cs
@@ -6,13 +6,13 @@ namespace Tomas.Kernel;
static class SysFS
{
// The root directory of the file system
- const string ROOT_DIR = "0:\\";
+ public const string ROOT_DIR = "0:\\";
// The system directory, located in the root directory
static string SYSTEM_DIR = $"{ROOT_DIR}\\SYSTEM\\";
static string LOG_FILE = $"{SYSTEM_DIR}system.log";
- const string FS_ERROR = "File system disabled.";
+ public const string FS_ERROR = "File system disabled.";
///
/// An instance of the CosmosVFS class, used for accessing the virtual file system
diff --git a/src/Tomas.Common/SysMeta.cs b/src/Tomas.Kernel/SysMeta.cs
similarity index 87%
rename from src/Tomas.Common/SysMeta.cs
rename to src/Tomas.Kernel/SysMeta.cs
index 80c9505..86d4b83 100644
--- a/src/Tomas.Common/SysMeta.cs
+++ b/src/Tomas.Kernel/SysMeta.cs
@@ -1,13 +1,8 @@
-// I license this project under the BSD 3-Clause license.
-// See the LICENSE file in the project root for more information.
using System.Text;
-namespace Tomas.Common;
+namespace Tomas.Kernel;
-///
-/// System metdata, such as name, version and build number.
-///
-public struct SysMeta
+internal struct SysMeta
{
///
/// The name of the operating system.
diff --git a/src/Tomas.Kernel/Tomas.Kernel.csproj b/src/Tomas.Kernel/Tomas.Kernel.csproj
index eeb902b..f15c019 100644
--- a/src/Tomas.Kernel/Tomas.Kernel.csproj
+++ b/src/Tomas.Kernel/Tomas.Kernel.csproj
@@ -25,10 +25,14 @@
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
-
+
diff --git a/src/Tomas.Terminal/GitInfo.txt b/src/Tomas.Terminal/GitInfo.txt
new file mode 100644
index 0000000..ceab6e1
--- /dev/null
+++ b/src/Tomas.Terminal/GitInfo.txt
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/src/Tomas.Terminal/GlobalUsing.cs b/src/Tomas.Terminal/GlobalUsing.cs
index 6169845..a3f2539 100644
--- a/src/Tomas.Terminal/GlobalUsing.cs
+++ b/src/Tomas.Terminal/GlobalUsing.cs
@@ -1,2 +1,4 @@
+global using System.Diagnostics.CodeAnalysis;
+global using System.Diagnostics;
global using Tomas.Common.Programs;
global using Tomas.Interface;
\ No newline at end of file
diff --git a/src/Tomas.Terminal/Programs/About.cs b/src/Tomas.Terminal/Programs/About.cs
index bf3e15f..6c716fa 100644
--- a/src/Tomas.Terminal/Programs/About.cs
+++ b/src/Tomas.Terminal/Programs/About.cs
@@ -6,10 +6,9 @@ namespace Tomas.Terminal.Programs;
public class About : IProgram
{
-public bool Run(IShell shell)
-{
-Console.WriteLine($"{SysMeta.NAME} Terminal Emulator v{SysMeta.BuildNumber}{Environment.NewLine}"
- + "TOMAS (Tony's Managed Operating System) is a operating system written in C# using the COSMOS framework.");
-return true;
-}
+ public bool Run(IShell shell)
+ {
+ Console.WriteLine($"{TermMeta.NAME} Terminal Emulator v{TermMeta.VERSION}");
+ return true;
+ }
}
\ No newline at end of file
diff --git a/src/Tomas.Terminal/TermMeta.cs b/src/Tomas.Terminal/TermMeta.cs
new file mode 100644
index 0000000..7eb564e
--- /dev/null
+++ b/src/Tomas.Terminal/TermMeta.cs
@@ -0,0 +1,48 @@
+// I license this project under the BSD 3-Clause license.
+// See the LICENSE file in the project root for more information.
+using System.Text;
+
+namespace Tomas.Common;
+
+///
+/// System metdata, such as name, version and build number.
+///
+public struct TermMeta
+{
+ ///
+ /// The name of the operating system.
+ ///
+ public const string NAME = "TOMAS Emulator";
+
+ ///
+ /// The version of the operating system, in the Calendar Versioning format: "yy.minor.patch".
+ /// The year, minor, and patch version numbers are automatically extracted from the Git repository
+ /// using the ThisAssembly.Git.SemVer object.
+ ///
+ public const string VERSION = $"{ThisAssembly.Git.SemVer.Major}.{ThisAssembly.Git.SemVer.Minor}.{ThisAssembly.Git.SemVer.Patch}";
+
+ ///
+ /// The build number of the operating system, generated from the commit hash.
+ /// The build number is a 6-digit number, with the first 3 digits being the first 3 digits of the commit hash
+ /// converted to a uint, and the last 3 digits being the last 3 digits of the commit hash converted to a uint.
+ ///
+ public static string BuildNumber = $"Build {BuildNumFromCommit}";
+
+ ///
+ /// Generates the build number from the commit hash.
+ ///
+ /// The build number as a uint.
+ static uint BuildNumFromCommit
+ {
+ get
+ {
+ // Get the bytes of the commit hash as a UTF-8 encoded string
+ var commit = Encoding.UTF8.GetBytes(ThisAssembly.Git.Commit);
+
+ // Convert the first 4 bytes of the commit hash to a uint and return it modulo 1000000
+ // (this will give us a 6-digit number with the first 3 digits being the first 3 digits of the commit hash
+ // and the last 3 digits being the last 3 digits of the commit hash)
+ return BitConverter.ToUInt32(commit, 0) % 1000000;
+ }
+ }
+}
diff --git a/src/Tomas.Terminal/Tomas.Terminal.csproj b/src/Tomas.Terminal/Tomas.Terminal.csproj
index f466519..91627f1 100644
--- a/src/Tomas.Terminal/Tomas.Terminal.csproj
+++ b/src/Tomas.Terminal/Tomas.Terminal.csproj
@@ -8,7 +8,15 @@
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+