Skip to content

Commit

Permalink
ensure lineout does not mix stderr and stdout (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mpdreamz authored Jan 6, 2024
1 parent f9283ad commit 60cc61a
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 40 deletions.
11 changes: 5 additions & 6 deletions src/Proc/BufferedObservableProcess.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading;
Expand All @@ -16,9 +17,7 @@ namespace ProcNet
///
/// This catches all cases where <see cref="EventBasedObservableProcess"/> would fall short to capture all the process output.
///
#pragma warning disable 1574
/// <see cref="CharactersOut"/> contains the current char[] buffer which could be fed to <see cref="Console.Write"/> directly.
#pragma warning restore 1574
/// <see cref="CharactersOut"/> contains the current char[] buffer which could be fed to <see cref="Console.Write(string,object)"/> directly.
///
/// Note that there is a subclass <use cref="ObservableProcess"/> that allows you to subscribe console output per line
/// instead whilst still reading the actual process output using asynchronous stream readers.
Expand All @@ -36,11 +35,11 @@ public BufferedObservableProcess(StartArguments startArguments) : base(startArgu
private TimeSpan? WaitForStreamReadersTimeout => StartArguments.WaitForStreamReadersTimeout;

/// <summary>
/// Expert level setting: the maximum number of characters to read per itteration. Defaults to 256
/// Expert level setting: the maximum number of characters to read per iteration. Defaults to 1024
/// </summary>
public int BufferSize { get; set; } = 256;
public int BufferSize { get; set; } = 1024;

private CancellationTokenSource _ctx = new CancellationTokenSource();
private CancellationTokenSource _ctx = new();
private Task _stdOutSubscription;
private Task _stdErrSubscription;
private IObserver<CharactersOut> _observer;
Expand Down
23 changes: 19 additions & 4 deletions src/Proc/ObservableProcess.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -89,11 +90,25 @@ public IDisposable Subscribe(IObserver<LineOut> observerLines, IObserver<Charact
.Where(o => o.EndsWithNewLine || o.StartsWithCarriage || BufferBoundary(_bufferStdOutRemainder, _bufferStdErrRemainder));
var buffered = published.Buffer(boundaries);
var newlines = buffered
.Select(c =>
.SelectMany(c =>
{
if (c.Count == 0) return null;
var line = new string(c.SelectMany(o => o.Characters).ToArray());
return new LineOut(c.First().Error, line.TrimEnd(NewlineChars));
if (c == null || c.Count == 0)
return Array.Empty<LineOut>();
if (c.Count == 1)
{
var cOut = c.First();
var chars = new string(cOut.Characters).TrimEnd(NewlineChars);
return new[] { new LineOut(cOut.Error, chars) };
}
return c
.GroupBy(l => l.Error)
.Select(g => (g.Key, new string(g.SelectMany(o => o.Characters).ToArray())))
.SelectMany(kv =>
kv.Item2.TrimEnd(NewlineChars).Split(NewlineChars)
.Select(line => new LineOut(kv.Key, line.TrimEnd(NewlineChars)))
)
.ToArray();
})
.TakeWhile(KeepBufferingLines)
.Where(l => l != null)
Expand Down
5 changes: 4 additions & 1 deletion src/Proc/Proc.Start.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ public static ProcessCaptureResult Start(StartArguments arguments, TimeSpan time
var consoleOut = new List<LineOut>();
composite.Add(process);
composite.Add(process.SubscribeLinesAndCharacters(
consoleOut.Add,
l =>
{
consoleOut.Add(l);
},
e => seenException = e,
consoleOutWriter.Write,
consoleOutWriter.Write
Expand Down
57 changes: 28 additions & 29 deletions src/Proc/Std/ConsoleOutColorWriter.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,43 @@
using System;

namespace ProcNet.Std
namespace ProcNet.Std;

public class ConsoleOutColorWriter : ConsoleOutWriter
{
public class ConsoleOutColorWriter : ConsoleOutWriter
{
public static ConsoleOutColorWriter Default { get; } = new ConsoleOutColorWriter();
public static ConsoleOutColorWriter Default { get; } = new();

private readonly object _lock = new object();
public override void Write(ConsoleOut consoleOut)
private readonly object _lock = new();
public override void Write(ConsoleOut consoleOut)
{
lock (_lock)
{
lock (_lock)
Console.ResetColor();
if (consoleOut.Error)
{
if (consoleOut.Error)
{
Console.ForegroundColor = ConsoleColor.Red;
consoleOut.CharsOrString(ErrorCharacters, ErrorLine);
}
else
{
Console.ResetColor();
consoleOut.CharsOrString(OutCharacters, OutLine);
}
Console.ResetColor();
Console.ForegroundColor = ConsoleColor.Yellow;
consoleOut.CharsOrString(ErrorCharacters, ErrorLine);
}
else
consoleOut.CharsOrString(OutCharacters, OutLine);

Console.ResetColor();
}
}

public override void Write(Exception e)
public override void Write(Exception e)
{
if (!(e is CleanExitExceptionBase ee)) throw e;
lock (_lock)
{
if (!(e is CleanExitExceptionBase ee)) throw e;
lock (_lock)
Console.ResetColor();
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(e.Message);
if (!string.IsNullOrEmpty(ee.HelpText))
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(e.Message);
if (!string.IsNullOrEmpty(ee.HelpText))
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.Write(ee.HelpText);
}
Console.ResetColor();
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.Write(ee.HelpText);
}
Console.ResetColor();
}
}
}

0 comments on commit 60cc61a

Please sign in to comment.