Skip to content

Commit c50d98c

Browse files
committed
Abstract out ProcessStreamPluginV2.cs and add ExecutablePluginV2.cs
1 parent e1deefc commit c50d98c

File tree

4 files changed

+107
-60
lines changed

4 files changed

+107
-60
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.Diagnostics;
2+
using System.IO;
3+
using System.Text.Json;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
7+
namespace Flow.Launcher.Core.Plugin
8+
{
9+
internal sealed class ExecutablePluginV2 : ProcessStreamPluginV2
10+
{
11+
protected override ProcessStartInfo StartInfo { get; set; }
12+
13+
public ExecutablePluginV2(string filename)
14+
{
15+
StartInfo = new ProcessStartInfo
16+
{
17+
FileName = filename,
18+
UseShellExecute = false,
19+
CreateNoWindow = true,
20+
RedirectStandardOutput = true,
21+
RedirectStandardError = true
22+
};
23+
}
24+
25+
}
26+
}

Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
using System.Threading.Tasks;
77
using Flow.Launcher.Core.Plugin.JsonRPCV2Models;
88
using Flow.Launcher.Plugin;
9+
using Microsoft.VisualStudio.Threading;
910
using StreamJsonRpc;
11+
using IAsyncDisposable = System.IAsyncDisposable;
1012

1113

1214
namespace Flow.Launcher.Core.Plugin
@@ -39,6 +41,11 @@ protected override async Task<bool> ExecuteResultAsync(JsonRPCResult result)
3941
}
4042
}
4143

44+
public override List<Result> LoadContextMenus(Result selectedResult)
45+
{
46+
throw new NotImplementedException();
47+
}
48+
4249
public override async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
4350
{
4451
try
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.IO.Pipelines;
5+
using System.Threading.Tasks;
6+
using Flow.Launcher.Infrastructure;
7+
using Flow.Launcher.Plugin;
8+
using Nerdbank.Streams;
9+
10+
namespace Flow.Launcher.Core.Plugin
11+
{
12+
internal abstract class ProcessStreamPluginV2 : JsonRPCPluginV2
13+
{
14+
15+
public override string SupportedLanguage { get; set; }
16+
protected override IDuplexPipe ClientPipe { get; set; }
17+
18+
protected abstract ProcessStartInfo StartInfo { get; set; }
19+
20+
public Process ClientProcess { get; set; }
21+
22+
public override async Task InitAsync(PluginInitContext context)
23+
{
24+
StartInfo.EnvironmentVariables["FLOW_VERSION"] = Constant.Version;
25+
StartInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory;
26+
StartInfo.EnvironmentVariables["FLOW_APPLICATION_DIRECTORY"] = Constant.ApplicationDirectory;
27+
28+
StartInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath);
29+
StartInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory;
30+
31+
ClientProcess = Process.Start(StartInfo);
32+
ArgumentNullException.ThrowIfNull(ClientProcess);
33+
34+
SetupPipe(ClientProcess);
35+
36+
await base.InitAsync(context);
37+
}
38+
39+
private void SetupPipe(Process process)
40+
{
41+
var (reader, writer) = (PipeReader.Create(process.StandardOutput.BaseStream),
42+
PipeWriter.Create(process.StandardInput.BaseStream));
43+
ClientPipe = new DuplexPipe(reader, writer);
44+
}
45+
46+
47+
public override async Task ReloadDataAsync()
48+
{
49+
var oldProcess = ClientProcess;
50+
ClientProcess = Process.Start(StartInfo);
51+
ArgumentNullException.ThrowIfNull(ClientProcess);
52+
SetupPipe(ClientProcess);
53+
await base.ReloadDataAsync();
54+
oldProcess.Kill(true);
55+
await oldProcess.WaitForExitAsync();
56+
oldProcess.Dispose();
57+
}
58+
59+
60+
public override async ValueTask DisposeAsync()
61+
{
62+
ClientProcess.Kill(true);
63+
await ClientProcess.WaitForExitAsync();
64+
ClientProcess.Dispose();
65+
await base.DisposeAsync();
66+
}
67+
}
68+
}

Flow.Launcher.Core/Plugin/PythonPluginV2.cs

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,16 @@
1616

1717
namespace Flow.Launcher.Core.Plugin
1818
{
19-
internal class PythonPluginV2 : JsonRPCPluginV2
19+
internal sealed class PythonPluginV2 : ProcessStreamPluginV2
2020
{
21-
private readonly ProcessStartInfo _startInfo;
22-
private Process _process;
23-
2421
public override string SupportedLanguage { get; set; } = AllowedLanguage.Python;
2522

2623
protected override IDuplexPipe ClientPipe { get; set; }
27-
28-
24+
protected override ProcessStartInfo StartInfo { get; set; }
25+
2926
public PythonPluginV2(string filename)
3027
{
31-
_startInfo = new ProcessStartInfo
28+
StartInfo = new ProcessStartInfo
3229
{
3330
FileName = filename,
3431
UseShellExecute = false,
@@ -40,61 +37,10 @@ public PythonPluginV2(string filename)
4037

4138
// temp fix for issue #667
4239
var path = Path.Combine(Constant.ProgramDirectory, JsonRpc);
43-
_startInfo.EnvironmentVariables["PYTHONPATH"] = path;
44-
45-
_startInfo.EnvironmentVariables["FLOW_VERSION"] = Constant.Version;
46-
_startInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory;
47-
_startInfo.EnvironmentVariables["FLOW_APPLICATION_DIRECTORY"] = Constant.ApplicationDirectory;
48-
40+
StartInfo.EnvironmentVariables["PYTHONPATH"] = path;
4941

5042
//Add -B flag to tell python don't write .py[co] files. Because .pyc contains location infos which will prevent python portable
51-
_startInfo.ArgumentList.Add("-B");
52-
}
53-
54-
55-
public override List<Result> LoadContextMenus(Result selectedResult)
56-
{
57-
throw new NotImplementedException();
58-
}
59-
60-
public override async Task InitAsync(PluginInitContext context)
61-
{
62-
_startInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath);
63-
_startInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory;
64-
65-
_process = Process.Start(_startInfo);
66-
ArgumentNullException.ThrowIfNull(_process);
67-
68-
SetupPipe(_process);
69-
70-
await base.InitAsync(context);
71-
}
72-
73-
public override async ValueTask DisposeAsync()
74-
{
75-
_process.Kill(true);
76-
await _process.WaitForExitAsync();
77-
_process.Dispose();
78-
await base.DisposeAsync();
79-
}
80-
81-
private void SetupPipe(Process process)
82-
{
83-
var (reader, writer) = (PipeReader.Create(process.StandardOutput.BaseStream),
84-
PipeWriter.Create(process.StandardInput.BaseStream));
85-
ClientPipe = new DuplexPipe(reader, writer);
86-
}
87-
88-
public override async Task ReloadDataAsync()
89-
{
90-
var oldProcess = _process;
91-
_process = Process.Start(_startInfo);
92-
ArgumentNullException.ThrowIfNull(_process);
93-
SetupPipe(_process);
94-
await base.ReloadDataAsync();
95-
oldProcess.Kill(true);
96-
await oldProcess.WaitForExitAsync();
97-
oldProcess.Dispose();
43+
StartInfo.ArgumentList.Add("-B");
9844
}
9945
}
10046
}

0 commit comments

Comments
 (0)