How to set default input value in .Net Console App?
I went ahead and completed Matt's implementation approach:
public static string ReadInputWithDefault(string defaultValue, string caret = "> ")
{
Console.WriteLine(); // make sure we're on a fresh line
List<char> buffer = defaultValue.ToCharArray().Take(Console.WindowWidth - caret.Length - 1).ToList();
Console.Write(caret);
Console.Write(buffer.ToArray());
Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop);
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
while (keyInfo.Key != ConsoleKey.Enter)
{
switch (keyInfo.Key)
{
case ConsoleKey.LeftArrow:
Console.SetCursorPosition(Math.Max(Console.CursorLeft - 1, caret.Length), Console.CursorTop);
break;
case ConsoleKey.RightArrow:
Console.SetCursorPosition(Math.Min(Console.CursorLeft + 1, caret.Length + buffer.Count), Console.CursorTop);
break;
case ConsoleKey.Home:
Console.SetCursorPosition(caret.Length, Console.CursorTop);
break;
case ConsoleKey.End:
Console.SetCursorPosition(caret.Length + buffer.Count, Console.CursorTop);
break;
case ConsoleKey.Backspace:
if (Console.CursorLeft <= caret.Length)
{
break;
}
var cursorColumnAfterBackspace = Math.Max(Console.CursorLeft - 1, caret.Length);
buffer.RemoveAt(Console.CursorLeft - caret.Length - 1);
RewriteLine(caret, buffer);
Console.SetCursorPosition(cursorColumnAfterBackspace, Console.CursorTop);
break;
case ConsoleKey.Delete:
if (Console.CursorLeft >= caret.Length + buffer.Count)
{
break;
}
var cursorColumnAfterDelete = Console.CursorLeft;
buffer.RemoveAt(Console.CursorLeft - caret.Length);
RewriteLine(caret, buffer);
Console.SetCursorPosition(cursorColumnAfterDelete, Console.CursorTop);
break;
default:
var character = keyInfo.KeyChar;
if (character < 32) // not a printable chars
break;
var cursorAfterNewChar = Console.CursorLeft + 1;
if (cursorAfterNewChar > Console.WindowWidth || caret.Length + buffer.Count >= Console.WindowWidth - 1)
{
break; // currently only one line of input is supported
}
buffer.Insert(Console.CursorLeft - caret.Length, character);
RewriteLine(caret, buffer);
Console.SetCursorPosition(cursorAfterNewChar, Console.CursorTop);
break;
}
keyInfo = Console.ReadKey(true);
}
Console.Write(Environment.NewLine);
return new string(buffer.ToArray());
}
private static void RewriteLine(string caret, List<char> buffer)
{
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(new string(' ', Console.WindowWidth - 1));
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(caret);
Console.Write(buffer.ToArray());
}
Notes:
- Works for only one line of input
- You can define what stands before the editable text area (
caret
parameter) - Use at your own risk, there may still be some IndexOutOfBound-problems. ;)
I believe that you will have manage this manually by listening to each key press:
Quickly thown together example:
// write the initial buffer
char[] buffer = "Initial text".ToCharArray();
Console.WriteLine(buffer);
// ensure the cursor starts off on the line of the text by moving it up one line
Console.SetCursorPosition(Console.CursorLeft + buffer.Length, Console.CursorTop - 1);
// process the key presses in a loop until the user presses enter
// (this might need to be a bit more sophisticated - what about escape?)
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
while (keyInfo.Key != ConsoleKey.Enter)
{
switch (keyInfo.Key)
{
case ConsoleKey.LeftArrow:
...
// process the left key by moving the cursor position
// need to keep track of the position in the buffer
// if the user presses another key then update the text in our buffer
// and draw the character on the screen
// there are lots of cases that would need to be processed (backspace, delete etc)
}
keyInfo = Console.ReadKey(true);
}
This is quite involved - you'll have to keep ensure the cursor doesn't go out of range and manually update your buffer.
Here's a simple solution:
public static string ConsoleReadLineWithDefault(string defaultValue)
{
System.Windows.Forms.SendKeys.SendWait(defaultValue);
return Console.ReadLine();
}
It's not complete however. Some characters in the SendWait input string have special meaning so you have to escape them (eg. +, (, ), etc.) See: http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx for a complete description.