diff --git a/.gitignore b/.gitignore index 08b1161..69d95ef 100644 --- a/.gitignore +++ b/.gitignore @@ -17,14 +17,19 @@ [Rr]eleases/ x64/ x86/ -build/ +src/**/build/ +tests/**/build/ bld/ [Bb]in/ [Oo]bj/ +packages/ # Visual Studo 2015 cache/options directory .vs/ +# Jetbrains Rider cache/options directory +.idea/ + # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* @@ -36,7 +41,6 @@ TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ -dlldata.c *_i.c *_p.c @@ -88,7 +92,11 @@ $tf/ # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper + +# Visual Studio preference files *.DotSettings.user +*.csproj.user +*.vcxproj.filters # JustCode is a .NET coding addin-in .JustCode @@ -134,6 +142,8 @@ publish/ *.pubxml *.publishproj +# NuGet Packages +#*.nupkg # The packages folder can be ignored because of Package Restore **/packages/* # except build/, which is used as an MSBuild target. @@ -151,12 +161,10 @@ AppPackages/ # Others *.[Cc]ache ClientBin/ -[Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview -*.pfx *.publishsettings node_modules/ bower_components/ @@ -193,9 +201,20 @@ FakesAssemblies/ # Visual Studio 6 workspace options file *.opt -# NuGet -NuGet/ +**/node_modules +**/node_modules/* +**/Images/ActualOutput +**/Images/ReferenceOutput + +# ASP.NET 5 +project.lock.json + +#BenchmarkDotNet +**/BenchmarkDotNet.Artifacts/ + +# Build process +*.csproj.bak -# Git -.gitignore -.gitattributes +# Advanced Installer +*-cache/ +*-SetupFiles/ \ No newline at end of file diff --git a/artifacts/ReadLine.1.0.0.nupkg b/artifacts/ReadLine.1.0.0.nupkg deleted file mode 100644 index 7ca71ff..0000000 Binary files a/artifacts/ReadLine.1.0.0.nupkg and /dev/null differ diff --git a/artifacts/ReadLine.2.0.1.nupkg b/artifacts/ReadLine.2.0.1.nupkg deleted file mode 100644 index 3e9ef8a..0000000 Binary files a/artifacts/ReadLine.2.0.1.nupkg and /dev/null differ diff --git a/artifacts/ReadLine.2.0.3.nupkg b/artifacts/ReadLine.2.0.3.nupkg index 8f196ec..2538e1b 100644 Binary files a/artifacts/ReadLine.2.0.3.nupkg and b/artifacts/ReadLine.2.0.3.nupkg differ diff --git a/src/ReadLine.Demo/ReadLine.Demo.csproj b/src/ReadLine.Demo/ReadLine.Demo.csproj index 6b3a6bd..a1a89cb 100755 --- a/src/ReadLine.Demo/ReadLine.Demo.csproj +++ b/src/ReadLine.Demo/ReadLine.Demo.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp2.2 portable ReadLine.Demo Exe diff --git a/src/ReadLine/KeyHandler.cs b/src/ReadLine/KeyHandler.cs index 577af65..075700e 100644 --- a/src/ReadLine/KeyHandler.cs +++ b/src/ReadLine/KeyHandler.cs @@ -1,373 +1,355 @@ -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"] = () => - { - while (!IsStartOfLine()) - Backspace(); - }, - ["ControlK"] = () => - { - var pos = _cursorPos; - MoveCursorEnd(); - while (_cursorPos > pos) - Backspace(); - }, - ["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() - { - if (IsStartOfLine()) - return; - - if (IsStartOfBuffer()) - _console2.SetCursorPosition(_console2.BufferWidth - 1, _console2.CursorTop - 1); - else - _console2.SetCursorPosition(_console2.CursorLeft - 1, _console2.CursorTop); - - _cursorPos--; - } - - - 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() - { - var currentCursorLine = _console2.CursorTop; - var startColumn = _console2.CursorLeft - _cursorPos; - _console2.SetCursorPosition(startColumn, currentCursorLine); - _console2.Write(new string(' ', _text.Length)); - _console2.SetCursorPosition(startColumn, currentCursorLine); - - _text.Clear(); - _cursorPos = 0; - _cursorLimit = 0; - } - - - 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() - { - if (IsStartOfLine()) - return; - - MoveCursorLeft(); - 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 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() - { - return _cursorLimit - _cursorPos == 1; - } - - int IncrementIf(Func expression, int index) - { - return expression() ? index + 1 : index; - } - - int DecrementIf(Func expression, int index) - { - return 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() - { - while (_cursorPos > _completionStart) - Backspace(); - - _completionsIndex = 0; - - WriteString(_completions[_completionsIndex]); - } - - - private void NextAutoComplete() - { - while (_cursorPos > _completionStart) - Backspace(); - - _completionsIndex++; - - if (_completionsIndex == _completions.Length) - _completionsIndex = 0; - - WriteString(_completions[_completionsIndex]); - } - - - private void PreviousAutoComplete() - { - while (_cursorPos > _completionStart) - Backspace(); - - _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, + ["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.csproj b/src/ReadLine/ReadLine.csproj index be3c5c1..88d7801 100755 --- a/src/ReadLine/ReadLine.csproj +++ b/src/ReadLine/ReadLine.csproj @@ -2,44 +2,33 @@ ReadLine - Toni Solarin-Sodara - Toni Solarin-Sodara - Toni Solarin-Sodara - net45;net462;net472;netcoreapp2.2;netcoreapp3.0;netstandard2.0 + net45;net461;net472;net48;netcoreapp2.2;netcoreapp3.0;netstandard2.0 ReadLine ReadLine - readline;gnu;console;shell;cui + readline gnu console shell cui https://github.com/tonerdo/readline - https://github.com/tonerdo/readline/blob/master/LICENSE - git + GIT https://github.com/tonerdo/readline true snKey.snk true - Updated to support .NET Standard v2.0 / Core 2.2 & 3.0 / Framework v4.5 / v4.6.2 / v4.7.2 + Updated to support .NET Standard v2.0 / Core 2.2 & 3.0 / Framework v4.5 - v4.8 2.0.3 A GNU-Readline like library for .NET + artifacts + MIT - - - - - - - - - - - - + + + - - + +