From f734a8a6db35a75d31b4662adc6f23bf22922cd0 Mon Sep 17 00:00:00 2001 From: Latency McLaughlin Date: Tue, 17 Mar 2020 19:29:01 -0700 Subject: [PATCH] Moved SRC and Test folders to root directory. Refactored static ReadLine class to a true singleton. Changed unit tests to use NUnit instead of XUnit. Fixed Ctrl+C issue #59 (Add option to return CTRL+C) Updated version. --- Artifacts/ReadLine.2.1.3.nupkg | Bin 0 -> 43618 bytes .../AutoCompleteHandler.cs | 56 +- .../Program.cs | 62 +- .../ReadLine.Demo.csproj | 30 +- .../Abstractions/Console2.cs | 0 .../AutoCompleteHandler.cs | 0 .../CharExtensions.cs | 2 + .../ConsoleKeyInfoExtensions.cs | 1 + .../KeyHandlerTests.cs | 156 ++-- ReadLine.Tests/ReadLine.Tests.csproj | 22 + ReadLine.Tests/ReadLineTests.cs | 51 ++ ReadLine.sln | 10 +- .../Abstractions/Console2.cs | 0 .../Abstractions/IConsole.cs | 0 .../IAutoCompleteHandler.cs | 0 ReadLine/IReadLine.cs | 12 + {src/ReadLine => ReadLine}/KeyHandler.cs | 709 +++++++++--------- {src/ReadLine => ReadLine}/ReadLine.cs | 24 +- {src/ReadLine => ReadLine}/ReadLine.csproj | 2 +- {src/ReadLine => ReadLine}/snKey.snk | Bin artifacts/ReadLine.2.0.3.nupkg | Bin 41824 -> 0 bytes test/ReadLine.Tests/ReadLine.Tests.csproj | 19 - test/ReadLine.Tests/ReadLineTests.cs | 46 -- 23 files changed, 618 insertions(+), 584 deletions(-) create mode 100644 Artifacts/ReadLine.2.1.3.nupkg rename {src/ReadLine.Demo => ReadLine.Demo}/AutoCompleteHandler.cs (95%) rename {src/ReadLine.Demo => ReadLine.Demo}/Program.cs (65%) mode change 100755 => 100644 rename {src/ReadLine.Demo => ReadLine.Demo}/ReadLine.Demo.csproj (96%) mode change 100755 => 100644 rename {test/ReadLine.Tests => ReadLine.Tests}/Abstractions/Console2.cs (100%) rename {test/ReadLine.Tests => ReadLine.Tests}/AutoCompleteHandler.cs (100%) rename {test/ReadLine.Tests => ReadLine.Tests}/CharExtensions.cs (96%) rename {test/ReadLine.Tests => ReadLine.Tests}/ConsoleKeyInfoExtensions.cs (96%) rename {test/ReadLine.Tests => ReadLine.Tests}/KeyHandlerTests.cs (69%) create mode 100644 ReadLine.Tests/ReadLine.Tests.csproj create mode 100644 ReadLine.Tests/ReadLineTests.cs rename {src/ReadLine => ReadLine}/Abstractions/Console2.cs (100%) rename {src/ReadLine => ReadLine}/Abstractions/IConsole.cs (100%) rename {src/ReadLine => ReadLine}/IAutoCompleteHandler.cs (100%) create mode 100644 ReadLine/IReadLine.cs rename {src/ReadLine => ReadLine}/KeyHandler.cs (96%) rename {src/ReadLine => ReadLine}/ReadLine.cs (61%) mode change 100755 => 100644 rename {src/ReadLine => ReadLine}/ReadLine.csproj (98%) mode change 100755 => 100644 rename {src/ReadLine => ReadLine}/snKey.snk (100%) delete mode 100644 artifacts/ReadLine.2.0.3.nupkg delete mode 100755 test/ReadLine.Tests/ReadLine.Tests.csproj delete mode 100755 test/ReadLine.Tests/ReadLineTests.cs diff --git a/Artifacts/ReadLine.2.1.3.nupkg b/Artifacts/ReadLine.2.1.3.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..f73310b4b17d782f99d40ed01c69c42032118a88 GIT binary patch literal 43618 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 bWc?qEYRd9(@K0ZX3_KWt3zH=0>D~VWD$AVN literal 0 HcmV?d00001 diff --git a/src/ReadLine.Demo/AutoCompleteHandler.cs b/ReadLine.Demo/AutoCompleteHandler.cs similarity index 95% rename from src/ReadLine.Demo/AutoCompleteHandler.cs rename to ReadLine.Demo/AutoCompleteHandler.cs index 44e188b..8fa9a11 100644 --- a/src/ReadLine.Demo/AutoCompleteHandler.cs +++ b/ReadLine.Demo/AutoCompleteHandler.cs @@ -1,28 +1,28 @@ -namespace ReadLine.Demo -{ - internal class AutoCompletionHandler : IAutoCompleteHandler - { - public char[] Separators { get; set; } = - { - ' ', - '.', - '/', - '\\', - ':' - }; - - - public string[] GetSuggestions(string text, int index) - { - return text.StartsWith("git ") - ? new[] - { - "init", - "clone", - "pull", - "push" - } - : null; - } - } -} +namespace ReadLine.Demo +{ + internal class AutoCompletionHandler : IAutoCompleteHandler + { + public char[] Separators { get; set; } = + { + ' ', + '.', + '/', + '\\', + ':' + }; + + + public string[] GetSuggestions(string text, int index) + { + return text.StartsWith("git ") + ? new[] + { + "init", + "clone", + "pull", + "push" + } + : null; + } + } +} diff --git a/src/ReadLine.Demo/Program.cs b/ReadLine.Demo/Program.cs old mode 100755 new mode 100644 similarity index 65% rename from src/ReadLine.Demo/Program.cs rename to ReadLine.Demo/Program.cs index 896f066..5be4213 --- a/src/ReadLine.Demo/Program.cs +++ b/ReadLine.Demo/Program.cs @@ -1,31 +1,33 @@ -using System; - - -namespace ReadLine.Demo -{ - public class Program - { - public static void Main(string[] args) - { - Console.WriteLine("ReadLine Library Demo"); - Console.WriteLine("---------------------"); - Console.WriteLine(); - - string[] history = - { - "ls -a", - "dotnet run", - "git init" - }; - ReadLine.AddHistory(history); - - ReadLine.AutoCompletionHandler = new AutoCompletionHandler(); - - var input = ReadLine.Read("(prompt)> "); - Console.WriteLine(input); - - input = ReadLine.ReadPassword("Enter Password> "); - Console.WriteLine(input); - } - } +using System; + + +namespace ReadLine.Demo +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("ReadLine Library Demo"); + Console.WriteLine("---------------------"); + Console.WriteLine(); + + string[] history = + { + "ls -a", + "dotnet run", + "git init" + }; + + IReadLine readLine = ReadLine.Instance; + readLine.AddHistory(history); + + readLine.AutoCompletionHandler = new AutoCompletionHandler(); + + var input = readLine.Read("(prompt)> "); + Console.WriteLine(input); + + input = readLine.ReadPassword("Enter Password> "); + Console.WriteLine(input); + } + } } \ No newline at end of file diff --git a/src/ReadLine.Demo/ReadLine.Demo.csproj b/ReadLine.Demo/ReadLine.Demo.csproj old mode 100755 new mode 100644 similarity index 96% rename from src/ReadLine.Demo/ReadLine.Demo.csproj rename to ReadLine.Demo/ReadLine.Demo.csproj index a1a89cb..039c0da --- a/src/ReadLine.Demo/ReadLine.Demo.csproj +++ b/ReadLine.Demo/ReadLine.Demo.csproj @@ -1,15 +1,15 @@ - - - - netcoreapp2.2 - portable - ReadLine.Demo - Exe - ReadLine.Demo - - - - - - - + + + + netcoreapp2.2 + portable + ReadLine.Demo + Exe + ReadLine.Demo + + + + + + + diff --git a/test/ReadLine.Tests/Abstractions/Console2.cs b/ReadLine.Tests/Abstractions/Console2.cs similarity index 100% rename from test/ReadLine.Tests/Abstractions/Console2.cs rename to ReadLine.Tests/Abstractions/Console2.cs diff --git a/test/ReadLine.Tests/AutoCompleteHandler.cs b/ReadLine.Tests/AutoCompleteHandler.cs similarity index 100% rename from test/ReadLine.Tests/AutoCompleteHandler.cs rename to ReadLine.Tests/AutoCompleteHandler.cs diff --git a/test/ReadLine.Tests/CharExtensions.cs b/ReadLine.Tests/CharExtensions.cs similarity index 96% rename from test/ReadLine.Tests/CharExtensions.cs rename to ReadLine.Tests/CharExtensions.cs index 7d0e892..2888008 100644 --- a/test/ReadLine.Tests/CharExtensions.cs +++ b/ReadLine.Tests/CharExtensions.cs @@ -11,6 +11,7 @@ public static class CharExtensions public const char CtrlA = '\u0001'; public const char CtrlB = '\u0002'; + public const char CtrlC = '\u0003'; public const char CtrlD = '\u0004'; public const char CtrlE = '\u0005'; public const char CtrlF = '\u0006'; @@ -29,6 +30,7 @@ public static class CharExtensions {Space, Tuple.Create(ConsoleKey.Spacebar, NoModifiers())}, {CtrlA, Tuple.Create(ConsoleKey.A, ConsoleModifiers.Control)}, {CtrlB, Tuple.Create(ConsoleKey.B, ConsoleModifiers.Control)}, + {CtrlC, Tuple.Create(ConsoleKey.C, ConsoleModifiers.Control)}, {CtrlD, Tuple.Create(ConsoleKey.D, ConsoleModifiers.Control)}, {CtrlE, Tuple.Create(ConsoleKey.E, ConsoleModifiers.Control)}, {CtrlF, Tuple.Create(ConsoleKey.F, ConsoleModifiers.Control)}, diff --git a/test/ReadLine.Tests/ConsoleKeyInfoExtensions.cs b/ReadLine.Tests/ConsoleKeyInfoExtensions.cs similarity index 96% rename from test/ReadLine.Tests/ConsoleKeyInfoExtensions.cs rename to ReadLine.Tests/ConsoleKeyInfoExtensions.cs index e604a17..e2497e9 100644 --- a/test/ReadLine.Tests/ConsoleKeyInfoExtensions.cs +++ b/ReadLine.Tests/ConsoleKeyInfoExtensions.cs @@ -23,6 +23,7 @@ public static class ConsoleKeyInfoExtensions public static readonly ConsoleKeyInfo Space = CharExtensions.Space.ToConsoleKeyInfo(); public static readonly ConsoleKeyInfo CtrlA = CharExtensions.CtrlA.ToConsoleKeyInfo(); public static readonly ConsoleKeyInfo CtrlB = CharExtensions.CtrlB.ToConsoleKeyInfo(); + public static readonly ConsoleKeyInfo CtrlC = CharExtensions.CtrlC.ToConsoleKeyInfo(); public static readonly ConsoleKeyInfo CtrlD = CharExtensions.CtrlD.ToConsoleKeyInfo(); public static readonly ConsoleKeyInfo CtrlE = CharExtensions.CtrlE.ToConsoleKeyInfo(); public static readonly ConsoleKeyInfo CtrlF = CharExtensions.CtrlF.ToConsoleKeyInfo(); diff --git a/test/ReadLine.Tests/KeyHandlerTests.cs b/ReadLine.Tests/KeyHandlerTests.cs similarity index 69% rename from test/ReadLine.Tests/KeyHandlerTests.cs rename to ReadLine.Tests/KeyHandlerTests.cs index 30705e1..4a48dad 100644 --- a/test/ReadLine.Tests/KeyHandlerTests.cs +++ b/ReadLine.Tests/KeyHandlerTests.cs @@ -1,23 +1,25 @@ using System; using System.Collections.Generic; using System.Linq; +using NUnit.Framework; using ReadLine.Abstractions; using ReadLine.Tests.Abstractions; -using Xunit; using static ReadLine.Tests.ConsoleKeyInfoExtensions; namespace ReadLine.Tests { + [TestFixture] public class KeyHandlerTests { private KeyHandler _keyHandler; - private readonly List _history; - private readonly AutoCompleteHandler _autoCompleteHandler; - private readonly string[] _completions; - private readonly IConsole _console; + private List _history; + private AutoCompleteHandler _autoCompleteHandler; + private string[] _completions; + private IConsole _console; - public KeyHandlerTests() + [SetUp] + public void Initialize() { _autoCompleteHandler = new AutoCompleteHandler(); _completions = _autoCompleteHandler.GetSuggestions("", 0); @@ -31,59 +33,65 @@ public KeyHandlerTests() .ForEach(_keyHandler.Handle); } - [Fact] + [Test] public void TestWriteChar() { - Assert.Equal("Hello", _keyHandler.Text); + Assert.AreEqual("Hello", _keyHandler.Text); " World".Select(c => c.ToConsoleKeyInfo()) .ToList() .ForEach(_keyHandler.Handle); - Assert.Equal("Hello World", _keyHandler.Text); + Assert.AreEqual("Hello World", _keyHandler.Text); } - [Fact] + [Test] public void TestBackspace() { _keyHandler.Handle(Backspace); - Assert.Equal("Hell", _keyHandler.Text); + Assert.AreEqual("Hell", _keyHandler.Text); } - [Fact] + [Test] public void TestDelete() { new List() { LeftArrow, Delete } .ForEach(_keyHandler.Handle); - Assert.Equal("Hell", _keyHandler.Text); + Assert.AreEqual("Hell", _keyHandler.Text); } - [Fact] + [Test] public void TestDelete_EndOfLine() { _keyHandler.Handle(Delete); - Assert.Equal("Hello", _keyHandler.Text); + Assert.AreEqual("Hello", _keyHandler.Text); } - [Fact] + [Test] + public void TestControlC() { + //_keyHandler.Handle(CtrlC); + Assert.Ignore("Unable to test."); + } + + [Test] public void TestControlH() { _keyHandler.Handle(CtrlH); - Assert.Equal("Hell", _keyHandler.Text); + Assert.AreEqual("Hell", _keyHandler.Text); } - [Fact] + [Test] public void TestControlT() { var initialCursorCol = _console.CursorLeft; _keyHandler.Handle(CtrlT); - Assert.Equal("Helol", _keyHandler.Text); - Assert.Equal(initialCursorCol, _console.CursorLeft); + Assert.AreEqual("Helol", _keyHandler.Text); + Assert.AreEqual(initialCursorCol, _console.CursorLeft); } - [Fact] + [Test] public void TestControlT_LeftOnce_CursorMovesToEnd() { var initialCursorCol = _console.CursorLeft; @@ -91,11 +99,11 @@ public void TestControlT_LeftOnce_CursorMovesToEnd() new List() { LeftArrow, CtrlT } .ForEach(_keyHandler.Handle); - Assert.Equal("Helol", _keyHandler.Text); - Assert.Equal(initialCursorCol, _console.CursorLeft); + Assert.AreEqual("Helol", _keyHandler.Text); + Assert.AreEqual(initialCursorCol, _console.CursorLeft); } - [Fact] + [Test] public void TestControlT_CursorInMiddleOfLine() { Enumerable @@ -107,11 +115,11 @@ public void TestControlT_CursorInMiddleOfLine() _keyHandler.Handle(CtrlT); - Assert.Equal("Hlelo", _keyHandler.Text); - Assert.Equal(initialCursorCol + 1, _console.CursorLeft); + Assert.AreEqual("Hlelo", _keyHandler.Text); + Assert.AreEqual(initialCursorCol + 1, _console.CursorLeft); } - [Fact] + [Test] public void TestControlT_CursorAtBeginningOfLine_HasNoEffect() { _keyHandler.Handle(CtrlA); @@ -120,47 +128,47 @@ public void TestControlT_CursorAtBeginningOfLine_HasNoEffect() _keyHandler.Handle(CtrlT); - Assert.Equal("Hello", _keyHandler.Text); - Assert.Equal(initialCursorCol, _console.CursorLeft); + Assert.AreEqual("Hello", _keyHandler.Text); + Assert.AreEqual(initialCursorCol, _console.CursorLeft); } - [Fact] + [Test] public void TestHome() { new List() { Home, 'S'.ToConsoleKeyInfo() } .ForEach(_keyHandler.Handle); - Assert.Equal("SHello", _keyHandler.Text); + Assert.AreEqual("SHello", _keyHandler.Text); } - [Fact] + [Test] public void TestControlA() { new List() { CtrlA, 'S'.ToConsoleKeyInfo() } .ForEach(_keyHandler.Handle); - Assert.Equal("SHello", _keyHandler.Text); + Assert.AreEqual("SHello", _keyHandler.Text); } - [Fact] + [Test] public void TestEnd() { new List() { Home, End, ExclamationPoint } .ForEach(_keyHandler.Handle); - Assert.Equal("Hello!", _keyHandler.Text); + Assert.AreEqual("Hello!", _keyHandler.Text); } - [Fact] + [Test] public void TestControlE() { new List() { CtrlA, CtrlE, ExclamationPoint } .ForEach(_keyHandler.Handle); - Assert.Equal("Hello!", _keyHandler.Text); + Assert.AreEqual("Hello!", _keyHandler.Text); } - [Fact] + [Test] public void TestLeftArrow() { " N".Select(c => c.ToConsoleKeyInfo()) @@ -168,10 +176,10 @@ public void TestLeftArrow() .ToList() .ForEach(_keyHandler.Handle); - Assert.Equal("Hell No", _keyHandler.Text); + Assert.AreEqual("Hell No", _keyHandler.Text); } - [Fact] + [Test] public void TestControlB() { " N".Select(c => c.ToConsoleKeyInfo()) @@ -179,19 +187,19 @@ public void TestControlB() .ToList() .ForEach(_keyHandler.Handle); - Assert.Equal("Hell No", _keyHandler.Text); + Assert.AreEqual("Hell No", _keyHandler.Text); } - [Fact] + [Test] public void TestRightArrow() { new List() { LeftArrow, RightArrow, ExclamationPoint } .ForEach(_keyHandler.Handle); - Assert.Equal("Hello!", _keyHandler.Text); + Assert.AreEqual("Hello!", _keyHandler.Text); } - [Fact] + [Test] public void TestControlD() { Enumerable.Repeat(LeftArrow, 4) @@ -199,44 +207,44 @@ public void TestControlD() .ToList() .ForEach(_keyHandler.Handle); - Assert.Equal("Hllo", _keyHandler.Text); + Assert.AreEqual("Hllo", _keyHandler.Text); } - [Fact] + [Test] public void TestControlF() { new List() { LeftArrow, CtrlF, ExclamationPoint } .ForEach(_keyHandler.Handle); - Assert.Equal("Hello!", _keyHandler.Text); + Assert.AreEqual("Hello!", _keyHandler.Text); } - [Fact] + [Test] public void TestControlL() { _keyHandler.Handle(CtrlL); - Assert.Equal(string.Empty, _keyHandler.Text); + Assert.AreEqual(string.Empty, _keyHandler.Text); } - [Fact] + [Test] public void TestUpArrow() { _history.AsEnumerable().Reverse().ToList().ForEach((history) => { _keyHandler.Handle(UpArrow); - Assert.Equal(history, _keyHandler.Text); + Assert.AreEqual(history, _keyHandler.Text); }); } - [Fact] + [Test] public void TestControlP() { _history.AsEnumerable().Reverse().ToList().ForEach((history) => { _keyHandler.Handle(CtrlP); - Assert.Equal(history, _keyHandler.Text); + Assert.AreEqual(history, _keyHandler.Text); }); } - [Fact] + [Test] public void TestDownArrow() { Enumerable.Repeat(UpArrow, _history.Count) @@ -244,12 +252,12 @@ public void TestDownArrow() .ForEach(_keyHandler.Handle); _history.ForEach( history => { - Assert.Equal(history, _keyHandler.Text); + Assert.AreEqual(history, _keyHandler.Text); _keyHandler.Handle(DownArrow); }); } - [Fact] + [Test] public void TestControlN() { Enumerable.Repeat(UpArrow, _history.Count) @@ -257,40 +265,40 @@ public void TestControlN() .ForEach(_keyHandler.Handle); _history.ForEach( history => { - Assert.Equal(history, _keyHandler.Text); + Assert.AreEqual(history, _keyHandler.Text); _keyHandler.Handle(CtrlN); }); } - [Fact] + [Test] public void TestControlU() { _keyHandler.Handle(LeftArrow); _keyHandler.Handle(CtrlU); - Assert.Equal("o", _keyHandler.Text); + Assert.AreEqual("o", _keyHandler.Text); _keyHandler.Handle(End); _keyHandler.Handle(CtrlU); - Assert.Equal(string.Empty, _keyHandler.Text); + Assert.AreEqual(string.Empty, _keyHandler.Text); } - [Fact] + [Test] public void TestControlK() { _keyHandler.Handle(LeftArrow); _keyHandler.Handle(CtrlK); - Assert.Equal("Hell", _keyHandler.Text); + Assert.AreEqual("Hell", _keyHandler.Text); _keyHandler.Handle(Home); _keyHandler.Handle(CtrlK); - Assert.Equal(string.Empty, _keyHandler.Text); + Assert.AreEqual(string.Empty, _keyHandler.Text); } - [Fact] + [Test] public void TestControlW() { " World".Select(c => c.ToConsoleKeyInfo()) @@ -298,20 +306,20 @@ public void TestControlW() .ToList() .ForEach(_keyHandler.Handle); - Assert.Equal("Hello ", _keyHandler.Text); + Assert.AreEqual("Hello ", _keyHandler.Text); _keyHandler.Handle(Backspace); _keyHandler.Handle(CtrlW); - Assert.Equal(string.Empty, _keyHandler.Text); + Assert.AreEqual(string.Empty, _keyHandler.Text); } - [Fact] + [Test] public void TestTab() { _keyHandler.Handle(Tab); // Nothing happens when no auto complete handler is set - Assert.Equal("Hello", _keyHandler.Text); + Assert.AreEqual("Hello", _keyHandler.Text); _keyHandler = new KeyHandler(new Console2(), _history, _autoCompleteHandler); @@ -319,17 +327,17 @@ public void TestTab() _completions.ToList().ForEach(completion => { _keyHandler.Handle(Tab); - Assert.Equal($"Hi {completion}", _keyHandler.Text); + Assert.AreEqual($"Hi {completion}", _keyHandler.Text); }); } - [Fact] + [Test] public void TestBackwardsTab() { _keyHandler.Handle(Tab); // Nothing happens when no auto complete handler is set - Assert.Equal("Hello", _keyHandler.Text); + Assert.AreEqual("Hello", _keyHandler.Text); _keyHandler = new KeyHandler(new Console2(), _history, _autoCompleteHandler); @@ -340,17 +348,17 @@ public void TestBackwardsTab() _completions.Reverse().ToList().ForEach(completion => { _keyHandler.Handle(ShiftTab); - Assert.Equal($"Hi {completion}", _keyHandler.Text); + Assert.AreEqual($"Hi {completion}", _keyHandler.Text); }); } - [Fact] + [Test] public void MoveCursorThenPreviousHistory() { _keyHandler.Handle(LeftArrow); _keyHandler.Handle(UpArrow); - Assert.Equal("clear", _keyHandler.Text); + Assert.AreEqual("clear", _keyHandler.Text); } } } \ No newline at end of file diff --git a/ReadLine.Tests/ReadLine.Tests.csproj b/ReadLine.Tests/ReadLine.Tests.csproj new file mode 100644 index 0000000..568a4fb --- /dev/null +++ b/ReadLine.Tests/ReadLine.Tests.csproj @@ -0,0 +1,22 @@ + + + + net472 + ReadLine.Tests + ReadLine.Tests + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/ReadLine.Tests/ReadLineTests.cs b/ReadLine.Tests/ReadLineTests.cs new file mode 100644 index 0000000..f07e200 --- /dev/null +++ b/ReadLine.Tests/ReadLineTests.cs @@ -0,0 +1,51 @@ +using System.Linq; +using NUnit.Framework; + + +namespace ReadLine.Tests +{ + [TestFixture] + public class ReadLineTests + { + private readonly IReadLine _readLine = ReadLine.Instance; + private static readonly string[] History = { "ls -a", "dotnet run", "git init" }; + + [SetUp] + public void Initialize() { + _readLine.AddHistory(History); + } + + [TearDown] + public void Destruct() { + _readLine.ClearHistory(); + } + + [Test] + public void TestClearHistory() { + _readLine.ClearHistory(); + Assert.AreEqual(0, _readLine.GetHistory().Count); + } + + [Test] + public void TestNoInitialHistory() + { + Assert.AreEqual(3, _readLine.GetHistory().Count); + } + + [Test] + public void TestUpdatesHistory() + { + _readLine.AddHistory("mkdir"); + Assert.AreEqual(4, _readLine.GetHistory().Count); + Assert.AreEqual("mkdir", _readLine.GetHistory().Last()); + } + + [Test] + public void TestGetCorrectHistory() + { + Assert.AreEqual("ls -a", _readLine.GetHistory()[0]); + Assert.AreEqual("dotnet run", _readLine.GetHistory()[1]); + Assert.AreEqual("git init", _readLine.GetHistory()[2]); + } + } +} diff --git a/ReadLine.sln b/ReadLine.sln index d0fa19b..489bf7c 100755 --- a/ReadLine.sln +++ b/ReadLine.sln @@ -2,15 +2,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2036 MinimumVisualStudioVersion = 15.0.26124.0 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{06FC0E85-E73C-4DC1-B6FD-A583B7B1DFE4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReadLine", "ReadLine\ReadLine.csproj", "{9EB290C9-BB52-4B24-9779-5A816AC75E18}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReadLine", "src\ReadLine\ReadLine.csproj", "{9EB290C9-BB52-4B24-9779-5A816AC75E18}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReadLine.Demo", "ReadLine.Demo\ReadLine.Demo.csproj", "{4C512FD1-A0E8-4908-B0A4-B0D85947716A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReadLine.Demo", "src\ReadLine.Demo\ReadLine.Demo.csproj", "{4C512FD1-A0E8-4908-B0A4-B0D85947716A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{38C56AEB-DB08-4CBF-AAC0-EBFC2B0EE045}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReadLine.Tests", "test\ReadLine.Tests\ReadLine.Tests.csproj", "{631582D9-EEEA-4F9D-8069-71ECA24ED282}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReadLine.Tests", "ReadLine.Tests\ReadLine.Tests.csproj", "{631582D9-EEEA-4F9D-8069-71ECA24ED282}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/ReadLine/Abstractions/Console2.cs b/ReadLine/Abstractions/Console2.cs similarity index 100% rename from src/ReadLine/Abstractions/Console2.cs rename to ReadLine/Abstractions/Console2.cs diff --git a/src/ReadLine/Abstractions/IConsole.cs b/ReadLine/Abstractions/IConsole.cs similarity index 100% rename from src/ReadLine/Abstractions/IConsole.cs rename to ReadLine/Abstractions/IConsole.cs diff --git a/src/ReadLine/IAutoCompleteHandler.cs b/ReadLine/IAutoCompleteHandler.cs similarity index 100% rename from src/ReadLine/IAutoCompleteHandler.cs rename to ReadLine/IAutoCompleteHandler.cs diff --git a/ReadLine/IReadLine.cs b/ReadLine/IReadLine.cs new file mode 100644 index 0000000..e7ab988 --- /dev/null +++ b/ReadLine/IReadLine.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace ReadLine { + public interface IReadLine { + IAutoCompleteHandler AutoCompletionHandler { get; set; } + void AddHistory(params string[] text); + List GetHistory(); + void ClearHistory(); + string Read(string prompt = "", string @default = ""); + string ReadPassword(string prompt = ""); + } +} diff --git a/src/ReadLine/KeyHandler.cs b/ReadLine/KeyHandler.cs similarity index 96% rename from src/ReadLine/KeyHandler.cs rename to ReadLine/KeyHandler.cs index 075700e..5fb3824 100644 --- a/src/ReadLine/KeyHandler.cs +++ b/ReadLine/KeyHandler.cs @@ -1,355 +1,356 @@ -using System; -using System.Collections.Generic; -using System.Text; -using ReadLine.Abstractions; - - -namespace ReadLine -{ - public class KeyHandler - { - private readonly IConsole _console2; - private readonly List _history; - private readonly Dictionary _keyActions; - private readonly StringBuilder _text; - private string[] _completions; - private int _completionsIndex; - private int _completionStart; - private int _cursorLimit; - private int _cursorPos; - private int _historyIndex; - private ConsoleKeyInfo _keyInfo; - - public KeyHandler(IConsole console, List history, IAutoCompleteHandler autoCompleteHandler) - { - _console2 = console; - - _history = history ?? new List(); - _historyIndex = _history.Count; - _text = new StringBuilder(); - _keyActions = new Dictionary - { - ["LeftArrow"] = MoveCursorLeft, - ["Home"] = MoveCursorHome, - ["End"] = MoveCursorEnd, - ["ControlA"] = MoveCursorHome, - ["ControlB"] = MoveCursorLeft, - ["RightArrow"] = MoveCursorRight, - ["ControlF"] = MoveCursorRight, - ["ControlE"] = MoveCursorEnd, - ["Backspace"] = Backspace, - ["Delete"] = Delete, - ["ControlD"] = Delete, - ["ControlH"] = Backspace, - ["ControlL"] = ClearLine, - ["Escape"] = ClearLine, - ["UpArrow"] = PrevHistory, - ["ControlP"] = PrevHistory, - ["DownArrow"] = NextHistory, - ["ControlN"] = NextHistory, - ["ControlU"] = () => { Backspace(_cursorPos); }, - ["ControlK"] = () => - { - var pos = _cursorPos; - MoveCursorEnd(); - Backspace(_cursorPos - pos); - }, - ["ControlW"] = () => - { - while (!IsStartOfLine() && _text[_cursorPos - 1] != ' ') - Backspace(); - }, - ["ControlT"] = TransposeChars, - ["Tab"] = () => - { - if (IsInAutoCompleteMode()) - { - NextAutoComplete(); - } - else - { - if (autoCompleteHandler == null || !IsEndOfLine()) - return; - - var text = _text.ToString(); - - _completionStart = text.LastIndexOfAny(autoCompleteHandler.Separators); - _completionStart = _completionStart == -1 ? 0 : _completionStart + 1; - - _completions = autoCompleteHandler.GetSuggestions(text, _completionStart); - _completions = _completions?.Length == 0 ? null : _completions; - - if (_completions == null) - return; - - StartAutoComplete(); - } - }, - ["ShiftTab"] = () => - { - if (IsInAutoCompleteMode()) - PreviousAutoComplete(); - } - }; - } - - - public string Text => _text.ToString(); - - - private bool IsStartOfLine() => _cursorPos == 0; - - - private bool IsEndOfLine() => _cursorPos == _cursorLimit; - - - private bool IsStartOfBuffer() => _console2.CursorLeft == 0; - - - private bool IsEndOfBuffer() => _console2.CursorLeft == _console2.BufferWidth - 1; - - - private bool IsInAutoCompleteMode() => _completions != null; - - - private void MoveCursorLeft() => MoveCursorLeft(1); - - private void MoveCursorLeft(int count) - { - if (count > _cursorPos) - count = _cursorPos; - - if (count > _console2.CursorLeft) - _console2.SetCursorPosition(_console2.BufferWidth - 1, _console2.CursorTop - 1); - else - _console2.SetCursorPosition(_console2.CursorLeft - 1, _console2.CursorTop); - - _cursorPos -= count; - } - - - private void MoveCursorHome() - { - while (!IsStartOfLine()) - MoveCursorLeft(); - } - - - private string BuildKeyInput() => _keyInfo.Modifiers != ConsoleModifiers.Control && _keyInfo.Modifiers != ConsoleModifiers.Shift ? _keyInfo.Key.ToString() : _keyInfo.Modifiers + _keyInfo.Key.ToString(); - - - private void MoveCursorRight() - { - if (IsEndOfLine()) - return; - - if (IsEndOfBuffer()) - _console2.SetCursorPosition(0, _console2.CursorTop + 1); - else - _console2.SetCursorPosition(_console2.CursorLeft + 1, _console2.CursorTop); - - _cursorPos++; - } - - - private void MoveCursorEnd() - { - while (!IsEndOfLine()) - MoveCursorRight(); - } - - - private void ClearLine() - { - MoveCursorEnd(); - Backspace(_cursorPos); - } - - - private void WriteNewString(string str) - { - ClearLine(); - WriteString(str); - } - - - private void WriteString(string str) - { - foreach (var character in str) - WriteChar(character); - } - - - private void WriteChar() => WriteChar(_keyInfo.KeyChar); - - - private void WriteChar(char c) - { - if (IsEndOfLine()) - { - _text.Append(c); - _console2.Write(c.ToString()); - _cursorPos++; - } - else - { - var left = _console2.CursorLeft; - var top = _console2.CursorTop; - var str = _text.ToString().Substring(_cursorPos); - _text.Insert(_cursorPos, c); - _console2.Write(c + str); - _console2.SetCursorPosition(left, top); - MoveCursorRight(); - } - - _cursorLimit++; - } - - - private void Backspace() => Backspace(1); - - private void Backspace(int count) - { - if (count > _cursorPos) - count = _cursorPos; - - MoveCursorLeft(count); - var index = _cursorPos; - _text.Remove(index, count); - var replacement = _text.ToString().Substring(index); - var left = _console2.CursorLeft; - var top = _console2.CursorTop; - var spaces = new string(' ', count); - _console2.Write($"{replacement}{spaces}"); - _console2.SetCursorPosition(left, top); - _cursorLimit -= count; - } - - - private void Delete() - { - if (IsEndOfLine()) - return; - - var index = _cursorPos; - _text.Remove(index, 1); - var replacement = _text.ToString().Substring(index); - var left = _console2.CursorLeft; - var top = _console2.CursorTop; - _console2.Write($"{replacement} "); - _console2.SetCursorPosition(left, top); - _cursorLimit--; - } - - - private void TransposeChars() - { - // local helper functions - bool AlmostEndOfLine() => _cursorLimit - _cursorPos == 1; - - int IncrementIf(Func expression, int index) => expression() ? index + 1 : index; - - int DecrementIf(Func expression, int index) => expression() ? index - 1 : index; - - if (IsStartOfLine()) - return; - - var firstIdx = DecrementIf(IsEndOfLine, _cursorPos - 1); - var secondIdx = DecrementIf(IsEndOfLine, _cursorPos); - - var secondChar = _text[secondIdx]; - _text[secondIdx] = _text[firstIdx]; - _text[firstIdx] = secondChar; - - var left = IncrementIf(AlmostEndOfLine, _console2.CursorLeft); - var cursorPosition = IncrementIf(AlmostEndOfLine, _cursorPos); - - WriteNewString(_text.ToString()); - - _console2.SetCursorPosition(left, _console2.CursorTop); - _cursorPos = cursorPosition; - - MoveCursorRight(); - } - - - private void StartAutoComplete() - { - Backspace(_cursorPos - _completionStart); - - _completionsIndex = 0; - - WriteString(_completions[_completionsIndex]); - } - - - private void NextAutoComplete() - { - Backspace(_cursorPos - _completionStart); - - _completionsIndex++; - - if (_completionsIndex == _completions.Length) - _completionsIndex = 0; - - WriteString(_completions[_completionsIndex]); - } - - - private void PreviousAutoComplete() - { - Backspace(_cursorPos - _completionStart); - - _completionsIndex--; - - if (_completionsIndex == -1) - _completionsIndex = _completions.Length - 1; - - WriteString(_completions[_completionsIndex]); - } - - - private void PrevHistory() - { - if (_historyIndex > 0) - { - _historyIndex--; - WriteNewString(_history[_historyIndex]); - } - } - - - private void NextHistory() - { - if (_historyIndex < _history.Count) - { - _historyIndex++; - if (_historyIndex == _history.Count) - ClearLine(); - else - WriteNewString(_history[_historyIndex]); - } - } - - - private void ResetAutoComplete() - { - _completions = null; - _completionsIndex = 0; - } - - - public void Handle(ConsoleKeyInfo keyInfo) - { - _keyInfo = keyInfo; - - // If in auto complete mode and Tab wasn't pressed - if (IsInAutoCompleteMode() && _keyInfo.Key != ConsoleKey.Tab) - ResetAutoComplete(); - - _keyActions.TryGetValue(BuildKeyInput(), out var action); - action = action ?? WriteChar; - action.Invoke(); - } - } +using System; +using System.Collections.Generic; +using System.Text; +using ReadLine.Abstractions; + + +namespace ReadLine +{ + public class KeyHandler + { + private readonly IConsole _console2; + private readonly List _history; + private readonly Dictionary _keyActions; + private readonly StringBuilder _text; + private string[] _completions; + private int _completionsIndex; + private int _completionStart; + private int _cursorLimit; + private int _cursorPos; + private int _historyIndex; + private ConsoleKeyInfo _keyInfo; + + public KeyHandler(IConsole console, List history, IAutoCompleteHandler autoCompleteHandler) + { + _console2 = console; + + _history = history ?? new List(); + _historyIndex = _history.Count; + _text = new StringBuilder(); + _keyActions = new Dictionary + { + ["LeftArrow"] = MoveCursorLeft, + ["Home"] = MoveCursorHome, + ["End"] = MoveCursorEnd, + ["ControlA"] = MoveCursorHome, + ["ControlB"] = MoveCursorLeft, + ["ControlC"] = () => Environment.Exit(0), + ["RightArrow"] = MoveCursorRight, + ["ControlF"] = MoveCursorRight, + ["ControlE"] = MoveCursorEnd, + ["Backspace"] = Backspace, + ["Delete"] = Delete, + ["ControlD"] = Delete, + ["ControlH"] = Backspace, + ["ControlL"] = ClearLine, + ["Escape"] = ClearLine, + ["UpArrow"] = PrevHistory, + ["ControlP"] = PrevHistory, + ["DownArrow"] = NextHistory, + ["ControlN"] = NextHistory, + ["ControlU"] = () => { Backspace(_cursorPos); }, + ["ControlK"] = () => + { + var pos = _cursorPos; + MoveCursorEnd(); + Backspace(_cursorPos - pos); + }, + ["ControlW"] = () => + { + while (!IsStartOfLine() && _text[_cursorPos - 1] != ' ') + Backspace(); + }, + ["ControlT"] = TransposeChars, + ["Tab"] = () => + { + if (IsInAutoCompleteMode()) + { + NextAutoComplete(); + } + else + { + if (autoCompleteHandler == null || !IsEndOfLine()) + return; + + var text = _text.ToString(); + + _completionStart = text.LastIndexOfAny(autoCompleteHandler.Separators); + _completionStart = _completionStart == -1 ? 0 : _completionStart + 1; + + _completions = autoCompleteHandler.GetSuggestions(text, _completionStart); + _completions = _completions?.Length == 0 ? null : _completions; + + if (_completions == null) + return; + + StartAutoComplete(); + } + }, + ["ShiftTab"] = () => + { + if (IsInAutoCompleteMode()) + PreviousAutoComplete(); + } + }; + } + + + public string Text => _text.ToString(); + + + private bool IsStartOfLine() => _cursorPos == 0; + + + private bool IsEndOfLine() => _cursorPos == _cursorLimit; + + + private bool IsStartOfBuffer() => _console2.CursorLeft == 0; + + + private bool IsEndOfBuffer() => _console2.CursorLeft == _console2.BufferWidth - 1; + + + private bool IsInAutoCompleteMode() => _completions != null; + + + private void MoveCursorLeft() => MoveCursorLeft(1); + + private void MoveCursorLeft(int count) + { + if (count > _cursorPos) + count = _cursorPos; + + if (count > _console2.CursorLeft) + _console2.SetCursorPosition(_console2.BufferWidth - 1, _console2.CursorTop - 1); + else + _console2.SetCursorPosition(_console2.CursorLeft - 1, _console2.CursorTop); + + _cursorPos -= count; + } + + + private void MoveCursorHome() + { + while (!IsStartOfLine()) + MoveCursorLeft(); + } + + + private string BuildKeyInput() => _keyInfo.Modifiers != ConsoleModifiers.Control && _keyInfo.Modifiers != ConsoleModifiers.Shift ? _keyInfo.Key.ToString() : _keyInfo.Modifiers + _keyInfo.Key.ToString(); + + + private void MoveCursorRight() + { + if (IsEndOfLine()) + return; + + if (IsEndOfBuffer()) + _console2.SetCursorPosition(0, _console2.CursorTop + 1); + else + _console2.SetCursorPosition(_console2.CursorLeft + 1, _console2.CursorTop); + + _cursorPos++; + } + + + private void MoveCursorEnd() + { + while (!IsEndOfLine()) + MoveCursorRight(); + } + + + private void ClearLine() + { + MoveCursorEnd(); + Backspace(_cursorPos); + } + + + private void WriteNewString(string str) + { + ClearLine(); + WriteString(str); + } + + + private void WriteString(string str) + { + foreach (var character in str) + WriteChar(character); + } + + + private void WriteChar() => WriteChar(_keyInfo.KeyChar); + + + private void WriteChar(char c) + { + if (IsEndOfLine()) + { + _text.Append(c); + _console2.Write(c.ToString()); + _cursorPos++; + } + else + { + var left = _console2.CursorLeft; + var top = _console2.CursorTop; + var str = _text.ToString().Substring(_cursorPos); + _text.Insert(_cursorPos, c); + _console2.Write(c + str); + _console2.SetCursorPosition(left, top); + MoveCursorRight(); + } + + _cursorLimit++; + } + + + private void Backspace() => Backspace(1); + + private void Backspace(int count) + { + if (count > _cursorPos) + count = _cursorPos; + + MoveCursorLeft(count); + var index = _cursorPos; + _text.Remove(index, count); + var replacement = _text.ToString().Substring(index); + var left = _console2.CursorLeft; + var top = _console2.CursorTop; + var spaces = new string(' ', count); + _console2.Write($"{replacement}{spaces}"); + _console2.SetCursorPosition(left, top); + _cursorLimit -= count; + } + + + private void Delete() + { + if (IsEndOfLine()) + return; + + var index = _cursorPos; + _text.Remove(index, 1); + var replacement = _text.ToString().Substring(index); + var left = _console2.CursorLeft; + var top = _console2.CursorTop; + _console2.Write($"{replacement} "); + _console2.SetCursorPosition(left, top); + _cursorLimit--; + } + + + private void TransposeChars() + { + // local helper functions + bool AlmostEndOfLine() => _cursorLimit - _cursorPos == 1; + + int IncrementIf(Func expression, int index) => expression() ? index + 1 : index; + + int DecrementIf(Func expression, int index) => expression() ? index - 1 : index; + + if (IsStartOfLine()) + return; + + var firstIdx = DecrementIf(IsEndOfLine, _cursorPos - 1); + var secondIdx = DecrementIf(IsEndOfLine, _cursorPos); + + var secondChar = _text[secondIdx]; + _text[secondIdx] = _text[firstIdx]; + _text[firstIdx] = secondChar; + + var left = IncrementIf(AlmostEndOfLine, _console2.CursorLeft); + var cursorPosition = IncrementIf(AlmostEndOfLine, _cursorPos); + + WriteNewString(_text.ToString()); + + _console2.SetCursorPosition(left, _console2.CursorTop); + _cursorPos = cursorPosition; + + MoveCursorRight(); + } + + + private void StartAutoComplete() + { + Backspace(_cursorPos - _completionStart); + + _completionsIndex = 0; + + WriteString(_completions[_completionsIndex]); + } + + + private void NextAutoComplete() + { + Backspace(_cursorPos - _completionStart); + + _completionsIndex++; + + if (_completionsIndex == _completions.Length) + _completionsIndex = 0; + + WriteString(_completions[_completionsIndex]); + } + + + private void PreviousAutoComplete() + { + Backspace(_cursorPos - _completionStart); + + _completionsIndex--; + + if (_completionsIndex == -1) + _completionsIndex = _completions.Length - 1; + + WriteString(_completions[_completionsIndex]); + } + + + private void PrevHistory() + { + if (_historyIndex > 0) + { + _historyIndex--; + WriteNewString(_history[_historyIndex]); + } + } + + + private void NextHistory() + { + if (_historyIndex < _history.Count) + { + _historyIndex++; + if (_historyIndex == _history.Count) + ClearLine(); + else + WriteNewString(_history[_historyIndex]); + } + } + + + private void ResetAutoComplete() + { + _completions = null; + _completionsIndex = 0; + } + + + public void Handle(ConsoleKeyInfo keyInfo) + { + _keyInfo = keyInfo; + + // If in auto complete mode and Tab wasn't pressed + if (IsInAutoCompleteMode() && _keyInfo.Key != ConsoleKey.Tab) + ResetAutoComplete(); + + _keyActions.TryGetValue(BuildKeyInput(), out var action); + action = action ?? WriteChar; + action.Invoke(); + } + } } \ No newline at end of file diff --git a/src/ReadLine/ReadLine.cs b/ReadLine/ReadLine.cs old mode 100755 new mode 100644 similarity index 61% rename from src/ReadLine/ReadLine.cs rename to ReadLine/ReadLine.cs index 0bb765e..434744a --- a/src/ReadLine/ReadLine.cs +++ b/ReadLine/ReadLine.cs @@ -5,27 +5,29 @@ namespace ReadLine { - public static class ReadLine + public class ReadLine : IReadLine { - private static List _history; + private List _history; + private ReadLine() { + _history = new List(); + } - static ReadLine() => _history = new List(); - + public static ReadLine Instance = new ReadLine(); // Singleton implementation - public static IAutoCompleteHandler AutoCompletionHandler { private get; set; } + public IAutoCompleteHandler AutoCompletionHandler { get; set; } - public static void AddHistory(params string[] text) => _history.AddRange(text); + public void AddHistory(params string[] text) => _history.AddRange(text); - public static List GetHistory() => _history; + public List GetHistory() => _history; - public static void ClearHistory() => _history = new List(); + public void ClearHistory() => _history = new List(); - public static string Read(string prompt = "", string @default = "") + public string Read(string prompt = "", string @default = "") { Console.Write(prompt); var keyHandler = new KeyHandler(new Console2(), _history, AutoCompletionHandler); @@ -40,7 +42,7 @@ public static string Read(string prompt = "", string @default = "") } - public static string ReadPassword(string prompt = "") + public string ReadPassword(string prompt = "") { Console.Write(prompt); var keyHandler = new KeyHandler(new Console2 @@ -53,6 +55,8 @@ public static string ReadPassword(string prompt = "") private static string GetText(KeyHandler keyHandler) { + Console.TreatControlCAsInput = true; + var keyInfo = Console.ReadKey(true); while (keyInfo.Key != ConsoleKey.Enter) { diff --git a/src/ReadLine/ReadLine.csproj b/ReadLine/ReadLine.csproj old mode 100755 new mode 100644 similarity index 98% rename from src/ReadLine/ReadLine.csproj rename to ReadLine/ReadLine.csproj index 88d7801..b23b06a --- a/src/ReadLine/ReadLine.csproj +++ b/ReadLine/ReadLine.csproj @@ -13,7 +13,7 @@ snKey.snk true Updated to support .NET Standard v2.0 / Core 2.2 & 3.0 / Framework v4.5 - v4.8 - 2.0.3 + 2.1.3 A GNU-Readline like library for .NET artifacts MIT diff --git a/src/ReadLine/snKey.snk b/ReadLine/snKey.snk similarity index 100% rename from src/ReadLine/snKey.snk rename to ReadLine/snKey.snk diff --git a/artifacts/ReadLine.2.0.3.nupkg b/artifacts/ReadLine.2.0.3.nupkg deleted file mode 100644 index 2538e1bf5992b42b40741fc7ecc23bab9d3eb5fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41824 zcmZ_VQ*%jSC(5J5pe9=O+(0Jtkc^Pj0twO`8B*r#2ZWbTqnnIdq{z0=-~q4|4d5n?Riv3u1_2g!Z25hWsKr*YjcR1TYL=<75 z7h5c?yG&qwqdLbm;aK|Ad_ zJe%<}y~~zAP6x3vES|m3b}RdJ$7qCrn7|L?Z z?{7K_h#}Nq$;Gho>2o<^fNOtD95e$ljS7?_@*w`JF?xd4)~SpqhZU4P6{HGDIA=K; zYglu`XcK)4e#nvpdML7|f1f>K8YaYha3u*lPlPR+kEjD*wb*%$`abP-$Q1?_EEVPa z%lmYu>{yYo||K zb9OMW&Bm($+~?vO0KUvd`h#KHsts?$jGf&o%kP5FJ+6)u>G;Mu+h~NFXYt!(D?6xf zbAw|LH3`mDPV-PmF3eV;Od=m_M=Phn)hKuHFRZK3mIpHV*M00^Z69Vk_>Pu4!suD^ zRC;29cx1%RhXrN4`F3!_CN9KZTLyCh$3I8CW-Mi`JK-pQ^Hd$4yu=D0We#+`$9Y05 zCz)e4M}I=QW>T72oAbg4cC%AXr~F8%rZ5 zJ5v{S4yOOvH6}JT=UUz#I;ze3M=VF#@`*BLH{`a!Cd*YzBICqAGmBbT?3VbMf+NLD zS_)K2NhT8}Qw~$|mNX$ozI_K`t&w`Iv<~+jBbXQ|bjZZ&LY~y5V`Zc|=g@hPy{bY_ z5Vhg!cQwrq85v13q%UcYao($%-k*zl-sjCrUxP1Y<7pzkFenJ7(9sm=I`ZxcnEiY9 zkdgr~2(-23>~;Ji4XUTd#)B0Y%=U-FaJXzB!h_e=bfCy=d8%Y!)TPy4iJsp!CIc`g z`w6E$yy+JpA``e}8{Lz;^h!XFoFJZ(`)<7A3GI} zz*i_@_R~m{`stbZWCL9E($e%pMlF8T7G%IbLg0@W+ww^BCWWLrYJgC(Y_8S0u zafkC$r4i}|+0ryve}wn*rTH}Lv!_4Ust5TDguL@nx(X_JYlOe@Cwr2UefHN2(5GSf zd{g;ofPAu!ubs3ID0%biyJR>ZMtQ3)c`Kgr*Q5C?j=!Wk$U}YmSb6)=nlQg;_e>s= z95Qv=@@I^SWqsiVx5Blte2mKR@;BIzbgffm*yb{UoA|Y1g$#O{Y`2gWzQP zP-Uc?!a~f)G6Wo%yTKsmVay=>f3RfE3w;2CS5u&k71g%j zt?TGus7|0Wf{6&Nt3Girk#ZGsas8Jfyi%ac@=t5kT0Ei2AG8WXBp6@1`nv?d?{D`9 zw#}J#96JbfCS)p7PF@3jPP&a)B(<+;)g7iwR8gaHt~G_3ijdu)KBb;M07OzVOnCQV z|B`gQ6bzm`QSaMzSkWv*qOfG|H|3oOKfrK5Ij|PPhRdkxD%)_3bUZT1G03j98?&1X z9l;O`vlAI_-8a9Nft$*AQLy|P()VvpKz9|&Z`jumj!Yv4>`)B(#pP9}>3v%Mq)Ht; zwQMtta>qRp8|~|4%Lmn9I$%WFT*8n6A4wvU#^mr1bB|7Xl{N!G8dz(RQEqeM zP4PI34to&;-3hHcb3?W{XJrDk)|6k8z-B~nWFtdX2Uid+bTz(Ib=-cCreK8gcjO4_ z#8V~9-NfxZO0X7>$2_q5H^1DLp5tGD3d|RH-6bl^o|aR8M~K;;%UXc{NKsELruz7^ z<4ugeArdy$5I6A1Ibtdb#_|#V{9{)^=Bi2+61l@|2)->Dl7HzpE@tyNwFMt_(_}&- z^FeBxOii`p4!}#KM&R!c)Eei?ljl-qvN*;Q)+^WND8T-Z6Ate5 zVB&^AkY6YosH?_Wa#9Df2o0-mGO^mW92NE(lz*Z$BE=AW474o*d&HDiF-mp}UaqTh7%Mj4rw_@*RzJ@vH($9~uvo-drQw^I~<%b^!Cn5~^g zmjEyE*Vmd_ZHPtmx5sFNSDeX?5IY(e=>{-usTV&nLW5LnZC%ARj1|e$sH12UYba;n8E#T|@A*D0`cF z0%rv%_;AYyODc8rR7A55vkPD@k-Ds=%$>5!Aa5-M#}z<}Y{eb!HicG&^&1Wii&qT& zb*(ZIhk@{9?1l5*tEskVcECQ#N`P>kul}cIsChXZmZcLLW_1RHT;%iAY2F(c{nXLW z=CVW=T9;;|0NC)NBwvv=?~;oxNVjWAyqP0SW-WvV(l{M67yEF78>_%h{2;2lW?t{b z9pd99 z72&t1)4%*rikcJ`fi~tT<7xcF0p>rIt*+`C^ajW)(R@Yh`nX1eFf3*YOnxGYTFsR8 zaliqlSvQ8*`|dnT@8#2gwMB1;IQDq_WAm3}ic^nuHGRA_dG;v2I;HiBU<+F@WL8(^ zrEGAHenqHVVicJ>dY7iQp>MqY8&0w3r75k1<7>W^CV}L4BM61A8b5ZdvNvfnzC%_S z*uUc_TAn(%yEzEymfjY^b(KmloF%!2|1n7Ah8Idp4K(HtyHh!bEbf`nPauB^f54l? zzF$h%9Gf?Mfs8rE*SWlX*MxK0`ZieXJfaz9uYo6Tfj3+GGzD8WK$c>^i#Q4yK6d|` z^k$=UVU+a@5&cEjxcZNV+D_a!F0Rsvw!^)umP;$%pV3NF!rwYg2>=!BjbpMqPV5}R zra1|rB$#t|KuD_~F9E|hSO6WPm3RkYxh~0!FLygAu@gWsXLZvBaL^=)Vuxyx{;GRi zsJ&n%9>my=rHrcsEJTea6!K{b;58BI^ez$B7tT3g))Yo7JW&NZa0rHLos>|r2o@wl zJ)T>CXpQ>FQGT@wtTAv2ilRgi6>E2)y7k<#3YFW zbLxly&WtbIg|r?afS4EsEtsMmg}~@xpDxz!Urnel>DP2yZsG@EeO|_C1ix-|nwG*x zIZ)gHYGmXK!W~hoCDsK{HO_#rk^v_|pCmxcRo;to8xgV}DiiXyESK9o1$K`emq+OtxbV`>R7O+po&AXTP$`qQ#ravAT9L~^z2)~;D%*cPf^jagNtO2I zRr4@gYks@>=w4l2?n+78l>2-!LcbK#w0odSWnydSf#3mC8}k09>&6q8xW*oL-U^K< zc)#K{{>6}E*6P@(Jdx)r6=at832P}yo=)e5L}%2xRd4*xs(3@g zUsE?Ok@!c8!CUS^XgpLj_!T)jP%2)qT!GXV%y?H)`lVEPAgp-r3SnFbHc!1)d`jR2 zH?;@rG;ATOUaxW^G(q~M)(~;2S8R0&5UO9fHG~R1PrQBX-~ZNt1DqT2m*9nG>La@u zUw%ZNwH^T`egtQG6^VMm@*befhU>+-q{SV-(*g!2a8STUk8Fe{KNhPKAlfoVqBc?)qQz5sWgS*qg7_-K>&18-_JroM$s)4bM_g$t z8|PJdbLb(N?s2j$$TcV6Ab=6)Sm~%#fln}#6%~;(haT(p_=L?Ic=B+3654G-n$_jVU+OQ_UDRMSwF|YRGF++Hryf+~)^z4=Uyv=4Uj&M` zWLeHBQW}gz$B9fYg5c=Sz(d49S%r8vGSHLKg;V?#`I9YD}CiZ#Jnxnado=&aIQh+(@R! z)=OiGzzuF0M?=X5cq{Pm0@I!wuA)H?c4gjvLC}fwtXeZv$g;t%<|U{DVAUXUhiLSA z(c`x?GOlK_?r|=?OaRsggDoFd7fq3>nIlaj6dro@*7#GKoMM-x31F#MqXvGPJGx~J zo3ky`eoGfuzxCSTHWtwILB*Xky$y|rEa8uH{98&i%u*)xgDNyhlgXRgu4t`g<=PUx zi=RW?4zrMRmE0eKqolZRlbW@*Zq5tKmyxkSO*thHI`Q+3 zdnvmu=W!M1Ji?~l(4OFE)_Cn2{T7!sC!$OMQLN2{lgE}-D2qU$G*MIOw9eP4BV&VD z=|G-)$YmsZ=-aRKjPuEuxGXn%&$f&$y_%ZxQ>b+eBgDU1WC+@JAsHQ$<2pFwF}#J6 zJ52LL(y^vgJFKOHgzR(Z8k15sF7zozA0V;gS;2JuNX&8OHghEC`C;zfeZtP`8=vf; z_2>^;iitcIW-FFAnf)Wl+69Ke$8{-z^nS~JvWDxSgsqHbb6IkwL-Kq*34=C~+B9)p zfft8p;nM>}pof$E{J>}JnS3AD-x>#R;mPoK?weG;qfg>^(*Y*^G`hoYi%}U5^(Or; z>ysgk#Z`OTG>vX1;RuWJg!xIP>pxNc$_X4SN!_5t+kG+|Z_~rO4V$B7B35Hgj_S8Hq z8TY}*NJ+R!g$_r|>Dh{Ah7$yFM=CXb@LdtO=@vthR3=^B+jYH7=jj>_XAW7jTLhH~hmE^sep^75Tc z!j73{eTlZqpJ`2jJ~=AB-MPd#`DQ5cIAQdgwYG2OeWoC$e075{5$ef)(gQfc4s=el z)Dmbk$qWZ~VDpGO3SMB8=BKm?Yn)+oah!L%41%CPwuM8jxt&ajXEFR5f@NRsCU?%# z2XMs+-^*D7@z{!stcX+Lwf|tBAMd5!>Bp}Mgf-eDnI92M1@dGY-kmdRaYiz*+-W8* z^&U{~b~#ynyS6%@+uHDaAI#D}sq&hR6GoIv42(%crtACG2cnK#(T<^YRtaw#54LP~ z>{{SH68JriiC!)W-?fRYiz%3 z_QwT2NOPw%;+i-K4*|%HBaGJFpA+7Xs(mjq=UM=jY#S3oaCh)f%-PI^Q%O-!n>wIqimC}3PY;Jb{*gtot|JnUUq`NWIFA`rG1$&8kO^s<3{R?#ZVzf9X!`5BB!Ge7b!*5t+t2^|FieWft8 z&B5%@K;n{04%<#1V86Q#y+QCT4@$aazb3Un(gBC!m$I>eP}Rs2%hiFzTmPw#(|Vnb ze{Zb0n>O%c4>pNOVj#&St0;{iXUiFi+#>Sgf|yZfb#;Som@l?ErbY}ia8)$v6{`u~ zF#IJLp20A=dawX~$>2(Edyfstpc#VBtAEY?@-+VtgEQ>MC=F>5XLo$?^&&QCd}FCEccy>&mvv`zE0*kGl%9qwX!i?5G@py|ufc z#!L14FhRC!&4!)y_k*~gCTpe;x_7e+4*A?#iO9)hs&4<-r-?b<+!Hmz*J^tyI7H`ztMK^ugX1ZMYs5Ge`IvmeDOTT1gb?bV`>J9d? z^Ijr)+Fhmw%ECU(+^(og(WWn{)Tyl#F2Zo4znzDXR3Y{f@pDPmt;ZY@f1aRq*L3rf z-R<|#p&an(3eZkGYm(=9EgK8vqH>jMvGZ*HNbh zPF|nvu~-Dd5=ZjVrRJ1Vf%I?MQRZkbAeQhqEjJqhcF-=F0OEA78NiyO-D^Jhk@ar5 zad|>h*0N}Gg{Wj|%5#HnwYozb%hJJ?IZ3~l8G{Q7E6N|=;Eks`Dhlsk60Dha2 zACZfF{*S!FvEXf#}xR4TK z@fB=Rau$Ch{dRi=2c}F@s3UXi3kA{(Z_j7}Mj>EqLJP~gdJM%|Ynna2alDwn$<}OK zPW~kD$4Nq=(D9|;eg~0_>vt=>CC|0nM5 zyay83{x|Mo|8Ka<$?|{cuBQiqdP1#WX$ME5@&9L$5mBz4mqJ0wgqN%pVO+iBK z^0zoi2Foi8Enx07>fb(+-b8w0ayhUpditsUmK7fen5|HhhG0le@)dH3{sfAE6`%10 zlfalBg#d@DPStxaGcB@+Ui~xTwTF4{9%~Jq^t}`7qNdE58EJZ+=F#p<4 zOrG--Y?Ti;2r`DR?Sk0s_L5qRJVo|Qw5`HwJ@7k!s;nk(CLOndt>QZ==E)j9qJs9G zS#i_+*73>m5;8M2&DF%x(mQ?SBcui)Z7MHFKMZ@{D^QV~p(BH@Lxm+?C9Q$SVReJIdwFw)850&d|+~ z^}1(B$Oa^Btdz}gY>+kn>Ik}B22%^+r<4tw<=>F%PUd2|2H~2rnF%VlNGELf>ptJ* zBNql?{Rknb%*5bYS@@-|HKI@RbP)2! zAva>LDf(&G$3(Y3oVv{?7yZiES4*?MMf2nu^5&ho?e7OGpaknDLGsy;_Lc|x5h?m{ znYx`OJJHh_-(v;)!MktmtmRJ9qkrWM_Z$Y%(-NPD^71v=G~9Ey=!e3uEulPrEUv`W zS&C^DY0YDPf4M0BsGXX{2^oepan;LK|H0 zFSpYTgYLpsmvCbF{rDQhtRA$cYJ?nCzp&-Cl6cOL%=MEf>76{xb&9~&>C})XI@J0& z^}xuELrDO=CGRb#2jbma6!d7NnFe$?qkrMa@aK`f97EYFfi-z6|y z^KU;P&>m}!E~!85hlRa1w}?e^-(I{?oRBO(faygeo&3Gz*STagrWUijvWKc4v)v5h zQcJ(P$uAQ5{9lhE)g8zft?)<1(`(Qv-EjJTRQXJD!B+i#hB2iYl_4ZNNgRLvEVH$t zP4CO9hhmh0Leg${%+Sq4y5UQ-r85scFgLIi^zsEvUsPSvEx`TrU3<0jy#M$vbZH4! zL)qe&@4B$i?xusemo;qpWc7$e^Tb5E;5l1sdXujUlQh$0A&B6t)=7YyRyn%>69e0;CNMd@Sq}?nEqq2vsv|>$6|xq%99>{;)Z@oM1ZtV zx`wARLhe^w7R>s=hCiHm-lImC|5=9$ zM0o!!D1=B|f75VN>BFoULc{N~f4a+1VZTE1Pj|_h|4Vmum9;QS9vnagXVG>#4%^Tg znm$5RXc^O{9ow#qt9SFa}ET8gB# z>-$U6ts(%Ww12B9)+Jgl=oDmLU5G-&MfP}bP=p%i4&%|uRzon z*|hw-iC1FJFdp~~CM~UDJnH@deg|oDDK+lqCmqgl=nBZB6Gsh>`pH0!3+GZ;hj_gr z#%YCx+WZyNLz4H!!l6+rC0*<^CwK`b98IDohdvY}7zZ42NOtWtE&1VkgBGkk8s=j) ziGD^e49y+|)rml2$mfhSOnB=w?32WXz%YD=wNwLK`De}7X~W>TYSQK3wwA7y^Qx(( zphwoRTspCp@}buO?57X)z|k6dd-O|)Y#&oBroEh|XYA}PbD$~gZHR?aEorq115~X2 zZ4!L~eh#{Iy}@x|8HKXqhWw?x*OXujJj-t~Q=*^VIOo|^8jL>=$mv}|DIZ$YFp!K&@w<}3-VKx*Vp#s~no9;NTh zXdYm)b%=rCRi_$DZIDlkDdL$!B^Irq+mQ6N!|O9B3TqMb#bRi~%%;9L9b5$A{ii9r z-T|RG&`>YOox`21L6You#P7S({~(-6OkVODa41va%ftztyizE`52n=ow!8ch#_pRu znOB^wOQ?5OP&4k$>6_~~#h)y-T|4^Ahw22##2GT@a83h-5PU~3YZFn5nUT#G&g=!w z?F*YDzjpZ}30yCQgs~MWd=%SZdPh*dZ`EMK9-zSH)hOvtu^wufE6{U}FV?9gd#C;p z1}x(!>^bntyL4B9e5?*AcY)=>ze1D?l2H(Q$-hi=;N@3)@$MvP15vKmOO@)r)oP|6 z=te1UUsAOkH^ubp%1pSf>LygzFOdktHw^1kTP&E6(8jHH0oV$Ps<$3fN_Obp`9{o$ zVB7ZJ19m)+WWpKS%aP7G^M5PnPwyN{Q90GOtx;H6eajOl?=}X zzz`m}4TT+JboR9KKwy>jezj;8C>X;VWk?%FE`DGQF}4ju;jk$&{iVAYSjWce4^2^m z`pd$B@{* zFkgyn;-anFg*9mL)FnKW)J=q|FQNtOJM&a;PgQ6XXwb+)4!y&Qea=?sL=mhrZw*l* zYvHV%xuYc;zx-Ykrc`u5$W7^gbLzC zQid?aQtfm%HbR5;JRoW*OR2l_)-+jlD3h~5U(;a8WnW5X#;K~jz4&U#z54tl^|Od8 z-_RwbEskX`H^j7PmmdOfU=?H5oSD)tDA*p4qf?3(ak}xX@rvdiYJa_UYw)JU;Jw_7 zYO%8E7AKW~=(|F* z6@gqM6)dvFX$4|Pq==^+(qTU0#3~U)rc>!!aZP>d(}~4~)c{&Z1DIpM);yZ74hd%e z_Yi`Xr2O&?b zfB2Htwn@dOfm|`TGIhs2cPrmRej-@IrVHiUnkvQ&wX{3>{&+?6q#pe!x1A)aQbcZS zLXAU1t3s?2)04(DSNoT{CqGa8CGnECcv{+C>V@*1viQ|kyeA)x&~$3or$Afu9M1pt zQfxK&C>CN;+LXT}s*Xs6b^!CA?Oy$}U3#%qiT|W4nEI+EsIMsXWrX-=yt6}mBsz+UkrP`WlnKC@~r;*9-AX-@b+9WH*@#kFIr6Y&c$ z*)-1B-gzwo0LayNgV^+NC!Zky<7PgqR?8uf#9r}PqhZBwxe7lRT9ssGKjcP_?+drV z#zu+7F0RId!0pXCy07;-^OMw8(%i@qT{>u>S%yvEgabTVbSQu={wCds6@8L8wuG{t z!*!O|@K+rYlulmYDNCGdN0nvLd7)~U80Tt#Gbj}{yhdE9vD>OdmkgVkbM-XAxV&Pf zTbylKw08-il=@@=zi!x*{tfXBkWQH>*-_R&?}I zLIoXjvzD|q8i_RBgjUqT6Knq6`+PdFr>2Rk4WcJB(~2*>w>%j)(=D zLCK*cnM365)=rsL(le0TyJ%Zp6EK%syJ=ht#n#t6%5QG{g5xsG!yEJ+3VJ_q1a{Oc za7cKKCWY~YY=laf?FNu^up5D+a8QonZ&Db^stzW<Iwv;F0P!lP&E% zOE$3Yv*}>uM0*Yk(4}N672laMWM;{c9%$u39Vgd)$MQmFV+P>j=fpp}{2Bn8`(td> zS3hvgl_X=1Z5-^kDID4QD|gQ++5djq^+eceogcBN6^|Rh21b$IE;0r$W-2&i$b49= z>2fLVeu9ug)*{HIyvvfka`K zN})VoX$x$s1~OY@9uS9j{U<_8S!xB8KJAYU@hV`Lp+e|evpMKdFWA%tWVRSQH`(zT zYLg9ucHwa&L~Y=>@}T!YSFLSVUU=c?v+u|yMtqWu9`3CJ(rjVo`* z(7C8YvP<~Ky9<4l`@(f=*oh?vuDr9d<;isv`6mtZbnWEEagih(5SWw+B%P4ZsZ5VR z+1~HpYefgBGi$~|MZ_RpBk-A<;t9^UFcOg<5OmqVmKot|M2cuaYhJ_YepD71Ku+?0 z8=Vg)6tjrfnL99Ou?aS5LmQ)`V9!U3bRb&jv#!@%S}>3iMk)`O6C=GPpbPX$fne9I z!1@2--4G+6i*{pZChgDu$)l;cf4plC{Q?P&HaGydQ2hSa-2)R@@M_()V;t>s&Pvs{ z(BI*+UOlh9{P-bKpjy z-7Ul2lr)KoY}NLbP{Y!w)WyC+Tb`T1Az@YE^m5?_E%o+}LIE@r$&VvJx+9#4U7Q1a z@V;#%c4&p-4H+ggOU4Ag*OBfG_oiWA!`F_FI+8g}lJIdh4$I!>#b)`?;AIr95p?Yz zzvZ%#_uY)-ek81yR8Mv}>9{)iniveXPh;LO|&Autlre>0>JNF>Jc0*#AKnXg@Fi=;xNd7pC;SzY^xxDdc>K zc%=X0I&MvT>TR;Z#3(4xUGp3QF7a4r<^7{ewL+!lyJ&qX6 z(tvK^OINj-9cM_<5 z`QbhbXt~$O!hE zC6LPi-sAH*GbCg<`sA%GY&08^weEGV17o9{D>r7ZcWs59{5F`3PvY=<>e%d$oL9C4 z7;pIN=c2Ag{=6oR7HE)CY<^R4+$ug&K|i5(=_8FB6m^C7JE8hGnXQM(BYMeN+1X2% z5 zQKn(=@5!HB2zuE}!IUtFvbe0o+0M%otOM*N2WC*7IF^ z{XrZye&o(UgV7dLpN1D`-S<121Hl!~nXW)Z-^{Iv&S$2@7I0_H?n{xkZP&HAGWhCK zkQYDte!*q95^AAdXQ~wpD|s(^dIGZkZWKWHGy3bSuXUm~fZp7}&+TH9T(moEc=_}O z{Q^f5|A+s)Mt|Jv(;t@D46@kOt&upwe1_v6#|fSPWxRI(ZM>tW?Joaiyl!8{o5uOx zhWPw>G=2TX^nV&JFq5+P|I2u}SpP5M_5LzmSE1YG41lbbrTX-UTjw7N@9JUFQMb2m zj`W%h6!a^x6g@`Rp3QhNL27(s6E()ejt()a{ph$beAq7j8)C8B&| zXDI&ekd+ue4DB;2wM~W+?>*Jl*in=seyo2N7u$8Txz%=*>wWQWFmDc0--3e!DSvA7 zK;0%mndbD^J3{ai9VdqE3!>Q4yN+kSI>#JHO2yA{JcFfTAylB8wd6x5-P03Nz>ZKq)id-to6n5!`q993 zv?poM!StfXZ6s_*)K7vazM3S6Y0jnus&#&KJN%D0KC>}JIBicuX?34m9ryZ-xJwLE zVt3fyvij)=-hf2Xwjn~%b9@2SbG$dqSO(BwU4rlMR)KS0$Q!E)0wI#5q(1Y7yiNa* zS3&!{Q22_yx|BYzupbGXOd5epR5hhiRm0Y)ZY!FL70@ zrkK-xtc<$Y#zn8LO;a%B3wftxC$%M11w*{mG1L3!H-lx%1e&@tnNy#4g4j3QM#9`fNC2gHqrpA*%K zmyu#o9lJ9|HRXK!ZARTpw82a+c}z8uI>1wf#=oW;foIH(DH@p0!pGV%rU7?>XjKfh z6^kw%pynEs`1N>+bEiltCz)Lko;lN;m#G4I^b|}B9+AISF`rnkG7fJgsKV1#ZPpX| z7L2?wRnAo4&Z}>!U>J~|2vkmPr81aaB#7~oOzL#%y29&=ZbNAzs;Lo%5Zia2)t+MI znS)_}UI~`pJ_Lff?`GfeyynxQAYr(Hy)?*|Qxae-T10lK;3RTs8e7ZxCeht0)cAP* zbW|@8PQga@(#SDyQBI756|+Gm!$ybe1b;f4dhV7*ti*|!(rG;TXfg8~;%+h4@*?v- z@p&i@fX$rRW6r5H`chu7tZu1j%`fG}zqQtM=l&BZYUT%jD;F}_zA@-X6Tn4txKc@@ zt^tL6>Dn9kG88P796<&10PC`Y51c`fnTo2|-e#>;X3&4Mxg;0HJKeO)+d z+d~s2BP^&LsY99nCk=D*+BEzFwk|VovyXqlsV~;~quM)itnka@C(8@+>)le_t}G9i zV$C)3grTut^bZliwBye3gopeYBKq}Yh-tl~$2xO!(mXlMUia!uRb_2`y)}{o+uY<} znwCL1Cx-i|xJ5*#d&}HNhn$wMO*jlr_HL*4WNfU2MXhr_@YJ*k*>p4QVl4u=#!DyE zZ*X#9DB``b0HV3f)iHJBc-13Cr*$i98Q)u^dfh=4f|@<>HA(niwvn@i)UIKXS38H? zTO8BL2_=YJ$v+$`d_u>^?Y`C6wA7tINjmRa>b*MXm5_2ZC1yuOmDF2QMNItQ(fom* zt69&9VacG{it&SiO-r?;sU*7N*e%=T_<-U2?sJSD_*mpU*Fr)*)WU-ET}!}}ImaO? zb(x@RJy(LeR$YrEPwqzF0w%I=YkMmZD+-bAMxWbixs1Ya!EoDs64n9{%-r1!bBRqOR zTeIyiJ)NdT*>F`4>S}CaYLLN`7f6|*+V*C`aqZqMjs%b8Cv@HGa#!2-ZmbNwyJSp7 z!QEw&sx~Nbep?OI+y#4+)&i}$Mwqp3!jAvY@Rvy3247`L=q~RGy(^N}Eq$~U_aDE{ z?LAdVe+@O1ZV%5!d=|)TVdBC z;k;o0qDNeq8*u)C4_Q~r8UjEW7}~ZaiR}BcTAY2mAPY667m*0BZyB~9`nFsFsb5paQj>jB;kU^<10i1zNJ&8nQhXP)(G{4CA{bCWYh5 z;Z0;RYAAU*gt$VJ)|b}xhgX9xZJ>ww1?23PLU``=3}HC!Hl}3D0+$79bm$hW2|wy_ z>NRF@$V^!D5f~q83LHdMv zGxYf%5ASR7KS^}*N7Ly-qaq8C#E@zAA3rCicjGnwl|@E`f~mfr5u+_|LnbsFjRBJ> zI!V?+79i5XOi#o&m=%i~OR2-Kd;HE*Y(xwf)xVbkHhs@h4(N~ zR?sHN@O({)0LPWvc3a0W4njqZ4iqRasbMyfrnX?dfdCfduHIvLoqTm%<)M{YG+(v< zs(6zta#_AAUPj^Up81HH8Mr1*+AD9(!$Pf@?b@R|bv4;5!(!I#>ytqy032(ab1lZL zd!2w3Scsa)yHAggB4xm-HrPUDFf@th30kp;MpP3TZ@Qh?>ffe3psGAFn*wuJ)T>~0 z6IAz@Ym{Y%)K(CkC;C!l#%6dE`YBUo*7qB+6VB)@_*KDTlD%*IkccnJ#c>u%(s_gF zt%y~<>{cFeE?|DWH%fix^Z4=3J$|VN_CqhI_XLZT&Hr&;%0&lsAB9)6)vL~zX>OyQ z7eaz}u5|rW(s#id{RGBdxvTOw)`$1-JGp%q=^hcqYGukUh;t_hOZi#}UYu_)@v?U? z&XNmI#g$-)^fGvhcnm5qP=Oag>MSMhE!>B-LTP)g?)DPx5Eo+Ya73c3V3}ycuf`m+ zTmw$UYX!tWM(zNYaP7EnzF3Lz-!Bp&a(+1;RO)=vE_s_^pDL$tucZ?id*uSv#RYm@ zOXc#Rmz+=}ckuYzgh2BG?F~Bhg99*9@F;M}#QLO_6QJU)-nx83{1AtpA>X-YvB8%} zd{w;oX1Pwy6Z9~@y-1`S!#HCd!f&8isXt|Xg3MC#yOV3g{2cnx4sq&O%-RXtMJdMD zZ90Mzg(=MkY!5Z((lcUVw2rsyi>5C+Vhp6-Togn;!M&CWU!OFOY8rZc#Pi}M4~o+v z>=f$M>E_^Joi%P_s~8+TuLwSMbBS&mI2ceQJ)c^xY4c^>Y1O8Zlx$a-`;!G!h&#t6 zuA4o)KV3}F;m@egsV*Xee*`K~5&nyKUxsD62dK6{`5J)x^+?B;3g%@BR4o4@UJW~_ zC`gz4bY~aW7Z+F2xRePEH{P9W{zcfe^Cs)E2}K;4Lo3J?*X|duR-YN7@zRNE=5tD0 zD$|($85u5P#o?BbldP6D`ZVfYZR%C zjXi0F6?ixY8?IF{ zJGXdNLx(jK)s!ng!8b!!*H4h^j3>8(n|Xm%wuQ&Um8eWy4m)}#IY=yn9!B5}yNp5{ z?{4IB%@9032q_4k1$X_iW*J_i?~wm;-i#Ys_GlEsKjz$jm{-rI z1NS)-(-jQq4(fzvx^%!IAU)W7e`SPGbveM}C08n9{>~;&a0>jGdM+N8l`pM|#iReVr@e<2s%f_XhhRm-YVLr%EgphLEPic53hphr73#RHy$b5g zzb6-m@Wa{jwJKsXno0as-b_BSKWiX>!`9SbfxnlPk)cs6<@QEfLU$;st#iIu}mO+sb2g||94Fo7aZwU zT&xYY%@jeIBk8<<4KLDmdD~aRtMk?H*5u;jXk0*JqLXK~9NzkW)wC~0PNdqyekGWrek2ehN*~jq{dYUM?Or{BbH0R}= z`d*T$`+eqIdh9U7y}vdzi-`eVx13%x*LLPw9^Uhp-c>)DrgVLeBad_9Xtav;<~%?V zC$$Ck?`cJA}2G`dcWa?z37)Bg# zhRzwBu;bhCCbhgNvG7Q=`+qpQtEj3Tw(s{K0@6~Vq_nhjcT0zKNOyNjcS|=&3rKf& zcXxMpzjLAgJDz9nJ>IboU~t6gTJt-8^K;o;L}i`345hyoTd#NVKaZO18XBHw~5w} z94m(Qz%_iMik#h{o>cS9a|;#3B+`=ev`1uEDwVLyfo|;5;X)QPC3BL9pg-L#ZGV`3 zm4hi)(6j=Z_hJ_7G@f0GF8EBA1$$q=C4-s%l*Pe7b%#OMiCb|=p-sEqO6a|;KQr}E zk-5!1T=nCQ|7G)+ykSOnD}&adT$^SWwG}7VT)frD!;7D?-Y^tYe;cnh(0J`zUjdEx z^88QZZ325~ycs(2UtIq-UNHX8UKJQuT19wQE48#ka09UVhkyQ*{GXIZK3a6vk~UFE98 zGUu#PrfSGDI>3klx}W9h@X}pxu6Ma9fL7lT*Debs zVd5%+yZ@eOwyO+3%x)GX)-)@U=0E^9RAsCqYd6D1*EFPc1)HY~#^>!jCTLw|d{X@7 zGM=7NEm4tIK9u#MOr{_Eg%Q7ra?S8Gy^V^gF3=bjHzD#p(46J2I?TUz|1;v%Xq?Xa zP8>R~s-)`d zN&JT@gRxazwuO4qcd1ofgN9DE9z}&Z7I-b`KU?6A-A+(h8;9HWEb}Lz-twlyEZML} z`kdPQ&?27J(_%*J06Tj7FwF(SQj&E{Aaker=^T<9kEhXvXNNP3lB1VSwjNmV4xflV z{aNu|yI3-qr1ogvwy`;AAZs~924%_2m!huB`7xdOByIJXbwA6@iz~xuQP9Be1`S2; zQ!|~freq#$Q*+<=hVm-?Cn<>9R(2F42wJ@Jru%)q7=Lx>LMKC&^6 z&H$s#N`8ih{T!oC>p&(LcGGYy? zUg)Gh_?7~)xh%ff9Ql?icxRdT2EFs)hQQSz(hB&yvh!j7wTCF}bFtu!riQ?Dj=rbM+VysTSWSu19#iKo~@tSgQ`4u)NYTU-woLsoQl9yhg8cKFENV@fRBiT(Bt z^N-O`nLRj}Xg;|P-wzlK{MOEkt+MLnu>>XS1`;5np}$9ru{g7U39C3& zh?npM{YoEMV)F1BG4<}o&&Kum;gqR)QTkc*t{-wf^gRWKMSN6GLEE>5bgW_v-{YRw z{P8@H$KGrXc%LlUheXrLkqTUSHMM{ZZ~uR6c%48S-U<3zy5WsJML%={1X%gn({$)b zCwna7+m{WmHL&5WY%y>cy8db`-6>MBo%r>-nX#X-s|j*^ENND5yHprbe8d(Pde;@5 zJ?3$1{{f#?pOJ1%IZ3m>jz5wSjqY4EUXxsWst77f417V9cG&nQ$F4Oz#-MQ_Y~2}Z z$gi!0L8A>%h4N+Ha0h~nHdC>!jc=d$rthOGmQ^pfSzqlgUvKYlZ;WcT2T^P;u+(;O)A|qI(n{Xm zs%4%N@XbB))i+zpp>UX}FSQq^oVrr$fe%+2D+roBI+;QHRyoO{E&-ybRgu8E^2jdda&H$=;y6`_uEEyc?;2W<>Tk@5*Oa)B<@|;Rld+ z2c_5U{^s3@zj>G0`(JrC^1PRQa7H!jqG*%l?W@%@YkQ~sr91JTq1Tn0Ssat_puGEC zzZMh7yO)vnY)SisIGHmagF@vQ$c=ST?|V6~_s(d=qS3nzf<0w1-hfuTiolAu^4}}o z3Y9?9cfg7_LmF7|=CAzMiWlx>#T#62;%^O`=i%|hCB1c3Ky|UUFh93rudu!MLNvsz zs)2}x!aqdArKXIW@q+H(LbA8|S2k}{!jW!iJy!u52 zQD1(_#n8{~L!0`yStKf}ymru|L#$pgd|x%%_zVoSJzTybXJvdf`(>uE9DY?9>vA(F zTbb+aLK@pAb^>qLNpNYNlgSwU%?W?m=`mXMyI$?W3{HK`KXtduP}P=y-tUU)rS4Kv zcP18srFNcu89*@6R%TB~wG~-=^HO&iK}18$4K6?;xj{7AF6n59W+0o?$xX%IQ;U_9 zLMymu{`6VOUXEbmp=zEkYuv#)S{7#GIbnYx8t_3xgYOH`kP9LjsIui=hz1SwmOn&8 z!9PU9B@lP%fwML-#WY>JgZ187{}XrZfw;^4Ipu4> zd6duvb&R2(i+cYY{H@(n-6r)rNM(Vf-#KlJERA+_8FWhhOLySO zQ%tKzrkgJ#UPxfXOFjz#Tfm6-6rO_$G~#`?t2cKpk~R(y4K>Ox2)l51`y$*!0MQ`$ zLNr`H^8Q0K%=&zd)IBB@zuyP?iZrr%Vp53v&D?b9uU#sd>v(Mmhh|XSb?4{ zb)tHGudrgr65$|Xx}QzH#*iW_hPtj-c*hkZMX#b?kUJ7YH0Z10;e>5P`s|=%Q1Jpp zg9gROBS17v*BZu2nt9lcqJxNrw}w9VX7;1qlV3nY1Go%~+GeH#g|hd-P81s*4b(`ZrI8L(KiuM*?@0F&2aJUTJ9Ajz>9D`HY?jdxi+REdoRX1M1!H zQ=4T;f$UejxwJ(7D;yYyjM~=dKI#)XK0nC~tz?32A>>={)h@tyf2%<(f3rn>sCSny z?)28|=#R6?-v79fDVz->Aok(0j3|>?yGrRW6CW?*lG>Svcw#HFow8Q>qmei#35}-) zM$suw^uAUfKs3bshBvp8!OGk`DUDSFh=!hSfN0=ha0VaUf&4=>zyd@AFzan%3pc!A zw2U*jsI)}NDnC*9cu^BfDWq5Q%FTCF27_~WM_m3-+|5OKOpr{N`<$miCdX+a-PAZN zoQ$+5plAd+M}&UkMrk8SWq2}Wb4Nizd}9K{U90_qojVOviwI(HuSMMnuIk z=VC?rMkpibDNO}-nX~pi`;cXW3ay{u>tGx(mv_iNk&NX;(putcV4|9gCM;8IU!`i_ zlCGLxl5Z?zrRm*b{dQMsMA)C4!vT$Wou@20UFGgE=T5{fwLl|YuCON;V8k2o^!~O) zWVj{xB;Zfn#k8KwUM9?)`V_6ON6i=s!s;S z&vV@>7C%<6igrHjvhnF?5i63~mxe$c0_me!mtxGPB|M5qjW=SES3G!Q>Yqaxx{CZG zpWsnWm^LLvM|3{taCBVy*DO&0E8arTiucnvd%QdUgqxZ{9h$QhmH#(*>h|b+IZNh$ z2@MMWEi~-JX(e-K;R)Y)9mD>V5>X^;-BaBjmSDSP$PRyzZ2%G)V*d&a za65a9+dF$FJA2=k{t68nqli1DV_`9L?B5t73(<9%9rv(SGx1GaN%YLU{|F85J0#fv zp;da*Le{divI`=WPs3cElyt9&Gk8EAhA@OL+h21Wet;& zzHp=dce#Q0mQZ83a^m`#x9z7FL{&NAs@>vmr&_=7(_322GR;z}*s*-eqEf@M zJS+Wvsl;S%pgs`|5*nNbOA~rU$B(Lt`f*gW(E3r54m=yHoH&dISu_Z(h?0A-5erk> zXU$UM`@a=_|AwMIxbM3j;-GgbsB21+L=UWZx12&K80=UPc<(_g-n3B+>(Q7g+H| zQZXEauB+9Vvb%%oF8ygmu9hQ7ii9LkcS*XV@^z;`E8Ybo{p)TydJ=2{Hd9HRx4Z)b z_QT@h@c_}_n=t=hL_>(uAEH71ebNUTfzUS1JkAL0Vae7_@j!ON9MaOn;F%pq^3Dfv z>^No^MIW4RsXa3}{3JXW$5#!WTR!#AMz6F<4=R(1Y!(K~`ZpMTM|I47{g5*W6`;y) zwC>4#t+4D@>f$A?#pxK$=W0WV^yOy0upS`TGRN__g5x6m{ zq?X5H+jT4{L@MVLUW6oh&2GS~G2RGIibTA7QH@2cj}0-E4og_LTu#(Kg;?znZ7MG~ zmhs4%)@1v@7EFg+sD7fia#MkiB?%EaH7#$DlTqn)x0ECi?SOTm!Z&G~fq@m=mOxlW z+<>(}$9GpDjS%ZCa5aGn^m2 z4=%6$CqBQHAm9fX4XRuJ%VB52Um6Y6Afo|YUP0852mQwihcREA7RYEQ`Uzq(OI}8N*s2mkY9e;MuSTb;5P0dk>OkKmo3jS>-B$2__1$Qi z>`kEWvI2cqDUwgD#v@=#GH2ym+3)4mixRF7zn-e zeAfJf@2vvC?HdMJ{xeyR!$yqb^w3yoU#c2)_%N+AgzA ziPo7bm8@epkxtgE+;8hF=TH}A>oCC6=#h_Iz1 zVdtU__`gy^f+IP0|4;~Nk)^QeeJr7)UiSGkYn06+a6aoETyBa^KcJ47)?3NRCH(SW%PivB4Eb5_4qR51b!p-;hE2E{&O7q-BCA^Mm47!+ejT#`f+#Wfp?K~*ck+eLzF~T z*N^VDHQLMrIOM2!?oyh?YLZ%vK|1gA^7CsFQJkA zUO;M?2sitmh4&w+;cwvut$5Qcp2V=uo`*HpZt?zIcp(6WcbFIgei2l7>A=8n|1CA> zSXk?6Sz6Lj|F1ExE%v5e^FL!=srj_DU9dqFV-jc4A6XUDmd}6&pvMRz!DMN{PgwlA^9l^i;x^8%x{>~Ma3XRe!X-* zcob%z9q}ai+%x0SeC*JCzj(X^{LmIII^9seq~2^XFexv`srJWI?h#*9Nfq|GNb}v!$|;;dSzDy$QR1l-=&sy4Hz2bd&Cs#NYS)>|JkzV zpL(MrbiDtYPK~k>oB@C2wS@=Xi^fa24QRYjJuxTgD|qf;BPB)EQJ)@%V`jbZATN)g zGOm;9nxl!8ewaePza!L+avR}lhd}6X!^M_JA{|%44XklzgsDH5#}1tf8I<3F0C-|TuFjXOTa(%Mc3OTN#C1G2_`||b(a!< zPxpo}b{}+rf++5bqyytNJWHUn=2I9F>G+DJQYi#zyat9$dbbS!sqwZLdxt*eY$_MM zk71ALDJ>AO@>VCl$-aHq^wLZn)@=O#;0Jke{Pv;D)!h}msl2788rI#8>sh0p0+tnHf&8#k`#@h4F_B|`%aHxUxAmNvu{W1?adJ;N-zYe*FW2f2(0CJ7 zaPoZSC#N-IolF0J8D9Q;Y!Bz)szG%ELk1E0Vdz&DQmjYv- z3eb47{?T~P3s|jjZvU3vA?Z<{eL1KBqB%h0{na0-4QRY=pwfFR0cgBciRrF{uzAP} z$Pd9;;7A4P(_6d_YrjOOg)ZGa-sl%v)qcTVeN%Opgh4g4BybNbd99N-0*2UygBM(- z!_rqV{jw!*6b=zOTYdShEHk7huxn+b|_c6=3DgBB3kC(&wZqU&G{0PFj>CEHSJXrOXw|mFF+;u6NRa!AkVR3f1$z zVPDEqNuP6gUemVqV502Nw>X^0u(5i_!xCiihQC<6LFjS)308EW9xeWtv$T@;|L(lp z4xr9!$J7RN-UE%kSE(kGzk=rO%H|MZ%^+n_%xeXYNT${5PYl&RDyC{F3hXQ}UT~#X z0G*e%$K(3N3%txk>dkHxE^qrz`uL`b5nw?)*QUFA2yY=+t| zDBhWY$@QD6qGh?@(_oOS&1WP$~%C$m@(c4pt z1?MA;;#!E6o|P_D%3v_zA!x_jpKmBX(Swdndc9ECyG6+ga1HMuvWwCF?s#7p06Si% z=B~nslUk!}6lEInBUS!ly08zjU2>8WE=0jMz>fE=QyTh7aGguoHn8K>1MPSZUbu#o z{Z1DPldSnaJKhQxY9xa)%wr_Yt$WS4%=Kl-5)CLLw?Xh4Z4~+I7!A#7IdQ}bGy>5s z=ti-|pRHVRXnqUW+b$^uL-J#AQUzX3AUYe2m0#7W2gsmPou?;y8*XE_T4#_`XlZ?B zC~ayi2pAnHU{YW%#N)kJ5#xN&&mS9aZA2Bz7IgHh(~j&sk`%NdX&qZ|-wu`1f3-*F zqN8|_NFBID*@@}79w$7Xxj#2mv(#0JSav4$L!IE^E3V~cLm`mYvuii#r^%B=~*pG{I_-t0YB>^&Th)8gi zXwxeb@`aEivnZID7V@yE>lK+pShbX*g%Wvp`K%e+?*uV6;>A1_=njF?D_@NuIm{cv zE~4kKMD|02qh2qMFA3Fk-5`uj+hvB+1KXX(pxdhBYuSiH~2d$O1O!I_wlP}j6`R?%o|Rli0-gK%GZ zD|0aG+kRv~w5ziev3^(`}zoDs03QmiufiU6}OEWH{GcWwxdRP8I06-319LC1+U9DoIQV{?$Or1a|YC32XPJf zXzIHRHAFkh@L*?TDqm<7x`bb?Wu`;pJAl@({Wdg}|JsGvjX?u3l4_MQb5v0uIaC7) z$wf#LGMu&!67UOXV#O>D;@+ zCbhzJjV47d!u9rBDlck@Htz_6$~OSw@R7>DQk?noq3+zUEzLN;__{dWT9Xuhkr$kr z)MqNIU1m!Xi*0A(@ubKq9k=`v2x7di)!I+g?b-X&^iJELixo=A!~PrIX{^njkqopdQ(%H|A65V^B3K&bYX@_;hSyKqAgc1^o8 z!+s<7^P=Yx#6Rfh6jM>#g1gS**F@9DeYP^B0N%#dwxDp6=bRy!)CV zTbPR#wId(o8eFL(sn+cktoY-&7E<5ruTdch8Q*g9MBGFepETUV-8r{z>DF1sj1QrH zdXT0FI%m1Vjg@m{J{O?4MX;Wq`)Qa2Gd{q zZ)kAIMR1oOiz1jQ(9bkBxNmn>o<{Y@V@Fq4Q+?=DLelmmyKoE+=T@0!7<9YkhAKAW z7o)A_XX$7;77~)nl5H)FO|Nfw2=ta}%yD`Jg~wwX^>iJdxE}Lm=9B5d$`zqE6MNvn2+C+6|!;5ik!iw#~i|uzrLvm0R$j#H(<`5SZ`bwkp z+2O2lzVocHRhwx!%CEyNve7 z2rH+VHZQ;K5B}zI;6<_pGeGS9IXGkMI`MjJ#nP-z9LZ%6j5KZZ_#&4hCw@TS9C|$; z##92QIxOMiuYRXNEw3l>&QR4Hw-*f|0eAkM(npsu`xSuq$`)U;&%SPTro^cpr{0rH zv`RAJ-0B$s@Lq@6DH#78oX)Wh5)-X(Gh8Vp`mkw8Y?#I5KfB+7=$GBE_=>=Z=^Bep zijiyihXhdrczn1sC){;wiIgxM$xtFG1mZD`E9r$U(OLcOT=8UY9pAHg%bUlX!*8-^ zOjo&GR4(L0y-8})u-keZw6r?qYFakoyCHLdyS1ThR!6jkBWL9s9;ta-hz~10x0KBCjeCXLEsl_v7hC2uybZVxnBUz+3upb^7)7 z92~KQh%|i}X80Q24(uRBnfGN2u=EZIq-sDDwpvIW8IKN-`e|A6C4@~TRZ4?Vy8$Aw z^nxh)+m{7!dPdJladP4ADABF!ECLNxHRPaH4py@y#964622ouq=I%u^Zw^#3-SADK z_;u<691IA0&#>$w^VxYD-$c?EiKQYgzsAkK()d zd*(&)6~9y}?yD!0rM4v4O7MMv8T!==D#Ia(VfA|>VspQ+IijiYa3!Tkun}Y5R7NLd zNhTiG^iwU=7|jpIAAxOYhA31-8}*Ba1#qWOACv)c*k0+i#Fr4#&&2eo2|7R=PVTz& zYJvmB;jB}J1Ke6fg!6%`@2sg;rrGe(HcsAwfxQ)^CV#fSms%fbV?^5HS#i@u>+Y!F zKbtQJcp=qryp&O7`w1*pdYBU(CbGcA$q~$F)C1!&yk*%js;1zVCwJ z6PAMc@ojI5Y8XAHcER7XCR%@VaXlqp&X(XZ@M+Dk2Mn80E*pnaE>{O%ZWw;xIxYzO zvljN4V{`Rs8YC%L(B1Ej&7kRI4UyLOJioD6$$<4QQQwwL9asU>DG4`tw2j?nuNlS4 zMJ9s!%{yAy?iNp@;??Pzl%(Rt&vL1@FVvIbE4<+@8B^kj4tx8$YpZyhZ9_ zoAx4a;)i!XJ;hu2oke-dJ*cpm)d=Ad-f%g{PL6l`^cAV(;j;5Cx0-sFob!PD*;iQ8 z)iHA`QnTrnCS1{Dt;+(b>C!-*2K#wn!!uFpi>CU+HGd&Fm&>t1a7l>Aqv;NGMy`Xu zBKP^U$9=Gi%k#r-q2^P|{c_FLt%q72$vZf1`$5jaW6$A*$?GpA=gW`JcE_vUN$uC1 zC59O)66-Jw3=UTj(}jj&v`v1QkoU-#Wh6Q>UdXCnN`J(XzrW9BK_}J{gq^g0emj^V z-rGvh>h2m%=ZFYz%jDAvD#K8=YE=`^?bzw@AisC$uivZu*YAbzee|8BgI$PFb888c zIxdrKBo&ru;zy7e+mzyCP0>s$j!0*!D|E=4FOz8aU0rh>J=i^;b(r^2I-&8Q_E@I= zEgua=cd05ikc#lqIL&_%-p;}?Sj*a_k;Mv3pcl0e`lBk zY<^Ka2k7WZY)|w%eeX2QZcZ^YpH7gj%ssZRZoXDac0xIGxnJZ9oBPGNtv_Set{xo? z_E(#iVCUV{9$Pxkjzbu@W7X}|S5hEalsNBA#<`nUAvQh=%@YnLwG}cyo`~FKmR_*a za9=N+8yK+bYXmS)n%$I+pJWL}-g7nHwj`M#RxCJo2lv`ZG2ngBNRb^MZgL%r(ImhM z5?Zc%JvPMoBawM+d&mCam*)Y0m%@sF(}gSgyvAk4s2mrDw)u6328=OhTD_jz^DSxW zL&yF#wed$BP5|vy%A&u(-NBwsv(#VfwWQ>vkNw?tXlBBU-8v6^=nO@Q?}W2l86qkX zPUEZ^u|(00XR)N6?iwX`{^GH9Hhrz_mU5`526J>`qG9bXj4`axT+q~5UA1+t*L;6h zKA5^pe5LQM&pKSbbbl`h97Q-1C2{CNC5yN2d2O}3u`LTh-iy?kmil}h-Vv>!dLk!v z+9)>9;p+T}1`)TjXyN>R_G{lJC<^;UUbTIky3=A#oo`n7W2|UKwfOXua!_ZdvF2cuRD^rM~bSZZM>(lh+d)WiF(n;QY zvgCQ9;r%wZ%vqZgdw>-Y@O3#%Axb`V~jjS*GW*sklZ^@-vd*)YyQ&{0yQy41Ys(C0I-r^9_;F zedHOj=ZRYe0-5K=I!+YdTm;G*&rSM<_d820Sp1*X!>kVW4iyy0H^EP>GcHGuDInn? z+2u$_q5gc2ofmYa4TI(t2jbc+ti^M3rD!${dgIe@(F^J)!_lXq?hFztk$s6*v z3<;9+vpWGF>~h9sC~yuxhzsN%(9&xte^5KzomqtY{E_Ul)pf_VjkBh2%&2ufPWlH= z636@d2!T`J%_Bz80+=Vm=N^*V9yMK4)#9H4Fzg=A>x}DPbk))5O7fsA451z60c2rl zAPaM04=0kADdC1Wxii9nfQLZ#VtUxrmn_Vt3d+I&@PPX#3tyqs7HiWpI|5la4vYi4 z`-U0p2YT;fsYISzeQu7rclg>23eQX@cxC!KmQZlTO(k@mw+y$o=&ZnzHsZB{P&1Y2 z;8(5V3`u3KL9p!NAs=ZM-hBO9JoT+|wAKBClMsdQra6`M0h{c?&IF9R9<4|1iXz52 zO@i>#nG+}r7iha%<2JDm*D%AlyU{-5wrWZbcv#{-ZEua9OSB?koNFfdKjV2dSHwTp zJKe;foX4S`D-N`4`n#G5?Ne@D!@4WdJ_C&dVin#W3M)fHaS%bvdj4S?r>0Wd=)b0&(h)ctS8MW0DO{uw{xS3P+tGKonW zeoBys>Vu4j5?8xCtQ|7y0EWiUmn+hNu-+cfHn$bw*MfYFQF5P*oU?npgS@ zJnVpg2QIx9@k~x`c&a*V3WNN35^Ml?c%BufTh}gx=?5vk?Kt=~pK#AIAou6ob`X=% zd)xE4-iNe^b5bh?5@NSced}*?nolxX2ClS)MPrXUZ5zg@BKFZTsI~v5L~feA2b%Dc zGoomJ&lTAw-RFeBly8a189meqxe441S;A7BVem6B_D~uls z?r8a%cI=5rTCgY;n_Ovc*gfPq#T|6&!U*OM$;poww_pHWSd)^C2k64HClSHJR0ZpbK|N&?%A4XmrhtMrrkFQ^10{u;YJpVax`g3k#0`N7~r( zV0<8aW4@Pyj$)W#clPICQrH(H$SW|gwBu6&yKH@3qvk|ju|T zVCPPah1jVe)A!@gk+%8J}#wtH3uo^XT7(W?PCv3{?csq;eMyh$JpvL)tF(cmucs!Ct^b~Eg-Un01r>HbF zk6iKwPq`F6xd?xJynlN8=)S>&G8rv8;LC4QO(}cVLQ0hpMbB z|KmFx5lV}?VQL?z?^JxV2(7Z9>h^pS5TR(@(|=i|sD0Q_dO7dr9A({umY= zHDxqaF@y6=CI3%TfornliD-;fsp}glE(o{D#0H(Gv&QKYdVE2;3Inmcp3;qN!uZG2 zj_4>{%q8;LSOT3cCZFWHX!#2q`vUL6b&-K1ZF~gB=dXBWu7^(7fFo_mulAPXnvvuk z8~5NE9godS&e#geFIO5v?1wi;)f9jQ@HwymUe{Or`a4kZ6`N*sd$1F+*#qnGaqf;D z%=KU30ZKf%rON;WJXrkN^vVcMtrBqA69U5U`IQq8hA~RcGW>urOxbFjK~AHk0}8{B zKp39MVVbPY!xOllBX@gvmp?V#T8}Cgqvz=7tX(R&^d}6rxo?L{nZJtNxaunI_^J-N z(#H6zn>w_*d%Chj)rIw>h{E?mCOPP<0a$E$RIa6kQcMqj;CYSSV(_Bkp;$|x z3P^Z3yuUjg1UDCSeH*GY8B-?Q;Gpar%K7`jqOWg9{Z0Z99?n6+L+M}PA?pN?e7}Mu zUj-*u(S>|Yq>JyL7;jSPij97MCBBPI23EjHWTWX~wW5MPPzTjCigFAAHmLX^Q`|>Dz68&=xrH6|$vO#~XPHn2m`% zqVa<0f$guEcm@c^f@b({dL=ec)O72ONN`)uR6PgFcu<6Xew_!f;zZbE-fO0QAM$UE z!uybpBC6qq<)Qaq`;d&#l0wr(Cb6S01FF`jPhpee6k2q;3Pp~`HTdiLYCejdcwJHa zGznpjXevN;3)uzEwy`H1zji0}t+jYx97Ro#i@yAup+IWjzCF1s-~}n8P^Q`=pq}lgpE>UyBa-FOzX^Y}v!4!LMENzK~w5#`A>R z%$MUj`^oHMdJfUn0iy+rx6ZBn*K~WPS6w>2_(II>7C#YdUp1{%GPYpWqBITe@c)Kj zB5??>Gf8cvrU=gU8n%Z9V4I&YYTCcm0yr7 zP$@X?$bTQfM0yk;o;b>IQMUHx8MC^~YXEcRs35hJ*LWR`>#SVtM{HT`4=Tgq)mwDR z-g>vmxub9aLNp%%_u=SL49c+K6@hA|6CnEz0O|ue#}1YoBS+tkPz}l(&VBqO8Nno; z=Z>8Ke+?a5ChC#>5X0_T1>(B7^pv{gbmvC#%VErlJ2A^Z&s{oWnX2!~@3U>|&in?32Bu%=BCnxKJYa2ym<<_7;sxctVf_5H_;<3EAVgt zq+xjxZeI;nuZgk!$W++3kAYt^ihfk zMtg2#aoZv}BGn1p&;66vVeRa^ifjL*Vbld@gfYBUP#PBT!u3_}8&~s4+~+I{zRdfQ zTqGX;xiM{5E)#c!ZM<{D+ol#(Xoc;Ce(ym7f*yt9kn z?hnxs*{^gUdBNq#F+k*ODKG;jeSu? z$n#o;*Ty<$QOueCPuV4#2U0vhgP1d2qGRJ&(5X$3Kht#}->oy5Myzh%!Y56zr>`=x zmmBeVY(r`48hI7WV zgr|Ts?CjiU8%0QlI{JN6zcij-F`QLQ(O*gt8hFZ8?w2G@i56x{pO>t+?>qRuI;vLm zv3^Lg8I9?zzolZTXgb!@Oj+xWZ-^=$2clkXA_ow)ape?Mwq!yUl`q*YD`s z&7BiVMeB=C8d25Cz*3k!x7@y(GX}I2rb)mROOOnlk-U$edeP1Is z9;U6V9bNewc=cZSs$$;(T$qp9z)I<7K$8uJ)XAEfKZmZjqNG&} zVauQhnLTh#l^#GG$eL*OQTSY77BmKFb|#g77B$pv|#p20;EI-&S%hdw`^-y;JTYT zH~Cs+Cwj*F0aOqS!L+j>L10nKdSr&Rk)T9SZ#JzRR-I=b&oTSi74*hGpKZ?&&pYme z_hybS*WDHl602l&a-vm%F5HIMuk{RjQuR?}s1>;Gwg7bDTHv~y+NEK}KV3N9cMWE! zsMlu~yIe?OTGeic*i3;sRWuF}$$*q9&YPI;@ZDBk^cMTBl^C=6+?7pE{rB6rbo4{O zgoq|wlgfpwr!+1P$9cya{mTkYj*dAJ5{i*@0KORGLOt)47Y$EBU(0esg<*hs9%9RJ zsyc>Fd~oZql7ytZ>DM8B0xcQrus^s-Ute21YihEj)1BE%7N$pp!ru>vG=RkgD-MLr zMa|XKXG?-xd;3`Bg=Pgw*uDArd7}+);^`vZ>6M?A*T`t}D`oMI& zyS@w|;6C+{(L!WVA{nN%xp3*`G)o(#->j>O32M!VlQk+b;Fbx5RzKB5tYU_#&3ZHV zrcq{Oa&ZzTH=zuH?d=GLX64cHvlU!vu{P_~kA~rzi$3G#s}m=?5hvpiCqob?{q=RRWvg zx9!g-Gr`A8GJ1~|!Rq(Y$1SPtB_8Kjb5icxDM-Z+gT7y-Ow|{@I@z5p7~nb|wFdf0 zJ)Pw~KPf$S7e7xeO+RPuC+Hwa;TqOR-K}MM;Hs#f_i%>)(2RY!Lx{v6l!6zcaXLG0 zdN_A+UViR~S$11?(X8Jyd9JdRAV7AzD5$5Y#lmeWKhD;;_PBe#Pc1~!Kz{6*Mx!d@ z8FzezFqrgWLdb^v+k}w+))6a9nVk*Wg_BLPTGG zV0#=W6MZbrA8mUZEiJh{opXso8F0LZvsZt)wxgF0sf=V;I z_Z_H_lBb%Rf8SNogr_K@ayD<19}bx;JzQx%JB#+0(=6JV=-qUxa$y)b-&PelP^mqf z+*{yinA)kcqc*SAH@lyA#--iew@2HiPw4$-d;aQlVCD_c9UJ?UCe+f2N$RzqFos1Qcgd6Su$P~dV&m;)u8M23 z*umiAfOVLG_w#k|cmIm<=r4!jDn{|vy)SiGn~)*fG%7siMI$K77T6CV0DD((C8a#Z`5F8E#}Jxx+^A9a|>THRD?Ey4V>mL^qr^7?f77m6#=?+D;c;v7QC@ziGrvL%=u z(n`XSfCuxYq|w6=bJPpyE=lpb!yRBW%sr-3+Lf5={;e)`wAzDSQElp^f>p*Zmt39b?+_klvQUJ>5-uPG(1_2GaSXY{CLwE z_fazqv7#7f=YEu>`x~l!rYraTf3Ofb_*MSzJ)lLd7h#SBHS|ZgNj)skU8FI>X?ISk zEJBh)cexEIk-HaN=drwvLWHl()@Kk^MAOy+(AIc8uCr(Cv>L7vQ=ZF2ntnWvO?@PKd$)M^U7_8+@ezT z>TNyjJjAPp8kcQ`Ijhk z00fxs7i`=YGcaTT0ek zO^5Sg6McRqM+FoX8%-u+14u+BfJ8*gD}C)aL2ZYT{km!VrqIOnfSGF8I6H44UnuM= zf6(*{qZeR3XyV_*bUsuD_gJV1JOkI=K5db{TV)RpxyNrUq1sAAe<1FBZ~+kDih$Hy z$mW9h=P`nZX~^b`_~)S)Bw`zA#MEue-(AfV_CIYoz_}ZM8nFeV4D0&E_& zPoVdsK9S#yeBoo24mt<{KA2X42O+@WF9>kp8vp^Op6O_r<15Gtwb@{L*AGLc44;L~ zAt*?HB=zBQ)TeDlUimn}Y)bUej@OSW`@@N%`r zA4Y`tRV)6B-XER&a)t6oc_2;k{SP&Y>dD|_??g4V%;(!)$ zLHgE%FIqc^_VZg!al>tpY!D{Kk&q?#w)sLO4@N64PY))=$CA~Ev z4qe{;OnTekMxt3|58uk3CId-tXiVsd7vnL1UX^A~a3t)A0Z}C+(V`%cs)RI@fz%pV z?^4+*dRpaoKN~CO3-8V1n5ll){pNK(TcIt)I*|>V^!6lDAK5;a;pnN44)~e$)_BiE zdY(O7(Zz%u$~m0EXDr*E=M5FO^V5j%`)NcFVU382SLJmVyz)ezM$A9dlV3@E>bG_y zX3m&_Y3!QrjQxYC*XcvVS7*JtLG`c{E*7QLLeA{DyZhi+Dg!0`4*?}Bs2>C{u27+7 zIGrx=>7#kz5xB(X-;D^cZi@kuT~1{C+pVZ7w~SWz64PVY3Pjy&WkvWPo4unS&C zj+((I*Kewn&tOsY<@AJ}*Yyp1xVVS)i~`Cw>nmKNveS)U(y0xC(xU+Juivf>%52Vi%_W^Y=; ztfuW8jH7$lTIzI%Z#}GuTv_M2&!qN7U}G)wrf|bb@*%1g!n6?03^sMN8mE1dYOxI3 zX$Vk@j_NDjey&9KGA0%F!H_}b)D9c;rhyH5yZWO&Tm=NZ5jblAL2uKVT>W6b9GO!J z(!GmS0YK0jrTp+qx%?d{JXdNPq5Ld91ay3RFiV;4`&0Fk%hVABzyReg`C`?E9smGW z*AHAj$Wt~;#(TpCmm#){SG@D&M2Y2KRR3w!DB&Z$oFkIwz}vC4SJ733ooa^(79OnI zewqB8RHiB~R-d4{0VBfN+#XG;3Zt6C8WC>$Wpec&hyt|Q#jDBs1-h;=(pe;^ywq~jaoj=YMWr@~w?5mxaabGLKZ{z59&HDd zh$T%qcKvM-Q`(jRk|o1{>p;-I&yC8q1t5SS00BIO?B^|;a9@%0U~K6pu4weh#t~c#2*8qZf^%llwfY1` zjuR`!$@(PI7TX$Q_;loNzod(jKWIn{veO%Qi4UTky4vR4GJ1QS1rpWQ8mx`}Applx z*M7dv;i&P^ualXm*4mdmN~&)zeRzPA%u~+*S&NL;#|6f9i46xr+sd8420FXoY1fc= za-rmCrOSf))fCfF6qbPxxW-pm%6ept0A;CqiATwhBh36wCksF#NT4_K ztZMwBgoB2!w0XqZ01Sn3{g4bmB9c~b14zU%Pr;{d{X)xtLkO((fO{zTmdnFQpUuM( z0r#>FA)H=GFE^s)jB&hyMQqetnf*n6eKrPPrlKRnSN!j~pIj9%9-r;s9hiLQ7+Ec= z1zk}%?arIEbe4KXY3r;4q`Zw~iw9<40{1P12dKhMW45o<5vX<88&9h#Vq{ch4u~CM zXe|a{MUo^pf>+8Ry9a)5vREbJ6%h5-j*WUtYxYw-H%5$Ps`I=pR@)3jy%p0pzI{fp z%)6(TnG2F=zJAgE`XmlU7IlGI@p6T<=zsy7WKOyY8_y(gFmqwbY&Y+XkNB zsWoYOoN5YYKLp1<3hJcIOa!rXE>&k?M}%V~#W?G|+a_HFl)Art zEEF1168sjP>vh=N8I#{WJ6jONm#msJmZB=ubMU>393|MeQdS5_Z2RW z>ToETjPDl%ro4mpPl)LtTrpj`J0sz=QAfLJv3mj6|K@=eZk1SH7hx)EPY$+Z9=7HG|<(^*%)Q-=Ol}ykk zD^XP{bCP2d)_GigUVi0oT%$QbbPPq|*@D3+iNSR$UkYUVV>@!xiot zQB6x)JyFY&5hs|9h^^*nii{=Lc6_VJNl(6ejjzJ&!;<1sT#7((TbvGCAj6fNTcojc zM5yGGcqA$mZG0n|e}2$E^Fn6#?08i?!%hO8Dkx)gx!bvmH{Sm~4aB^qm>)5e0G51o z@om9GgJVML03)o!yw-Yl);+iaoi=W<`b|S-yAyZ`uGsx*sL!&LqHC@#mH#V z=fK|eMKH9QN1SiYkM;#d{n>T?gk*O!W&a5)%NDE?F=j2&ePsAQCxS7xLd93von&g? z1-Ba{NY#heq&fx@zP(VDXc5~EyVw}{!-?=30h@1j@7%vOFYu+o5tP^yuZ0>aL(nO7 zy()@!7^7RVGxTUWf0x$y9Y<57VHG}c#{;%Y4^+edb|Rt`gRH(%LvAMja3ZRpOe!~3 z{^vw6f~hV8U0+QSQKhQ!+j$yU z)v`Dtd`LgK1X-Y(Bd*;`9JCv%&J@Q(pi^fyv1j!TsIxaJ=YJM$T;cV#Rwg6G{a^b zC^sMLY)w*msvWhe9biz05@J`w3rPQgBHp|qBB(;C4`JbzWnAfHCU!7 zvFe=krOtPD(#*^E8v6KI+}BEGXu%1lOEsZYyydhPANJ*;Bb0;3KtVCo;szv6ZE}xd zq}6F6`rOH|P=x2GF#tup`vpb#xTB)+fwZ?3*=vwTGYq=#D?N4~LUCL)<_`B-`dKq1 zLG@@}My*X@!{KR(ugAMW`)B*uC z_F`zI?^dapPg4)r%&S*xxxO%(F`=7A4mFDc* z;$^fnxIGHrw55(XWG~!md*bD=c1{#DX>U;z%BE6(l~}dUQ5Bd4PIcspFoxz~p7E?3 z7VCXvZ_SdQFtdHlte%YNttOQ^CQ74kZ8t)_Q#;xl zu0>BK3%L)!1*(bH>g?BUM&Ra#)IEIr`Dk&NDdz3|a;LqU&9J=ves?0pcXVMdeVppa zp;(#^^6Nt2JQMLQdTzh6vYr=|gURAIe^t+d-Y+&A=@{f*e;qvKaHt}olzPw_-fo|C z(!Uzq$c}NFo*DdJIW-}HELwX}zWtq+z8r&OgVgS7TBp3eALk#X)iqK}(K zdK)33h`foRofTW|lhp{Ln?u^P8`C;PyEz~28K|7aN`QQ~po-do%kI7KwA7 z?d;VAj+C`?Vun|qKH}ZTcAL|St-#;gPT%PA2{ESKJaQ}1sK!}#^K0Z8u%m9!<^J-H z&y2d$?d~B~|9ySXlGhh`n0GHKwi=}sw_6Gk*(_>xyUX-=C~_{cn5s7tbXNtd|M~&? zuLz+3Zm~97g*Zz!|2pPTpTy*-0k%@$pG)qm{`zpOZZHQ2;4IwyHE`}cO2W*JmR?{zD-Ri2T&~G0V z1iWYm87~F4`W17_n47LQ)gwn~7Y)Ik(4^F444?nkjZdJRs-q}Txt^A;4gQ#~^M>`% zp!b&#SPoO%9^={?rkaLQ9!X9ghHr=zVTXYAC%}cPb7*hUQ?iPOe8r0nO6CDcheIBP?DHytAx(#;7>~6DFdM@AJ;=;T z+tG~JxDDM@TpDMp}=jtmwi@nfR( za_E$P+bws^cE`q*1kf4@0frTH7@1yMch3}7vHNv+R7Wk!^lSP@hT>DpH}xFl0`@d1 zH#P$a@}5Z8_$`X}oyss%y?%X*^UAFDgVX_BHInn+UWZ(w@WybKt?#6L$NzKt>)9oC zUIW|Sb{+>u1K57Ji5bkq%7PnV;ot-{vp{g$S|Cl#O^_zsSTBPU?qCnMa6m$VKbQ&$ zg80paK_C#XAlO{k#8l8km>;++z{hI}7UDJIf+K9r&EU40opuvEWOY z?%=S4IQe|;?5F+GoBQ`$f}4~1iFLXAC5@q#*Y1X@P6@&k6G!ftehI&*s$mj5E}9VL zEypsFkw59{&CGYhD4AZvU^JYI0bVMkx-{Lr#qIV!K_$y61sXy%(gv3v4>x|`s|F$(f!T$-m<6V`HI)v<^(W3;W$k;yPRG=u z?dp-e)>-D8i$i!b_eA)SWiOd4&Ih*%(i@eTxnYzh<|R>k1v4tH?uJeex**B}L53LV zg7*lkJot;ZD4~^WRsB7;@SaL#xmWULu)ts5UO4(I?=B^I=%VR_cp6)1zLw{g_+0uA zFW#xl?0#0fmgbjBpzzo_^YU=SuuXi#UOf}JYh_-`OrfW+PPmTTG|lBj$SJ0Ej#ypk+<8hI zN?;ct!omJyWDhl{5Cc2L4)Ajcc=XRNBL|De2yQOy@3RZdxr5?Qfko|jI5?z#tP%ho z)wD1%SBBbIaM?K`;1*`TFUFpAq2}$c$@%-N%e6lio8sc&JcgQb+gTvN{C^DQpRF-_ z?7{SVYU8gm5;VVR2!Q^dMb1V){wl)4{j12CAjq??t^Yb(_It5^I|~0QMv(lk k$K - - - netcoreapp2.1 - portable - ReadLine.Tests - ReadLine.Tests - true - - - - - - - - - - - diff --git a/test/ReadLine.Tests/ReadLineTests.cs b/test/ReadLine.Tests/ReadLineTests.cs deleted file mode 100755 index 2b8cfdc..0000000 --- a/test/ReadLine.Tests/ReadLineTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Linq; -using Xunit; -using static ReadLine.ReadLine; - - -namespace ReadLine.Tests -{ - public class ReadLineTests : IDisposable - { - public ReadLineTests() - { - string[] history = { "ls -a", "dotnet run", "git init" }; - AddHistory(history); - } - - [Fact] - public void TestNoInitialHistory() - { - Assert.Equal(3, GetHistory().Count); - } - - [Fact] - public void TestUpdatesHistory() - { - AddHistory("mkdir"); - Assert.Equal(4, GetHistory().Count); - Assert.Equal("mkdir", GetHistory().Last()); - } - - [Fact] - public void TestGetCorrectHistory() - { - Assert.Equal("ls -a", GetHistory()[0]); - Assert.Equal("dotnet run", GetHistory()[1]); - Assert.Equal("git init", GetHistory()[2]); - } - - public void Dispose() - { - // If all above tests pass - // clear history works - ClearHistory(); - } - } -}