spectreconsole / spectre.console

A .NET library that makes it easier to create beautiful console applications.
https://spectreconsole.net
MIT License
9.36k stars 495 forks source link

Long strings get line breaks inserted when written using AnsiConsole.WriteLine #1312

Open Gnbrkm41 opened 1 year ago

Gnbrkm41 commented 1 year ago

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 :+1: this issue if you are interested in it.

sandreas commented 2 weeks ago

@Gnbrkm41 The suggested solutions so far were:

My personal suggestion would be a markup option:

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); 
filzrev commented 2 weeks ago

The suggested solutions so far were:

I've used another workaround by wrapping render element with custom IRenderable that override Measure/ Render methods. Downside of this workaround is when using link/decoration affected to the end of the console.
(I've confirmed that problems when changing Windows Terminal's size dynamically)

Example Code ```csharp using 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 Render(RenderOptions options, int maxWidth) => _renderable.Render(options, int.MaxValue); } } ```