Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions Terminal.Gui/Drivers/AnsiDriver/AnsiOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,20 @@ public AnsiOutput (AppModel appModel = AppModel.FullScreen)
}
else if (PlatformDetection.IsUnixLike ())
{
// duplicate stdout so we don't mess with Console.Out's FD
int fdCopy = UnixIOHelper.dup (UnixIOHelper.STDOUT_FILENO);
// duplicate the controlling terminal output fd so we don't mess with it.
// When stdout is redirected this is /dev/tty rather than STDOUT_FILENO,
// allowing TUI rendering to appear on the real terminal even when the
// app's stdout participates in a shell pipeline.
int outputFd = TerminalDevice.OutputFd;

if (outputFd < 0)
{
Trace.Lifecycle (nameof (AnsiOutput), "Init", "Console output stream is not writable. Running in degraded mode.");

return;
}

int fdCopy = UnixIOHelper.dup (outputFd);

if (fdCopy == -1)
{
Expand Down
38 changes: 20 additions & 18 deletions Terminal.Gui/Drivers/Driver.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Runtime.InteropServices;

namespace Terminal.Gui.Drivers;
namespace Terminal.Gui.Drivers;

/// <summary>
/// Holds global driver settings and cross-driver utility methods.
Expand Down Expand Up @@ -45,18 +43,27 @@ public static bool Force16Colors
public static SizeDetectionMode SizeDetection { get; set; } = SizeDetectionMode.AnsiQuery;

/// <summary>
/// Determines whether the process is attached to a real terminal (i.e. stdin/stdout
/// are connected to a console device rather than redirected or running inside a test harness). Set the environment
/// variable "DisableRealDriverIO=1" to skip real terminal detection and force this method to return false, which is
/// required for running in test harnesses that do not have a real terminal attached.
/// Determines whether the process has a controlling terminal usable for TUI rendering and input.
/// Returns <see langword="true"/> when either:
/// <list type="bullet">
/// <item>stdin/stdout are connected to a console device, or</item>
/// <item>
/// stdin/stdout are redirected (e.g. via a shell pipeline such as
/// <c>result=$(myapp)</c> or <c>myapp | jq</c>) but a controlling terminal is available
/// via <c>/dev/tty</c> on Unix or <c>CONIN$</c>/<c>CONOUT$</c> on Windows.
/// </item>
/// </list>
/// Set the environment variable <c>DisableRealDriverIO=1</c> to skip real terminal detection and
/// force this method to return false, which is required for running in test harnesses that do not
/// have a real terminal attached.
/// </summary>
/// <param name="inputAttached">
/// When this method returns, <see langword="true"/> if standard input is connected to a console device;
/// otherwise <see langword="false"/>.
/// When this method returns, <see langword="true"/> if a terminal device is available for input
/// (either stdin or the controlling terminal); otherwise <see langword="false"/>.
/// </param>
/// <param name="outputAttached">
/// When this method returns, <see langword="true"/> if standard output is connected to a console device;
/// otherwise <see langword="false"/>.
/// When this method returns, <see langword="true"/> if a terminal device is available for output
/// (either stdout or the controlling terminal); otherwise <see langword="false"/>.
/// </param>
/// <returns><see langword="true"/> if both input and output are attached to a terminal; otherwise <see langword="false"/>.</returns>
public static bool IsAttachedToTerminal (out bool inputAttached, out bool outputAttached)
Expand All @@ -69,13 +76,8 @@ public static bool IsAttachedToTerminal (out bool inputAttached, out bool output
return false;
}

if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows))
{
return WindowsConsoleHelper.IsAttachedToTerminal (out inputAttached, out outputAttached);
}

inputAttached = UnixIOHelper.IsTerminal (UnixIOHelper.STDIN_FILENO);
outputAttached = UnixIOHelper.IsTerminal (UnixIOHelper.STDOUT_FILENO);
inputAttached = TerminalDevice.IsInputAttached;
outputAttached = TerminalDevice.IsOutputAttached;

return inputAttached && outputAttached;
}
Expand Down
Loading
Loading