-
-
Notifications
You must be signed in to change notification settings - Fork 520
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Long strings get line breaks inserted when written using AnsiConsole.WriteLine #1312
Comments
@Gnbrkm41
My personal suggestion would be a AnsiConsole.Markup("[nobr]a very long string[/]"); or an options object as extra parameter or as default: var options = new AnsiConsoleOptions() {
NoBreak = true
};
AnsiConsole.DefaultOptions = options;
AnsiConsole.WriteLine("....", options); |
I've used another workaround by wrapping render element with custom Example Codeusing Spectre.Console;
using Spectre.Console.Rendering;
namespace SampleConsoleApp;
internal class Program
{
static void Main()
{
var bufferSize = Console.BufferWidth;
string longText = new string('a', bufferSize + 1);
// By default long text is automatically breaked based on console buffer size.
AnsiConsole.Console.WriteLine(longText);
// When using **custom renderable}} wrapper. long text is not wrapped.
AnsiConsole.Console.WriteLineNoBreak(longText);
AnsiConsole.Console.WriteLineNoBreak(longText, new(foreground: ConsoleColor.Red));
AnsiConsole.Console.WriteLineNoBreak(longText, new(background: ConsoleColor.Blue));
AnsiConsole.Console.WriteLineNoBreak(longText, new(link: "https://google.com"));
AnsiConsole.Console.WriteLineNoBreak(longText, new(decoration: Decoration.Strikethrough));
AnsiConsole.Console.MarkupNoBreak(Markup.FromInterpolated($"[yellow]{longText}{Environment.NewLine}[/]"));
}
}
public static class IAnsiConsoleExtensions
{
public static void WriteNoBreak(this IAnsiConsole ansiConsole, string text, Style? style = null)
{
ansiConsole.Write(new NonBreakingRenderable(text, style));
}
public static void WriteLineNoBreak(this IAnsiConsole ansiConsole, string text, Style? style = null)
{
ansiConsole.Write(new NonBreakingRenderable($"{text}{Environment.NewLine}", style));
}
public static void MarkupNoBreak(this IAnsiConsole ansiConsole, Markup markup)
{
ansiConsole.Write(new NonBreakingRenderable(markup));
}
private sealed class NonBreakingRenderable : IRenderable
{
private readonly IRenderable _renderable;
public NonBreakingRenderable(string text, Style? style)
{
_renderable = new Paragraph(text, style);
}
public NonBreakingRenderable(IRenderable renderable)
{
_renderable = renderable;
}
public Measurement Measure(RenderOptions options, int maxWidth) => _renderable.Measure(options, int.MaxValue);
public IEnumerable<Segment> Render(RenderOptions options, int maxWidth) => _renderable.Render(options, int.MaxValue);
}
} |
@filzrev I like your idea. Thanks for the code. I'm using spectre.console for logs, so this is how your code added to what I already have looks like. using Spectre.Console;
using Spectre.Console.Rendering;
namespace Omada.Ingestion.Logging.Helpers;
/// <summary>
/// A helper class for building ANSI strings using Spectre.Console.
/// </summary>
public sealed class AnsiStringBuilder : IDisposable
{
/// <summary>
/// Gets the ANSI console writer.
/// </summary>
private IAnsiConsole AnsiWriter { get; }
/// <summary>
/// Gets the string writer.
/// </summary>
private StringWriter Writer { get; }
/// <summary>
/// Initializes a new instance of the <see cref="AnsiStringBuilder"/> class.
/// </summary>
public AnsiStringBuilder()
{
Writer = new StringWriter();
AnsiWriter = AnsiConsole.Create(
new AnsiConsoleSettings
{
Ansi = AnsiSupport.No,
ColorSystem = ColorSystemSupport.NoColors,
Out = new AnsiConsoleOutput(Writer)
});
}
/// <summary>
/// Writes a <see cref="IRenderable"/> to the console.
/// </summary>
/// <param name="renderable">The <see cref="IRenderable"/> to write.</param>
public void Write(IRenderable renderable)
{
AnsiWriter.Write(renderable);
}
/// <summary>
/// Writes line to the builder without a line break.
/// </summary>
/// <param name="text">The text to write.</param>
/// <param name="style">The style to apply to the text.</param>
public void WriteNoLineBreak(string text, Style? style = null) => AnsiWriter.Write(new NonBreakingRenderable(text, style));
/// <summary>
/// Writes line to the builder without a line break.
/// </summary>
/// <param name="text">The text to write.</param>
/// <param name="style">The style to apply to the text.</param>
public void WriteLineNoLineBreak(string text, Style? style = null) => AnsiWriter.Write(new NonBreakingRenderable($"{text}{Environment.NewLine}", style));
/// <summary>
/// Writes markup to the console without a line break.
/// </summary>
/// <param name="markup">The markup to write.</param>
public void MarkupNoLineBreak(Markup markup) => AnsiWriter.Write(new NonBreakingRenderable(markup));
/// <summary>
/// Returns the string generated using ANSI string builder.
/// </summary>
public override string ToString()
{
return Writer.ToString();
}
/// <summary>
/// Disposes the resources used by the <see cref="AnsiStringBuilder"/> class.
/// </summary>
public void Dispose()
{
Writer.Dispose();
}
/// <summary>
/// A renderable class that prevents line breaks.
/// </summary>
private sealed class NonBreakingRenderable : IRenderable
{
private readonly IRenderable _renderable;
/// <summary>
/// Initializes a new instance of the <see cref="NonBreakingRenderable"/> class with text and style.
/// </summary>
/// <param name="text">The text to render.</param>
/// <param name="style">The style to apply to the text.</param>
public NonBreakingRenderable(string text, Style? style)
{
_renderable = new Paragraph(text, style);
}
/// <summary>
/// Initializes a new instance of the <see cref="NonBreakingRenderable"/> class with a renderable.
/// </summary>
/// <remarks>
/// Added to allow logging without a line break.
/// Based on issue: Long strings get line breaks inserted when written using AnsiConsole.WriteLine #1312
/// Comment: https://github.com/spectreconsole/spectre.console/issues/1312#issuecomment-2391514446
/// </remarks>
/// <param name="renderable">The renderable to wrap.</param>
public NonBreakingRenderable(IRenderable renderable)
{
_renderable = renderable;
}
/// <summary>
/// Measures the size of the renderable.
/// </summary>
/// <param name="options">The render options.</param>
/// <param name="maxWidth">The maximum width.</param>
/// <returns>The measurement of the renderable.</returns>
public Measurement Measure(RenderOptions options, int maxWidth) =>
_renderable.Measure(
options,
int.MaxValue);
/// <summary>
/// Renders the renderable.
/// </summary>
/// <param name="options">The render options.</param>
/// <param name="maxWidth">The maximum width.</param>
/// <returns>The segments of the renderable.</returns>
public IEnumerable<Segment> Render(RenderOptions options, int maxWidth) =>
_renderable.Render(
options,
int.MaxValue);
}
} |
I'm not sure why, but I don't run into this when running my program in debug mode in Rider: Codeusing Spectre.Console;
const string moreThan80Chars =
"asldjkhashjafhjkadfjhkashjksdakhjasjkhlasdhjklashjlkasjhkajhkdlasdhjkadjasdkjhs|asdkjlshdflkjshdfkjhsdfjhsdfkjhsdfkjhsdf";
Console.WriteLine(moreThan80Chars);
AnsiConsole.WriteLine(moreThan80Chars);
Console.WriteLine("Window Width:" + Console.WindowWidth);
Console.WriteLine("Buffer Width:" + Console.BufferWidth); |
Using using Spectre.Console;
const string moreThan80Chars =
"asldjkhashjafhjkadfjhkashjksdakhjasjkhlasdhjklashjlkasjhkajhkdlasdhjkadjasdkjhs|asdkjlshdflkjshdfkjhsdfjhsdfkjhsdfkjhsdf";
AnsiConsole.Console.Profile.Width = Console.LargestWindowWidth;
Console.WriteLine(moreThan80Chars);
AnsiConsole.WriteLine(moreThan80Chars);
Console.WriteLine("Window Width: " + Console.WindowWidth);
Console.WriteLine("Buffer Width: " + Console.BufferWidth);
Console.WriteLine("LargestWindowWidth: " + Console.LargestWindowWidth); For some reason, this also changes the values for |
Title says all; It's kind of annoying when you print long single-line strings and copy & paste it somewhere else, only to find that the string is not single line anymore.
Note that this is essentially a duplicate of #845, but since the original issue is marked as closed I am reopening another issue to hopefully get any suggestions to get around this. Since I'm on the latest preview and am experiencing this... I guess the issue still remains as is?
Please upvote 👍 this issue if you are interested in it.
The text was updated successfully, but these errors were encountered: