-
-
Notifications
You must be signed in to change notification settings - Fork 373
/
InteractiveOption.cs
120 lines (96 loc) · 2.65 KB
/
InteractiveOption.cs
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using CommandLine;
namespace ExchangeSharpConsole.Options
{
[Verb("interactive", HelpText = "Enables an interactive session.")]
public class InteractiveOption : BaseOption
{
internal static readonly string HistoryFilePath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
".exchange-sharp-history"
);
/// <summary>
/// UTF-8 No BOM
/// </summary>
internal static readonly Encoding HistoryFileEncoding = new UTF8Encoding(false, true);
internal const int HistoryMax = 100;
public override async Task RunCommand()
{
ReadLine.HistoryEnabled = true;
ReadLine.AutoCompletionHandler = new AutoCompleter();
Console.TreatControlCAsInput = true;
var program = Program.Instance;
LoadHistory();
try
{
await RunInteractiveSession(program);
Console.WriteLine();
}
finally
{
SaveHistory();
}
}
private void LoadHistory()
{
if (!File.Exists(HistoryFilePath))
return;
var lines = File.ReadLines(HistoryFilePath, HistoryFileEncoding)
.TakeLast(HistoryMax)
.ToArray();
ReadLine.AddHistory(lines);
}
private void SaveHistory()
{
var lines = ReadLine.GetHistory().TakeLast(HistoryMax).ToArray();
using var sw = File.CreateText(HistoryFilePath);
foreach (var line in lines)
{
sw.WriteLine(line);
}
}
private static async Task RunInteractiveSession(Program program)
{
while (true)
{
var command = ReadLine.Read("ExchangeSharp> ", "help");
if (command.Equals("exit", StringComparison.OrdinalIgnoreCase))
break;
var (error, help) = program.ParseArguments(command.Split(' '), out var options);
if (error || help)
continue;
await program.Run(options, exitOnError: false);
}
}
public class AutoCompleter : IAutoCompleteHandler
{
private readonly string[] options;
public AutoCompleter()
{
var optionsList = Program.Instance.CommandOptions
.Where(t => typeof(InteractiveOption) != t)
.Select(t => t.GetCustomAttribute<VerbAttribute>(true))
.Where(v => !v.Hidden)
.Select(v => v.Name)
.ToList();
optionsList.Add("help");
optionsList.Add("exit");
options = optionsList.OrderBy(o => o).ToArray();
}
public string[] GetSuggestions(string text, int index)
{
if (string.IsNullOrWhiteSpace(text))
return options;
return options
.Where(o => o.StartsWith(text, StringComparison.OrdinalIgnoreCase))
.ToArray();
}
public char[] Separators { get; set; } = { ' ', '.', '/', '\"', '\'' };
}
}
}