public static void WriteReverse(string text, bool reverse) { if (reverse) { if (Runtime.HasFeature("ansi-terminal")) { Console.Write("\x1b[7m"); Console.Write(text); Console.Write("\x1b[27m"); } else { Console.Write("["); Console.Write(text); Console.Write("]"); } } else { Console.Write(text); } }
public static string ReplReadImp(string prompt, bool lispCompletion, bool symbolCompletion, bool crlf) { //ReplReadTest(); var top = Console.CursorTop; var left = Console.CursorLeft; var pos = 0; var buffer = new StringBuilder(); var col = 0; var row = 0; var scrolled = 0; Action <char> writeChar = (char ch) => { var r1 = Console.CursorTop; var c1 = Console.CursorLeft; Console.Write(ch); var r2 = Console.CursorTop; var c2 = Console.CursorLeft; if (r1 == Console.BufferHeight - 1) { // on last row if (c2 == 0) { ++scrolled; --top; --row; } } }; Action <string> writeStr = (string str) => { foreach (var ch in str) { writeChar(ch); } }; Action cursorReset = () => { Console.SetCursorPosition(left, top); row = top; col = left; }; Action paint = () => { // // update display // cursorReset(); if (prompt != null) { writeStr(prompt); row = Console.CursorTop; col = Console.CursorLeft; } for (var i = 0; i < buffer.Length; ++i) { writeChar(buffer[i]); if (i + 1 == pos) { row = Console.CursorTop; col = Console.CursorLeft; } } writeChar(' '); }; Action erase = () => { if (Runtime.HasFeature("ansi-terminal")) { Console.Write("\x1b[J"); } else { var start = Console.CursorLeft + Console.CursorTop * Console.BufferWidth; var end = (Console.WindowTop + Console.WindowHeight) * Console.BufferWidth - 1; if (start < end) { var blanks = new String(' ', end - start); Console.Write(blanks); } } }; Action setupNewPromptLocation = () => { top = Console.CursorTop; left = Console.CursorLeft; col = 0; row = 0; scrolled = 0; }; while (true) { paint(); erase(); // // get next key // ConsoleKeyInfo keyInfo; ConsoleKey key; ConsoleModifiers mod; char ch; Console.SetCursorPosition(col, row); keyInfo = ReplReadKey(); key = keyInfo.Key; mod = keyInfo.Modifiers; ch = keyInfo.KeyChar; switch (key) { case ConsoleKey.Backspace: { if (pos > 0) { --pos; buffer.Remove(pos, 1); } break; } case ConsoleKey.Delete: { if (pos < buffer.Length) { buffer.Remove(pos, 1); } break; } case ConsoleKey.Enter: { var s = buffer.ToString(); if (!lispCompletion || (mod != ConsoleModifiers.Control && IsCompleteSourceCode(s))) { pos = buffer.Length; paint(); if (crlf) { writeChar('\n'); } return(s); } else { writeChar('\n'); buffer.Append('\n'); ++pos; } break; } case ConsoleKey.Home: { pos = 0; break; } case ConsoleKey.End: { pos = buffer.Length; break; } case ConsoleKey.LeftArrow: { if (pos > 0) { --pos; } break; } case ConsoleKey.RightArrow: { if (pos < buffer.Length) { ++pos; } break; } case ConsoleKey.UpArrow: { if (History != null) { var s = History.Previous(); buffer = new StringBuilder(s); pos = buffer.Length; } break; } case ConsoleKey.DownArrow: { if (History != null) { var s = History.Next(); buffer = new StringBuilder(s); pos = buffer.Length; } break; } case ConsoleKey.Escape: { cursorReset(); erase(); cursorReset(); return(null); } case ConsoleKey.Tab: { if (!symbolCompletion) { break; } var line = buffer.ToString(); var loc = Runtime.LocateWord(line, pos, false); var prefix = line.Substring(0, loc.Begin); var searchTerm = line.Substring(loc.Begin, loc.Span); var suffix = line.Substring(loc.Begin + loc.Span); var completions = GetCompletions(searchTerm); var common = FindLongestCommonStringLength(completions); if (common > loc.Span) { // add extra common characters searchTerm = completions[0].Substring(0, common); buffer = new StringBuilder(); buffer.Append(prefix); buffer.Append(searchTerm); pos = buffer.Length; buffer.Append(suffix); } else { // show all options and a new prompt var width = -1; for (var i = 0; i < completions.Count; ++i) { width = Math.Max(width, 1 + completions[i].Length); } var cols = Math.Max(1, Console.BufferWidth / width); Console.WriteLine(); Runtime.PrintMultiColumn(GetConsoleOut(), cols, width, completions); setupNewPromptLocation(); } break; } default: { if (mod == ConsoleModifiers.Control) { switch (key) { case ConsoleKey.V: var text = Runtime.GetClipboardData(); foreach (var ch2 in text) { var ch3 = (ch2 == '\n' || ch2 >= ' ') ? ch2 : ' '; buffer.Insert(pos, ch3); ++pos; } break; case ConsoleKey.U: var text3 = buffer.ToString(0, pos); buffer.Remove(0, pos); pos = 0; break; case ConsoleKey.K: var text4 = buffer.ToString(pos, buffer.Length - pos); buffer.Remove(pos, buffer.Length - pos); break; case ConsoleKey.W: var line = buffer.ToString(); var loc = Runtime.LocateWord(line, pos, true); var text5 = buffer.ToString(loc.Begin, pos - loc.Begin); buffer.Remove(loc.Begin, pos - loc.Begin); pos = loc.Begin; break; } } else if (ch == '\n') { var s = buffer.ToString(); if (mod != ConsoleModifiers.Control && IsCompleteSourceCode(s)) { pos = buffer.Length; paint(); if (crlf) { writeChar('\n'); } return(s); } else { writeChar('\n'); buffer.Append('\n'); ++pos; } } else if (ch >= ' ') { buffer.Insert(pos, ch); ++pos; } break; } } } }