Code
·
74 lines
·
3157 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using System.Security.Cryptography;
using System.Text;
using LineFormatter = System.Func<InteractiveReadLine.LineState, InteractiveReadLine.Formatting.LineDisplayState>;
using TokenFormatter = System.Func<InteractiveReadLine.Tokenizing.TokenizedLine, InteractiveReadLine.Formatting.LineDisplayState>;
#nullable disable
namespace InteractiveReadLine.Formatting
{
public static class CommonFormatters
{
/// <summary>
/// Provides a formatter that displays a fixed prompt in front of the input line, or wraps another
/// formatter overwriting its prefix with the supplied prompt
/// </summary>
/// <param name="prompt">the prompt text to display</param>
/// <param name="formatter"></param>
public static LineFormatter FixedPrompt(FormattedText prompt, LineFormatter formatter = null)
{
return state =>
{
if (formatter == null)
return new LineDisplayState(prompt, state.Text, string.Empty, state.Cursor);
var result = formatter.Invoke(state);
return new LineDisplayState(prompt, result.LineBody, result.Suffix, result.Cursor);
};
}
/// <summary>
/// A formatter that blanks out the entered characters, and has no prefix or suffix
/// </summary>
public static LineFormatter PasswordBlank =>
state => new LineDisplayState(string.Empty, string.Empty, string.Empty, 0);
/// <summary>
/// A formatter that puts out a variable length bar based on the 1st and 10th bytes in a SHA256 hash
/// of the entered password. Provides repeatable visual feedback without revealing anything about the
/// password itself
/// </summary>
public static LineFormatter PasswordBar =>
state =>
{
var hash = SHA256.Create();
var result = hash.ComputeHash(Encoding.ASCII.GetBytes(state.Text));
var l1 = (int) Math.Round(20.0 * result[0] / 255.0);
var l2 = (int) Math.Round(20.0 * result[10] / 255.0);
var builder = new StringBuilder("[");
for (var i = 0; i < 20; i++)
if (i < l1 && i < l2 || i > l1 && i > l2)
builder.Append(' ');
else
builder.Append('=');
builder.Append(']');
return new LineDisplayState(string.Empty, builder.ToString(), string.Empty, builder.Length);
};
/// <summary>
/// A formatter that converts the password characters to stars
/// </summary>
public static LineFormatter PasswordStars =>
state => new LineDisplayState(string.Empty, new string('*', state.Text.Length), string.Empty, state.Cursor);
/// <summary>
/// Adds a fixed prompt to the given formatter, overwriting the prefix
/// </summary>
public static LineFormatter WithFixedPrompt(this LineFormatter formatter, FormattedText prompt) => FixedPrompt(prompt, formatter);
}
}