/
Program.cs
138 lines (119 loc) · 4.93 KB
/
Program.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
129
130
131
132
133
134
135
136
137
138
using ConsoleAppFramework;
using Csi3.Build;
using Csi3.Contexts;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Csi3
{
class Program : ConsoleAppBase
{
static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder()
.ConfigureLogging(logging =>
{
logging.ReplaceToSimpleConsole();
logging.SetMinimumLevel(LogLevel.Debug);
})
.RunConsoleAppFrameworkAsync<Program>(args);
}
[Command("program")]
public async Task<int> ExecuteProgramAsync(
[Option("d", "enable debug")] bool debug = false,
[Option("e", "source code encoding")] string encoding = "utf-8",
[Option("i", "source code include paths")] string[] includes = null,
[Option("l", "library assembly paths")] string[] libraries = null,
[Option("w", "watch file updates")] bool watch = false
)
=> await ExecuteImplAsync(SourceCodeKind.Regular, debug, encoding, includes, libraries, watch);
[Command("script")]
public async Task<int> ExecuteScriptAsync(
[Option("d", "enable debug")] bool debug = false,
[Option("e", "source code encoding")] string encoding = "utf-8",
[Option("i", "source code include paths")] string[] includes = null,
[Option("l", "library assembly paths")] string[] libraries = null,
[Option("w", "watch file updates")] bool watch = false
)
=> await ExecuteImplAsync(SourceCodeKind.Script, debug, encoding, includes, libraries, watch);
private async Task<int> ExecuteImplAsync(SourceCodeKind kind, bool debug, string encoding, string[] includes, string[] libraries, bool watch)
{
var logger = Context.Logger;
var argsSplitterIndex = Array.IndexOf(Context.Arguments ?? Array.Empty<string>(), "--");
var scriptPath = default(string);
var args = Array.Empty<string>();
if (argsSplitterIndex < 0)
{
scriptPath = Context.Arguments.LastOrDefault();
}
else if (argsSplitterIndex > 0)
{
scriptPath = Context.Arguments[argsSplitterIndex - 1];
args = Context.Arguments.Skip(argsSplitterIndex + 1).ToArray();
}
if (string.IsNullOrEmpty(scriptPath))
{
logger.LogError("no script file is specified.");
return 1;
}
if (!File.Exists(scriptPath))
{
logger.LogError($"{scriptPath} is not found");
return 1;
}
var options = new BuildOptions()
{
SourceCodeKind = kind,
EnableDebug = debug,
Encoding = Encoding.GetEncoding(encoding),
LoadPaths = includes ?? Array.Empty<string>(),
ReferencePaths = libraries ?? Array.Empty<string>(),
WorkingDirectory = Environment.CurrentDirectory,
SourceFilesMayBeLocked = watch,
};
var builder = new Builder(options, logger);
if (watch)
{
using (var watcher = new FileWather())
{
Task waitForUnloadTask = null;
while (!Context.CancellationToken.IsCancellationRequested)
{
watcher.Stop();
watcher.Clear();
using (var executer = await builder.BuildAsync(scriptPath))
{
if (executer != null)
{
waitForUnloadTask?.Wait();
var awaiter = await executer.ExecuteAsync(args);
waitForUnloadTask = awaiter.WaitForUnloadAsync(Context.CancellationToken);
}
}
watcher.AddFiles(builder.SourceCodePaths);
watcher.Start();
Console.WriteLine();
Console.WriteLine("waiting for source codes edit...");
Console.WriteLine();
watcher.WaitForChanged(Context.CancellationToken);
}
waitForUnloadTask?.Wait();
}
}
else
{
var executer = await builder.BuildAsync(scriptPath);
var awaiter = await executer.ExecuteAsync(args);
awaiter.WaitForUnload();
}
return 0;
}
}
}