More cursor movements
This commit is contained in:
parent
ac43b77b1a
commit
b8914311b4
@ -20,6 +20,11 @@ namespace MApplication
|
||||
|
||||
public int Height { get; }
|
||||
|
||||
public void HideCursor()
|
||||
{
|
||||
Console.CursorVisible = false;
|
||||
}
|
||||
|
||||
public void MoveCursorTo(int column, int line)
|
||||
{
|
||||
Console.CursorLeft = StartingColumn + column;
|
||||
@ -39,6 +44,11 @@ namespace MApplication
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowCursor()
|
||||
{
|
||||
Console.CursorVisible = true;
|
||||
}
|
||||
|
||||
public void WriteText(string s)
|
||||
{
|
||||
Console.Write(s);
|
||||
|
@ -1,14 +1,18 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace MApplication
|
||||
{
|
||||
internal class DisplayLine
|
||||
{
|
||||
public ImmutableList<DisplayLineChunk> Chunks { get; }
|
||||
|
||||
public DisplayLine(ImmutableList<DisplayLineChunk> chunks)
|
||||
{
|
||||
Chunks = chunks;
|
||||
Width = chunks.Sum(c => c.Width);
|
||||
}
|
||||
|
||||
public ImmutableList<DisplayLineChunk> Chunks { get; }
|
||||
|
||||
public int Width { get; }
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,17 @@ namespace MApplication
|
||||
int width,
|
||||
int height,
|
||||
int startingColumn = 0,
|
||||
int startingLine = 0)
|
||||
int startingLine = 0,
|
||||
int cursorRelativeColumn = 0,
|
||||
int cursorRelativeLine = 0)
|
||||
{
|
||||
Text = text;
|
||||
Width = width;
|
||||
Height = height;
|
||||
StartingColumn = startingColumn;
|
||||
StartingLine = startingLine;
|
||||
CursorRelativeColumn = cursorRelativeColumn;
|
||||
CursorRelativeLine = cursorRelativeLine;
|
||||
}
|
||||
|
||||
public DisplayText Text { get; }
|
||||
@ -28,8 +32,138 @@ namespace MApplication
|
||||
|
||||
public int StartingLine { get; }
|
||||
|
||||
public int CursorRelativeColumn { get; }
|
||||
|
||||
public int CursorRelativeLine { get; }
|
||||
|
||||
public int CursorAbsoluteColumn => CursorRelativeColumn + StartingColumn;
|
||||
|
||||
public int CursorAbsoluteLine => CursorRelativeLine + StartingLine;
|
||||
|
||||
public int CurrentLineWidth => Text.Lines[CursorAbsoluteLine].Width;
|
||||
|
||||
public DisplayTextViewPort CursorLeft(out bool needsRedraw)
|
||||
{
|
||||
if (CursorRelativeColumn == 0)
|
||||
{
|
||||
return ShiftLeft(out needsRedraw);
|
||||
}
|
||||
else
|
||||
{
|
||||
return With(out needsRedraw, cursorRelativeColumn: CursorRelativeColumn - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public DisplayTextViewPort CursorRight(out bool needsRedraw)
|
||||
{
|
||||
if (CursorRelativeColumn == Width - 1)
|
||||
{
|
||||
return ShiftRight(out needsRedraw);
|
||||
}
|
||||
else
|
||||
{
|
||||
return With(out needsRedraw, cursorRelativeColumn: CursorRelativeColumn + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private DisplayTextViewPort SnapToLine(out bool needsRedraw)
|
||||
{
|
||||
if (CursorAbsoluteColumn > CurrentLineWidth)
|
||||
{
|
||||
needsRedraw = true;
|
||||
var toSubtract = CursorAbsoluteColumn - CurrentLineWidth;
|
||||
if (toSubtract < CursorRelativeColumn)
|
||||
{
|
||||
return With(out var _, cursorRelativeColumn: CursorRelativeColumn - toSubtract);
|
||||
}
|
||||
|
||||
return With(
|
||||
out var _,
|
||||
startingColumn: StartingColumn - (toSubtract - CursorRelativeColumn),
|
||||
cursorRelativeColumn: 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
needsRedraw = false;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public DisplayTextViewPort CursorUp(out bool needsRedraw)
|
||||
{
|
||||
bool changed1;
|
||||
var result1 = CursorRelativeLine switch
|
||||
{
|
||||
0 => ShiftUp(out changed1),
|
||||
_ => With(out changed1, cursorRelativeLine: CursorRelativeLine - 1),
|
||||
};
|
||||
var result = result1.SnapToLine(out var changed2);
|
||||
needsRedraw = changed1 || changed2;
|
||||
return result;
|
||||
}
|
||||
|
||||
public DisplayTextViewPort CursorDown(out bool needsRedraw)
|
||||
{
|
||||
bool changed1;
|
||||
var result1 = CursorRelativeLine switch
|
||||
{
|
||||
_ when CursorRelativeLine == Height - 1 => ShiftDown(out changed1),
|
||||
_ => With(out changed1, cursorRelativeLine: CursorRelativeLine + 1),
|
||||
};
|
||||
var result = result1.SnapToLine(out var changed2);
|
||||
needsRedraw = changed1 || changed2;
|
||||
return result;
|
||||
}
|
||||
|
||||
public DisplayTextViewPort CursorHome(out bool needsRedraw)
|
||||
{
|
||||
return With(out needsRedraw, startingColumn: 0, cursorRelativeColumn: 0);
|
||||
}
|
||||
|
||||
public DisplayTextViewPort CursorEnd(out bool needsRedraw)
|
||||
{
|
||||
var lineWidth = Text.Lines[CursorAbsoluteLine].Width;
|
||||
var toAdd = lineWidth - CursorAbsoluteColumn;
|
||||
if (toAdd == 0)
|
||||
{
|
||||
needsRedraw = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (CursorRelativeColumn + toAdd < Width)
|
||||
{
|
||||
return With(out needsRedraw, cursorRelativeColumn: CursorRelativeColumn + toAdd);
|
||||
}
|
||||
|
||||
return With(
|
||||
out needsRedraw,
|
||||
startingColumn: StartingColumn + CursorRelativeColumn + toAdd - Width + 1,
|
||||
cursorRelativeColumn: Width - 1);
|
||||
}
|
||||
|
||||
public DisplayTextViewPort ShiftLeft(out bool needsRedraw)
|
||||
{
|
||||
return With(out needsRedraw, startingColumn: Math.Max(StartingColumn - 1, 0));
|
||||
}
|
||||
|
||||
public DisplayTextViewPort ShiftRight(out bool needsRedraw)
|
||||
{
|
||||
return With(out needsRedraw, startingColumn: StartingColumn + 1);
|
||||
}
|
||||
|
||||
public DisplayTextViewPort ShiftUp(out bool needsRedraw)
|
||||
{
|
||||
return With(out needsRedraw, startingLine: Math.Max(StartingLine - 1, 0));
|
||||
}
|
||||
|
||||
public DisplayTextViewPort ShiftDown(out bool needsRedraw)
|
||||
{
|
||||
return With(out needsRedraw, startingLine: StartingLine + 1);
|
||||
}
|
||||
|
||||
public void RenderTo(IOutputView view)
|
||||
{
|
||||
view.HideCursor();
|
||||
for (var lineNumber = StartingLine; lineNumber < StartingLine + Height; lineNumber++)
|
||||
{
|
||||
view.MoveCursorTo(0, lineNumber - StartingLine);
|
||||
@ -63,32 +197,45 @@ namespace MApplication
|
||||
view.WriteText(new string(' ', numberOfSpaces));
|
||||
}
|
||||
}
|
||||
view.MoveCursorTo(column: CursorRelativeColumn, line: CursorRelativeLine);
|
||||
view.ShowCursor();
|
||||
}
|
||||
|
||||
public DisplayTextViewPort With(
|
||||
out bool changed,
|
||||
int? width = null,
|
||||
int? height = null,
|
||||
int? startingColumn = null,
|
||||
int? startingLine = null)
|
||||
int? startingLine = null,
|
||||
int? cursorRelativeColumn = null,
|
||||
int? cursorRelativeLine = null)
|
||||
{
|
||||
var widthValue = width ?? Width;
|
||||
var heightValue = height ?? Height;
|
||||
var startingColumnValue = startingColumn ?? StartingColumn;
|
||||
var startingLineValue = startingLine ?? StartingLine;
|
||||
var cursorRelativeColumnValue = cursorRelativeColumn ?? CursorRelativeColumn;
|
||||
var cursorRelativeLineValue = cursorRelativeLine ?? CursorRelativeLine;
|
||||
if (widthValue == Width &&
|
||||
heightValue == Height &&
|
||||
startingColumnValue == StartingColumn &&
|
||||
startingLineValue == StartingLine)
|
||||
startingLineValue == StartingLine &&
|
||||
cursorRelativeColumnValue == CursorRelativeColumn &&
|
||||
cursorRelativeLineValue == CursorRelativeLine)
|
||||
{
|
||||
changed = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
return new DisplayTextViewPort(
|
||||
text: Text,
|
||||
width: widthValue,
|
||||
height: heightValue,
|
||||
startingColumn: startingColumnValue,
|
||||
startingLine: startingLineValue);
|
||||
startingLine: startingLineValue,
|
||||
cursorRelativeColumn: cursorRelativeColumnValue,
|
||||
cursorRelativeLine: cursorRelativeLineValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
int Width { get; }
|
||||
int Height { get; }
|
||||
void MoveCursorTo(int column, int line);
|
||||
void ShowCursor();
|
||||
void HideCursor();
|
||||
void SetStyle(Style style);
|
||||
void WriteText(string s);
|
||||
}
|
||||
|
@ -4,6 +4,80 @@ using System.IO;
|
||||
|
||||
namespace MApplication
|
||||
{
|
||||
internal class FileRenderer
|
||||
{
|
||||
private readonly IOutputView _outputView;
|
||||
|
||||
public FileRenderer(IOutputView outputView)
|
||||
{
|
||||
_outputView = outputView;
|
||||
}
|
||||
|
||||
private static MParser CreateParser(ITextWindow window)
|
||||
{
|
||||
return new MParser(window);
|
||||
}
|
||||
|
||||
private static SyntaxTree GetTree(string fileName)
|
||||
{
|
||||
var text = File.ReadAllText(fileName);
|
||||
var window = new TextWindowWithNull(text, fileName);
|
||||
var parser = CreateParser(window);
|
||||
var tree = parser.Parse();
|
||||
return tree;
|
||||
}
|
||||
|
||||
public void RenderFile(string fileName)
|
||||
{
|
||||
var tree = GetTree(fileName);
|
||||
var text = CodeProcessor.GetText(tree);
|
||||
var viewPort = new DisplayTextViewPort(
|
||||
text: text,
|
||||
width: 80,
|
||||
height: 24);
|
||||
|
||||
var needsRedraw = true;
|
||||
while (true)
|
||||
{
|
||||
if (needsRedraw)
|
||||
{
|
||||
viewPort.RenderTo(_outputView);
|
||||
}
|
||||
|
||||
_outputView.MoveCursorTo(viewPort.CursorRelativeColumn, viewPort.CursorRelativeLine);
|
||||
|
||||
var key = Console.ReadKey(intercept: true);
|
||||
switch (key.Key)
|
||||
{
|
||||
case ConsoleKey.LeftArrow:
|
||||
viewPort = viewPort.CursorLeft(out needsRedraw);
|
||||
break;
|
||||
|
||||
case ConsoleKey.RightArrow:
|
||||
viewPort = viewPort.CursorRight(out needsRedraw);
|
||||
break;
|
||||
|
||||
case ConsoleKey.UpArrow:
|
||||
viewPort = viewPort.CursorUp(out needsRedraw);
|
||||
break;
|
||||
|
||||
case ConsoleKey.DownArrow:
|
||||
viewPort = viewPort.CursorDown(out needsRedraw);
|
||||
break;
|
||||
|
||||
case ConsoleKey.Home:
|
||||
viewPort = viewPort.CursorHome(out needsRedraw);
|
||||
break;
|
||||
|
||||
case ConsoleKey.End:
|
||||
viewPort = viewPort.CursorEnd(out needsRedraw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
private static readonly string BaseDirectory;
|
||||
@ -24,20 +98,6 @@ namespace MApplication
|
||||
}
|
||||
}
|
||||
|
||||
private static MParser CreateParser(ITextWindow window)
|
||||
{
|
||||
return new MParser(window);
|
||||
}
|
||||
|
||||
private static SyntaxTree GetTree(string fileName)
|
||||
{
|
||||
var text = File.ReadAllText(fileName);
|
||||
var window = new TextWindowWithNull(text, fileName);
|
||||
var parser = CreateParser(window);
|
||||
var tree = parser.Parse();
|
||||
return tree;
|
||||
}
|
||||
|
||||
private static Style GetStyle()
|
||||
{
|
||||
return new Style(
|
||||
@ -57,56 +117,6 @@ namespace MApplication
|
||||
Console.Write(chunk.Text.ToString());
|
||||
}
|
||||
|
||||
private static void PrintLine(DisplayLine line)
|
||||
{
|
||||
foreach (var chunk in line.Chunks)
|
||||
{
|
||||
PrintChunk(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
static void RenderFile(string fileName)
|
||||
{
|
||||
var tree = GetTree(fileName);
|
||||
var text = CodeProcessor.GetText(tree);
|
||||
var viewPort = new DisplayTextViewPort(
|
||||
text: text,
|
||||
width: 80,
|
||||
height: 24);
|
||||
|
||||
var targetWidth = 80;
|
||||
var targetHeight = 24;
|
||||
var outputViewPort = new ConsoleWindowView(
|
||||
startingColumn: (Console.WindowWidth - targetWidth) / 2,
|
||||
startingLine: (Console.WindowHeight - targetHeight) / 2,
|
||||
width: targetWidth,
|
||||
height: targetHeight);
|
||||
|
||||
while (true)
|
||||
{
|
||||
viewPort.RenderTo(outputViewPort);
|
||||
var key = Console.ReadKey(intercept: true);
|
||||
switch (key.Key)
|
||||
{
|
||||
case ConsoleKey.LeftArrow:
|
||||
viewPort = viewPort.With(startingColumn: Math.Max(viewPort.StartingColumn - 1, 0));
|
||||
break;
|
||||
|
||||
case ConsoleKey.RightArrow:
|
||||
viewPort = viewPort.With(startingColumn: viewPort.StartingColumn + 1);
|
||||
break;
|
||||
|
||||
case ConsoleKey.UpArrow:
|
||||
viewPort = viewPort.With(startingLine: Math.Max(viewPort.StartingLine - 1, 0));
|
||||
break;
|
||||
|
||||
case ConsoleKey.DownArrow:
|
||||
viewPort = viewPort.With(startingLine: viewPort.StartingLine + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var oldStyle = GetStyle();
|
||||
@ -115,15 +125,15 @@ namespace MApplication
|
||||
"datatypes",
|
||||
"@table",
|
||||
"table.m");
|
||||
Console.CursorVisible = false;
|
||||
RenderFile(fileName);
|
||||
Console.CursorVisible = true;
|
||||
|
||||
//foreach (var line in text.Lines)
|
||||
//{
|
||||
// PrintLine(line);
|
||||
// Console.WriteLine();
|
||||
//}
|
||||
var targetWidth = 80;
|
||||
var targetHeight = 24;
|
||||
var outputViewPort = new ConsoleWindowView(
|
||||
startingColumn: (Console.WindowWidth - targetWidth) / 2,
|
||||
startingLine: (Console.WindowHeight - targetHeight) / 2,
|
||||
width: targetWidth,
|
||||
height: targetHeight);
|
||||
var renderer = new FileRenderer(outputViewPort);
|
||||
renderer.RenderFile(fileName);
|
||||
|
||||
SetStyle(oldStyle);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user