Skip to content

Commit

Permalink
start fleshing out the parser, add some unit tests for sanity
Browse files Browse the repository at this point in the history
  • Loading branch information
doubleyewdee committed Nov 15, 2018
1 parent e40e759 commit 9b8af82
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 80 deletions.
18 changes: 18 additions & 0 deletions ConsoleBuffer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "condo", "src\condo\condo.cs
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "condo.uwp", "src\condo.uwp\condo.uwp.csproj", "{FB9FD3E5-EDF1-4924-8945-42DC0AFE478F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleBufferTests", "test\ConsoleBufferTests\ConsoleBufferTests.csproj", "{D11953E5-195F-43F4-9109-DE93CED6D016}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -73,6 +75,22 @@ Global
{FB9FD3E5-EDF1-4924-8945-42DC0AFE478F}.Release|x86.ActiveCfg = Release|x86
{FB9FD3E5-EDF1-4924-8945-42DC0AFE478F}.Release|x86.Build.0 = Release|x86
{FB9FD3E5-EDF1-4924-8945-42DC0AFE478F}.Release|x86.Deploy.0 = Release|x86
{D11953E5-195F-43F4-9109-DE93CED6D016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Debug|ARM.ActiveCfg = Debug|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Debug|ARM.Build.0 = Debug|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Debug|x64.ActiveCfg = Debug|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Debug|x64.Build.0 = Debug|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Debug|x86.ActiveCfg = Debug|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Debug|x86.Build.0 = Debug|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Release|Any CPU.Build.0 = Release|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Release|ARM.ActiveCfg = Release|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Release|ARM.Build.0 = Release|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Release|x64.ActiveCfg = Release|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Release|x64.Build.0 = Release|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Release|x86.ActiveCfg = Release|Any CPU
{D11953E5-195F-43F4-9109-DE93CED6D016}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
18 changes: 18 additions & 0 deletions src/ConsoleBuffer/BaseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace ConsoleBuffer
{
public abstract class BaseCommand
{
internal BaseCommand(string bufferData)
{
this.Parse(bufferData);
}

protected abstract void Parse(string bufferData);
}

public sealed class UnsupportedCommand : BaseCommand
{
public UnsupportedCommand() : base(null) { }
protected override void Parse(string bufferData) { }
}
}
48 changes: 43 additions & 5 deletions src/ConsoleBuffer/Buffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ public void Append(byte[] bytes, int length)
case ParserAppendResult.Complete:
this.ExecuteParserCommand();
break;
case ParserAppendResult.Pending:
break;
case ParserAppendResult.Invalid:
// XXX: we should keep a trailing history of received bytes or something so we can actually log meaningful data.
Logger.Verbose("Invalid command sequence in parser.");
break;
default:
throw new InvalidOperationException("unexpected parser result");
}
Expand All @@ -79,21 +85,53 @@ private bool AppendChar(byte b)

private void ExecuteParserCommand()
{
switch (this.parser.CurrentCommand)
switch (this.parser.Command)
{
case ParserCommand.LF:
case ControlCharacterCommand ctrl:
this.HandleControlCharacter(ctrl.Code);
break;
case UnsupportedCommand unsupported:
// XXX: would be nice to log the sequence
Logger.Verbose("Unsupported command provided.");
break;
default:
throw new InvalidOperationException("Unknown command type passed.");
}
}

private void HandleControlCharacter(ControlCharacterCommand.ControlCode code)
{
switch (code)
{
case ControlCharacterCommand.ControlCode.NUL:
// XXX: do we want to print these in some magic way? it seems like most terminals just discard these characters when received.
break;
case ControlCharacterCommand.ControlCode.BEL:
// XXX: need to raise a beep event.
break;
case ControlCharacterCommand.ControlCode.BS:
this.cursorX = (short)Math.Max(0, this.cursorX - 1);
break;
case ControlCharacterCommand.ControlCode.CR:
this.cursorX = 0;
break;
case ControlCharacterCommand.ControlCode.FF: // NB: could clear screen with this if we were so inclined. apparently xterm treats this as LF though, let's emulate.
case ControlCharacterCommand.ControlCode.LF:
if (this.currentLine == this.lines.Count - 1)
{
this.lines.Add(new Line());
}

this.cursorY = (short)Math.Min(this.Height - 1, this.cursorY + 1);
break;
case ParserCommand.CR:
this.cursorX = 0;
case ControlCharacterCommand.ControlCode.TAB:
// XXX: we don't handle commands to set tab stops yet but I guess need to do so at some point!
this.cursorX = (short)Math.Max(this.Width - 1, (this.cursorX + 8 - (this.cursorX % 8)));
break;
default:
throw new InvalidOperationException($"Unexpected parser command {this.parser.CurrentCommand}");
// XXX: should log the sequence.
Logger.Verbose("Encountered unsupported sequence.");
break;
}
}

Expand Down
46 changes: 46 additions & 0 deletions src/ConsoleBuffer/Commands/ControlCharacterCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
namespace ConsoleBuffer
{
public sealed class ControlCharacterCommand : BaseCommand
{
public enum ControlCode
{
/// <summary>
/// Not really a command but a notable character we may wish to specially handle (\0 or '^ ')
/// </summary>
NUL = 0,
/// <summary>
/// Beep beep (\a or ^G)
/// </summary>
BEL,
/// <summary>
/// Backspace (\b or ^H)
/// </summary>
BS,
/// <summary>
/// Carriage return (\r or ^M)
/// </summary>
CR,
/// <summary>
/// Form feed (\f or ^L)
/// </summary>
FF,
/// <summary>
/// Line-feed (\n or ^J)
/// </summary>
LF,
/// <summary>
/// Horizontal tab (\t or ^I)
/// </summary>
TAB,
}

public readonly ControlCode Code;

public ControlCharacterCommand(ControlCode code) : base(null)
{
this.Code = code;
}

protected override void Parse(string bufferData) { }
}
}
Loading

0 comments on commit 9b8af82

Please sign in to comment.