using System; using System.Runtime.InteropServices; using System.Text; using Spectre.Console.Enrichment; namespace Spectre.Console { /// /// Factory for creating an ANSI console. /// public sealed class AnsiConsoleFactory { /// /// Creates an ANSI console. /// /// The settings. /// An implementation of . public IAnsiConsole Create(AnsiConsoleSettings settings) { if (settings is null) { throw new ArgumentNullException(nameof(settings)); } var buffer = settings.Out ?? System.Console.Out; // Detect if the terminal support ANSI or not var (supportsAnsi, legacyConsole) = DetectAnsi(settings, buffer); // Use the provided encoding or fall back to UTF-8 var encoding = buffer.IsStandardOut() || buffer.IsStandardError() ? System.Console.OutputEncoding : Encoding.UTF8; // Get the color system var colorSystem = settings.ColorSystem == ColorSystemSupport.Detect ? ColorSystemDetector.Detect(supportsAnsi) : (ColorSystem)settings.ColorSystem; // Get whether or not we consider the terminal interactive var interactive = settings.Interactive == InteractionSupport.Yes; if (settings.Interactive == InteractionSupport.Detect) { interactive = Environment.UserInteractive; } var profile = new Profile(buffer, encoding) { ColorSystem = colorSystem, }; profile.Capabilities.Ansi = supportsAnsi; profile.Capabilities.Links = supportsAnsi && !legacyConsole; profile.Capabilities.Legacy = legacyConsole; profile.Capabilities.Interactive = interactive; // Enrich the profile ProfileEnricher.Enrich( profile, settings.Enrichment, settings.EnvironmentVariables); return new AnsiConsoleFacade(profile); } private static (bool Ansi, bool Legacy) DetectAnsi(AnsiConsoleSettings settings, System.IO.TextWriter buffer) { var supportsAnsi = settings.Ansi == AnsiSupport.Yes; var legacyConsole = false; if (settings.Ansi == AnsiSupport.Detect) { (supportsAnsi, legacyConsole) = AnsiDetector.Detect(buffer.IsStandardError(), true); // Check whether or not this is a legacy console from the existing instance (if any). // We need to do this because once we upgrade the console to support ENABLE_VIRTUAL_TERMINAL_PROCESSING // on Windows, there is no way of detecting whether or not we're running on a legacy console or not. if (AnsiConsole.Created && !legacyConsole && (buffer.IsStandardOut() || buffer.IsStandardError()) && AnsiConsole.Profile.Capabilities.Legacy) { legacyConsole = AnsiConsole.Profile.Capabilities.Legacy; } } else { if (buffer.IsStandardOut() || buffer.IsStandardError()) { // Are we running on Windows? if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // Not the first console we're creating? if (AnsiConsole.Created) { legacyConsole = AnsiConsole.Profile.Capabilities.Legacy; } else { // Try detecting whether or not this (_, legacyConsole) = AnsiDetector.Detect(buffer.IsStandardError(), false); } } } } return (supportsAnsi, legacyConsole); } } }