How to force ANSI escape sequencess mode? #844
-
OS-es: Windows 10, Windows 11, Ubuntu. I would like to escape output with ANSI escape sequences in a program running as CI/CD "gate tool" to display errors and warnings in red/yellow colours. The tool is checking some files match some rules on commit, committers get e-mails if pipeline fails, clicks on the link and sees error output of failed task. Usual stuff. But the output is black and white now. For example, a program argument Is it possible to force ANSI escaping so this code works well both in interactive mode and in CI/CD?: AnsiConsole.MarkupLineInterpolated($"[red][[ERROR]][/] Required field Name is empty in row [invert]{rowNumber}[/]."); |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
@r-pankevicius What CI server are you running it on? Not all support VT/ANSI codes. You can check whether or not Spectre.Console detected ANSI support with the following code: |
Beta Was this translation helpful? Give feedback.
-
@patriksvensson Gitlab, it supports VT/ANSI codes. We made one tool using raw escape sequences but Spectre.Console looks very promising to simplify this stuff. Actually I can make a simple check with very basic spectre "Hello, World!" console program by redirecting it's output to text file. Test 1, On Windows, Ubuntu: Test 2, Do the same on Windows, inside Cmder shell |
Beta Was this translation helpful? Give feedback.
-
Regarding internal class SetAnsiConsoleOutputMode : IDisposable
{
private const int STD_OUTPUT_HANDLE = -11;
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
private const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008;
private readonly uint _previousOutConsoleMode;
private readonly bool _succeededToSet;
public SetAnsiConsoleOutputMode()
{
IntPtr stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (!GetConsoleMode(stdOutHandle, out _previousOutConsoleMode))
{
_succeededToSet = false;
}
else
{
uint outConsoleMode = _previousOutConsoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
_succeededToSet = SetConsoleMode(stdOutHandle, outConsoleMode);
}
}
public void Dispose()
{
if (_succeededToSet)
{
IntPtr stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(stdOutHandle, _previousOutConsoleMode);
}
}
[DllImport("kernel32.dll")]
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll")]
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
}
internal static class Program
{
static void Main()
{
// AnsiConsole.Profile.Capabilities.Ansi == true here
using var _ = new SetAnsiConsoleOutputMode();
// AnsiConsole.Profile.Capabilities.Ansi == true here, too
AnsiConsole.Background = ConsoleColor.Magenta;
AnsiConsole.WriteLine("Hello, World!");
}
} |
Beta Was this translation helpful? Give feedback.
-
Actually it appeared that So the answer to the question "How to force ANSI escape sequencess mode?" was quite simple then: static void Main(string[] args)
{
if (args.Any(arg => arg == "--force-ansi-output"))
{
AnsiConsole.Console = AnsiConsole.Create(new AnsiConsoleSettings
{
Ansi = AnsiSupport.Yes,
ColorSystem = ColorSystemSupport.EightBit,
Out = new AnsiConsoleOutput(Console.Out)
});
}
AnsiConsole.Background = ConsoleColor.Magenta;
AnsiConsole.WriteLine("Hello, World!");
AnsiConsole.MarkupLine("[default on blue]World[/]");
} |
Beta Was this translation helpful? Give feedback.
Actually it appeared that
SetAnsiConsoleOutputMode()
failed to set desired output mode when output was redirected to the file.So the answer to the question "How to force ANSI escape sequencess mode?" was quite simple then: