Skip to content

Commit

Permalink
Allow passing strings to stdin.
Browse files Browse the repository at this point in the history
  • Loading branch information
twitchax committed Feb 6, 2019
1 parent 66c8d9a commit 70de5bd
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 8 deletions.
8 changes: 8 additions & 0 deletions src/Core/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ internal static void CopyToStringDictionary(this IEnumerable<KeyValuePair<string
internal static Task<ICommandResult> RunCommand(
string command,
string args = null,
IEnumerable<string> standardInputs = null,
IEnumerable<Action<string>> standardOutputHandlers = null,
IEnumerable<Action<string>> standardErrorHandlers = null)
{
Expand All @@ -94,6 +95,7 @@ internal static Task<ICommandResult> RunCommand(
process.StartInfo.FileName = command;
process.StartInfo.Arguments = args;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.UseShellExecute = false;
Expand All @@ -119,8 +121,14 @@ internal static Task<ICommandResult> RunCommand(
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if(standardInputs != null)
foreach(var l in standardInputs)
process.StandardInput.WriteLine(l);
process.WaitForExit();
var exitCode = process.ExitCode;
Expand Down
16 changes: 16 additions & 0 deletions src/Core/Implementations/Executables/Executable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ public virtual TExecutable WithTimeout(TimeSpan timeout) =>
);
IExecutable IExecutable.WithTimeout(TimeSpan timeout) => WithTimeout(timeout);

/// <summary>
/// Adds a string to the standard input stream (of which there may be many) to the executable context and returns a `new` context instance.
/// </summary>
/// <param name="standardInput">A string that gets passed to the standard input stream of the executable.</param>
/// <returns>A `new` instance of type <typeparamref name="TExecutable"/> with the standard input passed to this call.</returns>
public TExecutable WithStandardInput(string standardInput) =>
new TExecutable().Initialize(
_executable,
_shell.WithStandardInput(standardInput),
_arguments,
_timeout,
_waitFuncs, _waitTimeout,
_state
);
IExecutable IExecutable.WithStandardInput(string standardInput) => WithStandardInput(standardInput);

/// <summary>
/// Adds a standard output handler (of which there may be many) to the execution context and returns a `new` context instance.
/// </summary>
Expand Down
32 changes: 25 additions & 7 deletions src/Core/Implementations/Shells/Shell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace Sheller.Implementations.Shells

private IEnumerable<KeyValuePair<string, string>> _environmentVariables;

private IEnumerable<string> _standardInputs;
private IEnumerable<Action<string>> _standardOutputHandlers;
private IEnumerable<Action<string>> _standardErrorHandlers;

Expand All @@ -47,25 +48,28 @@ namespace Sheller.Implementations.Shells
/// Initializes the shell.
/// </summary>
/// <param name="shell">The name or path of the shell.</param>
public virtual TShell Initialize(string shell) => Initialize(shell, null, null, null);
public virtual TShell Initialize(string shell) => Initialize(shell, null, null, null, null);

/// <summary>
/// Initializes the shell.
/// </summary>
/// <param name="shell">The name or path of the shell.</param>
/// <param name="environmentVariables">The environment variables to set on any executions in this shell.</param>
/// <param name="standardInputs">The standard inputs to pass to the execution.</param>
/// <param name="standardOutputHandlers">The standard output handlers for capture from the execution.</param>
/// <param name="standardErrorHandlers">The standard error handlers for capture from the execution.</param>
protected virtual TShell Initialize(
string shell,
IEnumerable<KeyValuePair<string, string>> environmentVariables,
IEnumerable<string> standardInputs,
IEnumerable<Action<string>> standardOutputHandlers,
IEnumerable<Action<string>> standardErrorHandlers)
{
_shell = shell;

_environmentVariables = environmentVariables ?? new Dictionary<string, string>();

_standardInputs = standardInputs ?? new List<string>();
_standardOutputHandlers = standardOutputHandlers ?? new List<Action<string>>();
_standardErrorHandlers = standardErrorHandlers ?? new List<Action<string>>();

Expand All @@ -87,6 +91,7 @@ public virtual async Task<ICommandResult> ExecuteCommandAsync(string executable,
var result = await Helpers.RunCommand(
command,
commandArguments,
_standardInputs,
_standardOutputHandlers,
_standardErrorHandlers);

Expand All @@ -104,7 +109,7 @@ public virtual TShell Clone() =>
new TShell().Initialize(
_shell,
_environmentVariables,
_standardOutputHandlers, _standardErrorHandlers
_standardInputs, _standardOutputHandlers, _standardErrorHandlers
);
IShell IShell.Clone() => Clone();

Expand All @@ -118,7 +123,7 @@ public virtual TShell WithEnvironmentVariable(string key, string value) =>
new TShell().Initialize(
_shell,
Helpers.MergeEnumerables(_environmentVariables, new KeyValuePair<string, string>(key, value).ToEnumerable()),
_standardOutputHandlers, _standardErrorHandlers
_standardInputs, _standardOutputHandlers, _standardErrorHandlers
);
IShell IShell.WithEnvironmentVariable(string key, string value) => WithEnvironmentVariable(key, value);

Expand All @@ -131,7 +136,7 @@ public virtual TShell WithEnvironmentVariables(IEnumerable<KeyValuePair<string,
new TShell().Initialize(
_shell,
Helpers.MergeEnumerables(_environmentVariables, variables),
_standardOutputHandlers, _standardErrorHandlers
_standardInputs, _standardOutputHandlers, _standardErrorHandlers
);
IShell IShell.WithEnvironmentVariables(IEnumerable<KeyValuePair<string, string>> variables) => WithEnvironmentVariables(variables);

Expand All @@ -144,10 +149,23 @@ public virtual TShell WithEnvironmentVariables(IEnumerable<(string, string)> var
new TShell().Initialize(
_shell,
Helpers.MergeEnumerables(_environmentVariables, variables.ToDictionary()),
_standardOutputHandlers, _standardErrorHandlers
_standardInputs, _standardOutputHandlers, _standardErrorHandlers
);
IShell IShell.WithEnvironmentVariables(IEnumerable<(string, string)> variables) => WithEnvironmentVariables(variables);

/// <summary>
/// Adds a string to the standard input stream (of which there may be many) to the shell context and returns a `new` context instance.
/// </summary>
/// <param name="standardInput">A string that gets passed to the standard input stram of the executable.</param>
/// <returns>A `new` instance of type <typeparamref name="TShell"/> with the standard input passed to this call.</returns>
public TShell WithStandardInput(string standardInput) =>
new TShell().Initialize(
_shell,
_environmentVariables,
Helpers.MergeEnumerables(_standardInputs, standardInput.ToEnumerable()), _standardOutputHandlers, _standardErrorHandlers
);
IShell IShell.WithStandardInput(string standardInput) => WithStandardInput(standardInput);

/// <summary>
/// Adds a standard output handler (of which there may be many) to the shell context and returns a `new` context instance.
/// </summary>
Expand All @@ -157,7 +175,7 @@ public virtual TShell WithStandardOutputHandler(Action<string> standardOutputHan
new TShell().Initialize(
_shell,
_environmentVariables,
Helpers.MergeEnumerables(_standardOutputHandlers, standardOutputHandler.ToEnumerable()), _standardErrorHandlers
_standardInputs, Helpers.MergeEnumerables(_standardOutputHandlers, standardOutputHandler.ToEnumerable()), _standardErrorHandlers
);
IShell IShell.WithStandardOutputHandler(Action<string> standardOutputHandler) => WithStandardOutputHandler(standardOutputHandler);

Expand All @@ -170,7 +188,7 @@ public virtual TShell WithStandardErrorHandler(Action<string> standardErrorHandl
new TShell().Initialize(
_shell,
_environmentVariables,
_standardOutputHandlers, Helpers.MergeEnumerables(_standardErrorHandlers, standardErrorHandler.ToEnumerable())
_standardInputs, _standardOutputHandlers, Helpers.MergeEnumerables(_standardErrorHandlers, standardErrorHandler.ToEnumerable())
);
IShell IShell.WithStandardErrorHandler(Action<string> standardErrorHandler) => WithStandardErrorHandler(standardErrorHandler);

Expand Down
12 changes: 12 additions & 0 deletions src/Core/Models/IExecutable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ public interface IExecutable
/// <returns>A `new` instance of type <see cref="IExecutable"/> with the timeout set to the value passed to this call.</returns>
IExecutable WithTimeout(TimeSpan timeout);

/// <summary>
/// Adds a string to the standard input stream (of which there may be many) to the executable context and returns a `new` context instance.
/// </summary>
/// <param name="standardInput">A string that gets passed to the standard input stream of the executable.</param>
/// <returns>A `new` instance of type <see cref="IExecutable"/> with the standard input passed to this call.</returns>
IExecutable WithStandardInput(string standardInput);
/// <summary>
/// Adds a standard output handler (of which there may be many) to the execution context and returns a `new` context instance.
/// </summary>
Expand Down Expand Up @@ -101,6 +107,12 @@ public interface IExecutable<out TExecutable> : IExecutable where TExecutable :
/// <returns>A `new` instance of <typeparamref name="TExecutable"/> with the timeout set to the value passed to this call.</returns>
new TExecutable WithTimeout(TimeSpan timeout);

/// <summary>
/// Adds a string to the standard input stream (of which there may be many) to the executable context and returns a `new` context instance.
/// </summary>
/// <param name="standardInput">A string that gets passed to the standard input stream of the executable.</param>
/// <returns>A `new` instance of type <typeparamref name="TExecutable"/> with the standard input passed to this call.</returns>
new TExecutable WithStandardInput(string standardInput);
/// <summary>
/// Adds a standard output handler (of which there may be many) to the execution context and returns a `new` context instance.
/// </summary>
Expand Down
12 changes: 12 additions & 0 deletions src/Core/Models/IShell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ public interface IShell
/// <returns>A `new` instance of type <see cref="IShell"/> with the environment variables passed in this call.</returns>
IShell WithEnvironmentVariables(IEnumerable<(string, string)> variables);

/// <summary>
/// Adds a string to the standard input stream (of which there may be many) to the shell context and returns a `new` context instance.
/// </summary>
/// <param name="standardInput">A string that gets passed to the standard input stream of the executable.</param>
/// <returns>A `new` instance of type <see cref="IShell"/> with the standard input passed to this call.</returns>
IShell WithStandardInput(string standardInput);
/// <summary>
/// Adds a standard output handler (of which there may be many) to the shell context and returns a `new` context instance.
/// </summary>
Expand Down Expand Up @@ -110,6 +116,12 @@ public interface IShell<out TShell> : IShell where TShell : IShell<TShell>
/// <returns>A `new` instance of <typeparamref name="TShell"/> with the environment variables passed in this call.</returns>
new TShell WithEnvironmentVariables(IEnumerable<(string, string)> variables);

/// <summary>
/// Adds a string to the standard input stream (of which there may be many) to the shell context and returns a `new` context instance.
/// </summary>
/// <param name="standardInput">A string that gets passed to the standard input stream of the executable.</param>
/// <returns>A `new` instance of type <typeparamref name="TShell"/> with the standard input passed to this call.</returns>
new TShell WithStandardInput(string standardInput);
/// <summary>
/// Adds a standard output handler (of which there may be many) to the shell context and returns a `new` context instance.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Sheller.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<IsTestProject>false</IsTestProject>
<TargetFramework>netstandard2.0</TargetFramework>

<Version>3.3.0</Version>
<Version>3.4.0</Version>
<AssemblyName>Sheller</AssemblyName>
<PackageId>Sheller</PackageId>
<PackageProjectUrl>https://github.com/twitchax/sheller</PackageProjectUrl>
Expand Down
17 changes: 17 additions & 0 deletions src/Test/BasicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,23 @@ public async void CanExecuteEchoWithStandardErrorHandler()
Assert.Equal(expected, handlerString.ToString());
}

[Fact]
[Trait("os", "nix_win")]
public async void CanExecuteEchoWithStandardInput()
{
var expected1 = "lol";
var expected2 = "face";

var echoResult = await Sheller
.Shell<Bash>()
.UseExecutable("read var1; read var2; echo $var1$var2")
.WithStandardInput(expected1)
.WithStandardInput(expected2)
.ExecuteAsync();

Assert.Equal($"{expected1}{expected2}", echoResult.StandardOutput.Trim());
}

[Fact]
[Trait("os", "nix_win")]
public async void CanExecuteEchoWithResultSelector()
Expand Down

0 comments on commit 70de5bd

Please sign in to comment.