forked from DigitalRuby/ExchangeSharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathInteractiveOption.cs
128 lines (104 loc) · 2.68 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
121
122
123
124
125
126
127
128
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; } = {' ', '.', '/', '\"', '\''};
}
}
}