spectreconsole / spectre.console

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

AnsiConsole.Write(table) throw ArgumentOutOfRangeException #1342

Open lisenz opened 10 months ago

lisenz commented 10 months ago

Information

Describe the bug What I wrote is a console application. It runs without problems on Windows 10, but an ArgumentOutOfRangeException exception is thrown on Windows 7.

Additional context Stack trace:

System.ArgumentOutOfRangeException: Index and length must refer to a locationwithin the string.(Parameterlength')string System.String.Substring<int startIndex, int length)at
List<Segment> Spectre.Console.Rendering.Segment.SplitOuerflow(Segmentt
segment, Overflow? overflow, int maxWidth> in
_/src/Spectre.Console/Rendering/Segment .cs:36?
List<SegmentLine> Spectre.Console.Paragraph.SplitLines(int maxWidth》 inat
/src/Spectre.Console/Widgets/Paragraph.cs:233
IEnumerable<Segment> Spectre.Console .Paragraph.Render(RenderOptionsoptionsat
int maxWidth) in / /src/Spectre.Console/Widgets/Paragraph.cs:142
IEnumerable<segmentat
Spectre.Console.Rendering.Renderable.Spectre.Console.Rendering.IRenderableRender(RenderOptions options, int maxWidth》 in
/src/Spectre .Console/Rendering/Renderable .cs:19

Screenshots 96c8d88167f4c1447199dcdff6e3494

I love this library, thank you always. Hope it will be fixed


Please upvote :+1: this issue if you are interested in it.

patriksvensson commented 10 months ago

@lisenz Thanks. Can you show the code so we can reproduce this?

lisenz commented 10 months ago
                var oriSubDirs = new string[] {
                    "佛山行政智慧安防",
                    "江门行政智慧安防",
                    "南方基地智慧园区",
                    "汕尾行政智慧安防",
                    "韶关行政智慧安防",
                    "深圳行政智慧安防",
                    "阳江行政智慧安防",
                    "云浮行政智慧安防",
                    "湛江行政智慧安防",
                    "中国移动南方基地6号地"
                };

                AnsiConsole.MarkupLine($"1.[yellow]共{oriSubDirs.Count()}个巡检项目:[/]{Environment.NewLine}");
                var itemsPerLine = 5;

                var table = new Table();
                for (int i = 0, len = oriSubDirs.Count(); i < len; i++)
                {
                    var oriPro = oriSubDirs[i];
                    table.AddColumn($"[yellow]{oriPro}[/]");
                    if ((i + 1) % itemsPerLine == 0)
                    {
                        AnsiConsole.Write(table);
                        table = new Table();
                    }
                    if (len < itemsPerLine && i == len - 1)
                    {
                        AnsiConsole.Write(table);
                    }
                }

@patriksvensson Hi,I Copied from my own project and add some test data.

etherfield commented 10 months ago

I've managed to reproduce on my machine with 100x32 console window size, but I think OS doesn't matter here. The exception occurs when the row text is too long and SplitOverflow method is called. I guess Windows 10 sets larger console size by default.

The root cause is that some symbols have different length in console and as a member of string in .NET. E.g.

"𧼢".Length // 2
Cell.GetCellLength("𧼢") // 2

"中".Length // 1
Cell.GetCellLength("中") // 2

"A".Length // 1
Cell.GetCellLength("A") // 1

I can fix it by truncating a string with regard to space it takes up in console. @patriksvensson what do you think?

lisenz commented 10 months ago

@etherfield Hi, Is it because the table.AddColumn() method has a length limit on the text content passed in? Once the text length is too long, will it be automatically intercepted and cause an exception?

etherfield commented 10 months ago

If a text is too long is should be truncated, but it causes an exception instead. This is Windows 8.1. I don't have all the characters (hence '?' marks), but nevertheless the screenshot below is to illustrate what I'm talking about. Untitled

In fact, this is how the fix may look like: 1342-argument-out-of-range