Unhandled exception. System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
Opened this issue ยท 2 comments
Information
- OS:Windows And Mac
- Version:0.49.1
- Terminal: Windows Terminal And Mac MacTerminal
Describe the bug
To Reproduce
Expected behavior
Unhandled exception. System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
at System.String.ThrowSubstringArgumentOutOfRange(Int32, Int32)
at System.String.Substring(Int32, Int32)
at Spectre.Console.Rendering.Segment.SplitOverflow(Segment, Nullable1, Int32) in /_/src/Spectre.Console/Rendering/Segment.cs:line 371 at Spectre.Console.Paragraph.SplitLines(Int32) in /_/src/Spectre.Console/Widgets/Paragraph.cs:line 232 at Spectre.Console.Paragraph.Render(RenderOptions, Int32) in /_/src/Spectre.Console/Widgets/Paragraph.cs:line 141 at Spectre.Console.TableRenderer.Render(TableRendererContext, List
1) in //src/Spectre.Console/Widgets/Table/TableRenderer.cs:line 11
at Spectre.Console.TableRenderer.Render(TableRendererContext, List1) in /_/src/Spectre.Console/Widgets/Table/TableRenderer.cs:line 31 at Spectre.Console.Padder.Render(RenderOptions, Int32) in /_/src/Spectre.Console/Widgets/Padder.cs:line 45 at Spectre.Console.Rendering.LiveRenderable.Render(RenderOptions, Int32)+MoveNext() at System.Collections.Generic.List
1.AddRange(IEnumerable1) at Spectre.Console.RenderableExtensions.GetSegments(IAnsiConsole, RenderOptions, IEnumerable
1) in //src/Spectre.Console/Extensions/RenderableExtensions.cs:line 34
at Spectre.Console.AnsiBuilder.Build(IAnsiConsole, IRenderable) in //src/Spectre.Console/Internal/Backends/Ansi/AnsiBuilder.cs:line 17
at Spectre.Console.AnsiConsoleFacade.Write(IRenderable) in //src/Spectre.Console/Internal/Backends/AnsiConsoleFacade.cs:line 38
at Spectre.Console.ProgressRefreshThread.Run() in /_/src/Spectre.Console/Live/Progress/ProgressRefreshThread.cs:line 45
at System.Threading.Thread.StartCallback()
Screenshots
Additional context
Please upvote ๐ this issue if you are interested in it.
@zwluoqi Thanks for reporting this. We would however need a reproducable example to even know how to fix this and to make sure it doesn't happen again.
looking at the source code the posted stack trace, it seems the issue is occurring in Segment.SplitOverflow
when the overflow mode is Overflow.Ellipsis
or Overflow.Crop
and Segment.Text
is a string shorter than maxWidth-1
.
Which then poses the question as to why the Segment.SplitOverflow
method is being called despite the Segment.Text
string being shorter than maxWidth-1
. Looking at the calling method (Paragraph.SplitLines
), its logic decides that Segment.SplitOverflow
is being called when Segment.CellCount()
is larger than maxWidth
.
Ergo, reproducing the problem requires a Segment.Text
string whose length is shorter than maxWidth-1
but its corresponding Segment.CellCount()
is larger than maxWidth
. This condition would be satisfied by strings mainly composed of characters that occupy more than one console cell (like CJK characters for example), rendered by Paragraph
elements in either Overflow.Ellipsis
or Overflow.Crop
mode .
Based on this, i made some quick'n'dirty reproduction code (which i wrote and tested using Spectre.Console 0.49.2-preview.0.16):
using Spectre.Console;
using System.Text;
Console.OutputEncoding = Encoding.UTF8;
int stringWidth = 20;
var table = new Table() { Width = 50 };
table.AddColumn("Foo");
table.AddColumn("Bar");
//
// Adding paragraphs with strings mainly composed of single-cell characters is fine...
//
table.AddRow(
new Paragraph(new string('a', stringWidth)) { Overflow = Overflow.Ellipsis },
new Paragraph(new string('b', stringWidth)) { Overflow = Overflow.Ellipsis }
);
AnsiConsole.Write(table);
//
// Exception happens here when adding the paragraphs with the CJK strings to the table
//
table.AddRow(
new Paragraph(new string('ํ', stringWidth)) { Overflow = Overflow.Ellipsis },
new Paragraph(new string('๊ธ', stringWidth)) { Overflow = Overflow.Ellipsis }
);
//
// Using Overflow.Crop would get the same kind of exception
//
// table.AddRow(
// new Paragraph(new string('ํ', stringWidth)) { Overflow = Overflow.Crop },
// new Paragraph(new string('๊ธ', stringWidth)) { Overflow = Overflow.Crop }
// );
AnsiConsole.Write(table);
(dotnetfiddle: https://dotnetfiddle.net/HREpNo)