diff --git a/examples/Console/Info/Program.cs b/examples/Console/Info/Program.cs index 030a455..d06d6ab 100644 --- a/examples/Console/Info/Program.cs +++ b/examples/Console/Info/Program.cs @@ -9,7 +9,7 @@ namespace InfoExample var grid = new Grid() .AddColumn(new GridColumn().NoWrap().PadRight(4)) .AddColumn() - .AddRow("[b]Profile[/]", $"{AnsiConsole.Console.Profile.Name}") + .AddRow("[b]Enrichers[/]", string.Join(", ", AnsiConsole.Profile.Enrichers)) .AddRow("[b]Color system[/]", $"{AnsiConsole.Profile.ColorSystem}") .AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Ansi)}") .AddRow("[b]Supports links?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Links)}") diff --git a/src/Spectre.Console.Testing/Fakes/FakeAnsiConsole.cs b/src/Spectre.Console.Testing/Fakes/FakeAnsiConsole.cs index 06f1e85..c692b20 100644 --- a/src/Spectre.Console.Testing/Fakes/FakeAnsiConsole.cs +++ b/src/Spectre.Console.Testing/Fakes/FakeAnsiConsole.cs @@ -26,12 +26,16 @@ namespace Spectre.Console.Testing { _writer = new StringWriter(); - var factory = AnsiConsoleFactory.NoEnrichers(); + var factory = new AnsiConsoleFactory(); _console = factory.Create(new AnsiConsoleSettings { Ansi = ansi, ColorSystem = (ColorSystemSupport)system, Out = _writer, + Enrichment = new ProfileEnrichment + { + UseDefaultEnrichers = false, + }, }); _console.Profile.Width = width; diff --git a/src/Spectre.Console.Testing/Fakes/FakeConsole.cs b/src/Spectre.Console.Testing/Fakes/FakeConsole.cs index 8aade3c..183d916 100644 --- a/src/Spectre.Console.Testing/Fakes/FakeConsole.cs +++ b/src/Spectre.Console.Testing/Fakes/FakeConsole.cs @@ -11,18 +11,11 @@ namespace Spectre.Console.Testing { public Profile Profile { get; } public IAnsiConsoleCursor Cursor => new FakeAnsiConsoleCursor(); - public FakeConsoleInput Input { get; } - IAnsiConsoleInput IAnsiConsole.Input => Input; public RenderPipeline Pipeline { get; } - public Decoration Decoration { get; set; } - public Color Foreground { get; set; } - public Color Background { get; set; } - public string Link { get; set; } - - public StringWriter Writer { get; } - public string Output => Writer.ToString(); + public FakeConsoleInput Input { get; } + public string Output => Profile.Out.ToString(); public IReadOnlyList Lines => Output.TrimEnd('\n').Split(new char[] { '\n' }); public FakeConsole( @@ -30,11 +23,10 @@ namespace Spectre.Console.Testing bool supportsAnsi = true, ColorSystem colorSystem = ColorSystem.Standard, bool legacyConsole = false, bool interactive = true) { - Writer = new StringWriter(); Input = new FakeConsoleInput(); Pipeline = new RenderPipeline(); - Profile = new Profile("Fake console", Writer, encoding ?? Encoding.UTF8); + Profile = new Profile(new StringWriter(), encoding ?? Encoding.UTF8); Profile.Width = width; Profile.Height = height; Profile.ColorSystem = colorSystem; @@ -46,7 +38,7 @@ namespace Spectre.Console.Testing public void Dispose() { - Writer.Dispose(); + Profile.Out.Dispose(); } public void Clear(bool home) @@ -62,7 +54,7 @@ namespace Spectre.Console.Testing foreach (var segment in segments) { - Writer.Write(segment.Text); + Profile.Out.Write(segment.Text); } } diff --git a/src/Spectre.Console/AnsiConsoleFactory.cs b/src/Spectre.Console/AnsiConsoleFactory.cs index 00f9f59..55635eb 100644 --- a/src/Spectre.Console/AnsiConsoleFactory.cs +++ b/src/Spectre.Console/AnsiConsoleFactory.cs @@ -1,8 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; using System.Text; +using Spectre.Console.Enrichment; namespace Spectre.Console { @@ -11,49 +10,6 @@ namespace Spectre.Console /// public sealed class AnsiConsoleFactory { - private readonly List _enrichers; - - /// - /// Initializes a new instance of the class. - /// - public AnsiConsoleFactory() - { - _enrichers = new List - { - new AppVeyorProfile(), - new BambooProfile(), - new BitbucketProfile(), - new BitriseProfile(), - new ContinuaCIProfile(), - new GitHubProfile(), - new GitLabProfile(), - new GoCDProfile(), - new JenkinsProfile(), - new MyGetProfile(), - new TeamCityProfile(), - new TfsProfile(), - new TravisProfile(), - }; - } - - /// - /// Initializes a new instance of the class. - /// - /// The profile enrichers to use. - public AnsiConsoleFactory(IEnumerable enrichers) - { - _enrichers = new List(enrichers ?? Enumerable.Empty()); - } - - /// - /// Creates a new without default profile enrichers. - /// - /// A new without default profile enrichers. - public static AnsiConsoleFactory NoEnrichers() - { - return new AnsiConsoleFactory(Enumerable.Empty()); - } - /// /// Creates an ANSI console. /// @@ -86,7 +42,7 @@ namespace Spectre.Console interactive = Environment.UserInteractive; } - var profile = new Profile("Default", buffer, encoding) + var profile = new Profile(buffer, encoding) { ColorSystem = colorSystem, }; @@ -97,43 +53,14 @@ namespace Spectre.Console profile.Capabilities.Interactive = interactive; // Enrich the profile - var variables = GetEnvironmentVariables(settings); - var customEnrichers = settings.Enrichers ?? Enumerable.Empty(); - foreach (var enricher in _enrichers.Concat(customEnrichers)) - { - if (enricher.Enabled(variables)) - { - enricher.Enrich(profile); - } - } + ProfileEnricher.Enrich( + profile, + settings.Enrichment, + settings.EnvironmentVariables); return new AnsiConsoleFacade(profile); } - private static IDictionary GetEnvironmentVariables(AnsiConsoleSettings settings) - { - if (settings.EnvironmentVariables != null) - { - return new Dictionary(settings.EnvironmentVariables, StringComparer.OrdinalIgnoreCase); - } - - return Environment.GetEnvironmentVariables() - .Cast() - .Aggregate( - new Dictionary(StringComparer.OrdinalIgnoreCase), - (dictionary, entry) => - { - var key = (string)entry.Key; - if (!dictionary.TryGetValue(key, out _)) - { - dictionary.Add(key, entry.Value as string ?? string.Empty); - } - - return dictionary; - }, - dictionary => dictionary); - } - private static (bool Ansi, bool Legacy) DetectAnsi(AnsiConsoleSettings settings, System.IO.TextWriter buffer) { var supportsAnsi = settings.Ansi == AnsiSupport.Yes; diff --git a/src/Spectre.Console/AnsiConsoleSettings.cs b/src/Spectre.Console/AnsiConsoleSettings.cs index 7cfe9ee..2027872 100644 --- a/src/Spectre.Console/AnsiConsoleSettings.cs +++ b/src/Spectre.Console/AnsiConsoleSettings.cs @@ -30,6 +30,11 @@ namespace Spectre.Console /// public InteractionSupport Interactive { get; set; } + /// + /// Gets or sets the profile enrichments settings. + /// + public ProfileEnrichment Enrichment { get; set; } + /// /// Gets or sets the environment variables. /// If not value is provided the default environment variables will be used. @@ -37,8 +42,11 @@ namespace Spectre.Console public Dictionary? EnvironmentVariables { get; set; } /// - /// Gets or sets the profile enrichers to use. + /// Initializes a new instance of the class. /// - public List? Enrichers { get; set; } + public AnsiConsoleSettings() + { + Enrichment = new ProfileEnrichment(); + } } } diff --git a/src/Spectre.Console/Cli/CommandApp.cs b/src/Spectre.Console/Cli/CommandApp.cs index a4766d0..3e857fb 100644 --- a/src/Spectre.Console/Cli/CommandApp.cs +++ b/src/Spectre.Console/Cli/CommandApp.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Threading.Tasks; using Spectre.Console.Rendering; diff --git a/src/Spectre.Console/Profiles/AppVeyorProfile.cs b/src/Spectre.Console/Enrichment/CI/AppVeyorEnricher.cs similarity index 62% rename from src/Spectre.Console/Profiles/AppVeyorProfile.cs rename to src/Spectre.Console/Enrichment/CI/AppVeyorEnricher.cs index f5b6b53..a7cb5c2 100644 --- a/src/Spectre.Console/Profiles/AppVeyorProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/AppVeyorEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class AppVeyorProfile : IProfileEnricher + internal sealed class AppVeyorEnricher : IProfileEnricher { + public string Name => "AppVeyor"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("APPVEYOR"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "AppVeyor"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/BambooProfile.cs b/src/Spectre.Console/Enrichment/CI/BambooEnricher.cs similarity index 64% rename from src/Spectre.Console/Profiles/BambooProfile.cs rename to src/Spectre.Console/Enrichment/CI/BambooEnricher.cs index 15922c6..6a3520e 100644 --- a/src/Spectre.Console/Profiles/BambooProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/BambooEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class BambooProfile : IProfileEnricher + internal sealed class BambooEnricher : IProfileEnricher { + public string Name => "Bamboo"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("bamboo_buildNumber"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "Bamboo"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/BitbucketProfile.cs b/src/Spectre.Console/Enrichment/CI/BitbucketEnricher.cs similarity index 72% rename from src/Spectre.Console/Profiles/BitbucketProfile.cs rename to src/Spectre.Console/Enrichment/CI/BitbucketEnricher.cs index c30b10f..2237ea3 100644 --- a/src/Spectre.Console/Profiles/BitbucketProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/BitbucketEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class BitbucketProfile : IProfileEnricher + internal sealed class BitbucketEnricher : IProfileEnricher { + public string Name => "Bitbucket"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("BITBUCKET_REPO_OWNER") || @@ -13,7 +15,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "BitBucket"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/BitriseProfile.cs b/src/Spectre.Console/Enrichment/CI/BitriseEnricher.cs similarity index 63% rename from src/Spectre.Console/Profiles/BitriseProfile.cs rename to src/Spectre.Console/Enrichment/CI/BitriseEnricher.cs index 64762d9..a3d0fc1 100644 --- a/src/Spectre.Console/Profiles/BitriseProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/BitriseEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class BitriseProfile : IProfileEnricher + internal sealed class BitriseEnricher : IProfileEnricher { + public string Name => "Bitrise"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("BITRISE_BUILD_URL"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "Bitrise"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/ContinuaCIProfile.cs b/src/Spectre.Console/Enrichment/CI/ContinuaEnricher.cs similarity index 63% rename from src/Spectre.Console/Profiles/ContinuaCIProfile.cs rename to src/Spectre.Console/Enrichment/CI/ContinuaEnricher.cs index bc0b97f..e1b70e2 100644 --- a/src/Spectre.Console/Profiles/ContinuaCIProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/ContinuaEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class ContinuaCIProfile : IProfileEnricher + internal sealed class ContinuaEnricher : IProfileEnricher { + public string Name => "ContinuaCI"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("ContinuaCI.Version"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "Continua CI"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/GitHubProfile.cs b/src/Spectre.Console/Enrichment/CI/GitHubEnricher.cs similarity index 82% rename from src/Spectre.Console/Profiles/GitHubProfile.cs rename to src/Spectre.Console/Enrichment/CI/GitHubEnricher.cs index eb59684..5d18f47 100644 --- a/src/Spectre.Console/Profiles/GitHubProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/GitHubEnricher.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class GitHubProfile : IProfileEnricher + internal sealed class GitHubEnricher : IProfileEnricher { + public string Name => "GitHub"; + public bool Enabled(IDictionary environmentVariables) { if (environmentVariables.TryGetValue("GITHUB_ACTIONS", out var value)) @@ -17,7 +19,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "GitHub Actions"; profile.Capabilities.Ansi = true; profile.Capabilities.Legacy = false; profile.Capabilities.Interactive = false; diff --git a/src/Spectre.Console/Profiles/GitLabProfile.cs b/src/Spectre.Console/Enrichment/CI/GitLabEnricher.cs similarity index 78% rename from src/Spectre.Console/Profiles/GitLabProfile.cs rename to src/Spectre.Console/Enrichment/CI/GitLabEnricher.cs index cd8bc2a..7e170c6 100644 --- a/src/Spectre.Console/Profiles/GitLabProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/GitLabEnricher.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class GitLabProfile : IProfileEnricher + internal sealed class GitLabEnricher : IProfileEnricher { + public string Name => "GitLab"; + public bool Enabled(IDictionary environmentVariables) { if (environmentVariables.TryGetValue("CI_SERVER", out var value)) @@ -17,7 +19,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "GitLab"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/GoCDProfile.cs b/src/Spectre.Console/Enrichment/CI/GoCDEnricher.cs similarity index 64% rename from src/Spectre.Console/Profiles/GoCDProfile.cs rename to src/Spectre.Console/Enrichment/CI/GoCDEnricher.cs index 4147ad5..769d865 100644 --- a/src/Spectre.Console/Profiles/GoCDProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/GoCDEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class GoCDProfile : IProfileEnricher + internal sealed class GoCDEnricher : IProfileEnricher { + public string Name => "GoCD"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("GO_SERVER_URL"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "GoCD"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/JenkinsProfile.cs b/src/Spectre.Console/Enrichment/CI/JenkinsEnricher.cs similarity index 63% rename from src/Spectre.Console/Profiles/JenkinsProfile.cs rename to src/Spectre.Console/Enrichment/CI/JenkinsEnricher.cs index 861a363..aebf806 100644 --- a/src/Spectre.Console/Profiles/JenkinsProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/JenkinsEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class JenkinsProfile : IProfileEnricher + internal sealed class JenkinsEnricher : IProfileEnricher { + public string Name => "Jenkins"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("JENKINS_URL"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "Jenkins"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/MyGetProfile.cs b/src/Spectre.Console/Enrichment/CI/MyGetEnricher.cs similarity index 76% rename from src/Spectre.Console/Profiles/MyGetProfile.cs rename to src/Spectre.Console/Enrichment/CI/MyGetEnricher.cs index eb8d26c..d33198b 100644 --- a/src/Spectre.Console/Profiles/MyGetProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/MyGetEnricher.cs @@ -1,10 +1,12 @@ -using System; +using System; using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class MyGetProfile : IProfileEnricher + internal sealed class MyGetEnricher : IProfileEnricher { + public string Name => "MyGet"; + public bool Enabled(IDictionary environmentVariables) { if (environmentVariables.TryGetValue("BuildRunner", out var value)) @@ -17,7 +19,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "MyGet"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/TeamCityProfile.cs b/src/Spectre.Console/Enrichment/CI/TeamCityEnricher.cs similarity index 63% rename from src/Spectre.Console/Profiles/TeamCityProfile.cs rename to src/Spectre.Console/Enrichment/CI/TeamCityEnricher.cs index f5d19ea..fc4b730 100644 --- a/src/Spectre.Console/Profiles/TeamCityProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/TeamCityEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class TeamCityProfile : IProfileEnricher + internal sealed class TeamCityEnricher : IProfileEnricher { + public string Name => "TeamCity"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("TEAMCITY_VERSION"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "TeamCity"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/TfsProfile.cs b/src/Spectre.Console/Enrichment/CI/TfsEnricher.cs similarity index 64% rename from src/Spectre.Console/Profiles/TfsProfile.cs rename to src/Spectre.Console/Enrichment/CI/TfsEnricher.cs index 25681ac..3bb5068 100644 --- a/src/Spectre.Console/Profiles/TfsProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/TfsEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class TfsProfile : IProfileEnricher + internal sealed class TfsEnricher : IProfileEnricher { + public string Name => "TFS"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("TF_BUILD"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "TFS"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Profiles/TravisProfile.cs b/src/Spectre.Console/Enrichment/CI/TravisEnricher.cs similarity index 63% rename from src/Spectre.Console/Profiles/TravisProfile.cs rename to src/Spectre.Console/Enrichment/CI/TravisEnricher.cs index dacf373..46f6528 100644 --- a/src/Spectre.Console/Profiles/TravisProfile.cs +++ b/src/Spectre.Console/Enrichment/CI/TravisEnricher.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace Spectre.Console +namespace Spectre.Console.Enrichment { - internal sealed class TravisProfile : IProfileEnricher + internal sealed class TravisEnricher : IProfileEnricher { + public string Name => "Travis"; + public bool Enabled(IDictionary environmentVariables) { return environmentVariables.ContainsKey("TRAVIS"); @@ -11,7 +13,6 @@ namespace Spectre.Console public void Enrich(Profile profile) { - profile.Name = "Travis"; profile.Capabilities.Interactive = false; } } diff --git a/src/Spectre.Console/Enrichment/ProfileEnricher.cs b/src/Spectre.Console/Enrichment/ProfileEnricher.cs new file mode 100644 index 0000000..2987786 --- /dev/null +++ b/src/Spectre.Console/Enrichment/ProfileEnricher.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Spectre.Console.Enrichment +{ + internal static class ProfileEnricher + { + private static readonly List _defaultEnrichers = new List + { + new WindowsTerminalEnricher(), + new AppVeyorEnricher(), + new BambooEnricher(), + new BitbucketEnricher(), + new BitriseEnricher(), + new ContinuaEnricher(), + new GitHubEnricher(), + new GitLabEnricher(), + new GoCDEnricher(), + new JenkinsEnricher(), + new MyGetEnricher(), + new TeamCityEnricher(), + new TfsEnricher(), + new TravisEnricher(), + }; + + public static void Enrich( + Profile profile, + ProfileEnrichment settings, + IDictionary? environmentVariables) + { + if (profile is null) + { + throw new ArgumentNullException(nameof(profile)); + } + + settings ??= new ProfileEnrichment(); + + var variables = GetEnvironmentVariables(environmentVariables); + foreach (var enricher in GetEnrichers(settings)) + { + if (string.IsNullOrWhiteSpace(enricher.Name)) + { + throw new InvalidOperationException($"Profile enricher of type '{enricher.GetType().FullName}' does not have a name."); + } + + if (enricher.Enabled(variables)) + { + enricher.Enrich(profile); + profile.AddEnricher(enricher.Name); + } + } + } + + private static List GetEnrichers(ProfileEnrichment settings) + { + var enrichers = new List(); + + if (settings.UseDefaultEnrichers) + { + enrichers.AddRange(_defaultEnrichers); + } + + if (settings.Enrichers?.Count > 0) + { + enrichers.AddRange(settings.Enrichers); + } + + return enrichers; + } + + private static IDictionary GetEnvironmentVariables(IDictionary? variables) + { + if (variables != null) + { + return new Dictionary(variables, StringComparer.OrdinalIgnoreCase); + } + + return Environment.GetEnvironmentVariables() + .Cast() + .Aggregate( + new Dictionary(StringComparer.OrdinalIgnoreCase), + (dictionary, entry) => + { + var key = (string)entry.Key; + if (!dictionary.TryGetValue(key, out _)) + { + dictionary.Add(key, entry.Value as string ?? string.Empty); + } + + return dictionary; + }, + dictionary => dictionary); + } + } +} diff --git a/src/Spectre.Console/Enrichment/ProfileEnrichment.cs b/src/Spectre.Console/Enrichment/ProfileEnrichment.cs new file mode 100644 index 0000000..7d43e8f --- /dev/null +++ b/src/Spectre.Console/Enrichment/ProfileEnrichment.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Spectre.Console +{ + /// + /// Contains settings for profile enrichment. + /// + public sealed class ProfileEnrichment + { + /// + /// Gets or sets a value indicating whether or not + /// any default enrichers should be added. + /// + /// Defaults to true. + public bool UseDefaultEnrichers { get; set; } = true; + + /// + /// Gets or sets the list of custom enrichers to use. + /// + public List? Enrichers { get; set; } + } +} diff --git a/src/Spectre.Console/Enrichment/Terminals/WindowsTerminalEnricher.cs b/src/Spectre.Console/Enrichment/Terminals/WindowsTerminalEnricher.cs new file mode 100644 index 0000000..392d43d --- /dev/null +++ b/src/Spectre.Console/Enrichment/Terminals/WindowsTerminalEnricher.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace Spectre.Console.Enrichment +{ + internal sealed class WindowsTerminalEnricher : IProfileEnricher + { + public string Name => "Windows Terminal"; + + public bool Enabled(IDictionary environmentVariables) + { + return environmentVariables.ContainsKey("WT_SESSION"); + } + + public void Enrich(Profile profile) + { + profile.Capabilities.Links = true; + } + } +} diff --git a/src/Spectre.Console/IProfileEnricher.cs b/src/Spectre.Console/IProfileEnricher.cs index 2bc52e2..70263f3 100644 --- a/src/Spectre.Console/IProfileEnricher.cs +++ b/src/Spectre.Console/IProfileEnricher.cs @@ -7,6 +7,11 @@ namespace Spectre.Console /// public interface IProfileEnricher { + /// + /// Gets the name of the enricher. + /// + public string Name { get; } + /// /// Gets whether or not this enricher is enabled. /// diff --git a/src/Spectre.Console/Profile.cs b/src/Spectre.Console/Profile.cs index e2b550e..4f083db 100644 --- a/src/Spectre.Console/Profile.cs +++ b/src/Spectre.Console/Profile.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Text; @@ -9,7 +10,9 @@ namespace Spectre.Console /// public sealed class Profile { - private string _name; + private readonly HashSet _enrichers; + private static readonly string[] _defaultEnricher = new[] { "Default" }; + private TextWriter _out; private Encoding _encoding; private Capabilities _capabilities; @@ -17,19 +20,18 @@ namespace Spectre.Console private int? _height; /// - /// Gets or sets the profile name. + /// Gets the enrichers used to build this profile. /// - public string Name + public IReadOnlyCollection Enrichers { - get => _name; - set + get { - if (value == null) + if (_enrichers.Count > 0) { - throw new InvalidOperationException("Profile name cannot be null"); + return _enrichers; } - _name = value; + return _defaultEnricher; } } @@ -139,12 +141,11 @@ namespace Spectre.Console /// /// Initializes a new instance of the class. /// - /// The profile name. /// The output buffer. /// The output encoding. - public Profile(string name, TextWriter @out, Encoding encoding) + public Profile(TextWriter @out, Encoding encoding) { - _name = name ?? throw new ArgumentNullException(nameof(name)); + _enrichers = new HashSet(StringComparer.OrdinalIgnoreCase); _out = @out ?? throw new ArgumentNullException(nameof(@out)); _encoding = encoding ?? throw new ArgumentNullException(nameof(encoding)); _capabilities = new Capabilities(this); @@ -161,6 +162,16 @@ namespace Spectre.Console return (int)colorSystem <= (int)ColorSystem; } + internal void AddEnricher(string name) + { + if (name is null) + { + throw new ArgumentNullException(nameof(name)); + } + + _enrichers.Add(name); + } + private int GetWidth() { if (_width != null)