Skip to content

Commit 46e7a7a

Browse files
authored
Spacing and bounding boxes (part 1) (#132)
* Implemented center and right align correctly * Update ReadMe as well * -PositiveInfinity -> NegativeInfinity * Update ReadMe as well 2 * Fix master tests * Fixed alignment, new test, but lots of broken tests * Additional fix for hanging MathView for \left(\\\right) * Only RedMatrix needs fixing * Ready! * Revert unneeded changes * One more test * Resolve review comment
1 parent 96aef6c commit 46e7a7a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+404
-140
lines changed

.editorconfig

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,18 @@ trim_trailing_whitespace = true
1818
dotnet_sort_system_directives_first = true
1919
# C# formatting settings
2020
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference#c-formatting-settings
21-
csharp_new_line_before_open_brace = none
22-
csharp_new_line_before_else = false
2321
csharp_new_line_before_catch = false
22+
csharp_new_line_before_else = false
2423
csharp_new_line_before_finally = false
25-
csharp_new_line_before_members_in_object_initializers = true
26-
csharp_new_line_before_members_in_anonymous_types = true
24+
csharp_new_line_before_members_in_object_initializers = false
25+
csharp_new_line_before_members_in_anonymous_types = false
26+
csharp_new_line_before_open_brace = none
2727
csharp_new_line_between_query_expression_clauses = false
2828

2929
# Indentation options
3030
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference#indent
3131
csharp_indent_case_contents = true
3232
csharp_indent_switch_labels = true
33-
csharp_indent_labels = false
3433
# Spacing options
3534
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference#spacing
3635
csharp_space_after_cast = false

CSharpMath.CoreTests/LaTeXParserTest.cs

Lines changed: 242 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace CSharpMath.CoreTests {
1010
public class LaTeXParserTest {
1111
public static MathList ParseLaTeX(string latex) {
1212
var builder = new LaTeXParser(latex);
13-
if(builder.Build() is { } mathList) {
13+
if (builder.Build() is { } mathList) {
1414
Assert.Null(builder.Error);
1515
return mathList;
1616
} else throw new Xunit.Sdk.NotNullException();
@@ -419,6 +419,47 @@ public void TestMatrix(string env, string left, string right, string leftOutput,
419419
Assert.Equal($@"{leftOutput}\begin{{matrix}}x&y\\ z&w\end{{matrix}}{rightOutput}",
420420
LaTeXParser.MathListToLaTeX(list).ToString());
421421
}
422+
[Theory]
423+
[InlineData(@"\color{red}\begin{pmatrix}1&2\\3&4\end{pmatrix}")]
424+
[InlineData(@"\color{red}\begin{pmatrix}{1}&2\\3&{4}\end{pmatrix}")]
425+
[InlineData(@"\color{red}{\begin{pmatrix}1&2\\3&4\end{pmatrix}}")]
426+
[InlineData(@"\color{red}{{\begin{pmatrix}1&2\\3&4\end{pmatrix}}}")]
427+
[InlineData(@"\color{red}\left(\begin{matrix}1&2\\3&4\end{matrix}\right)")]
428+
[InlineData(@"\color{red}\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) ")]
429+
[InlineData(@"\color{red}{\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) }")]
430+
[InlineData(@"\color{red}{{\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) }}")]
431+
public void TestRedMatrix(string input) {
432+
var list = ParseLaTeX(input);
433+
Assert.Collection(list, CheckAtom<Color>("", color => {
434+
Assert.Equal(new Structures.Color(255, 0, 0), color.Colour);
435+
Assert.Collection(color.InnerList,
436+
CheckAtom<Inner>("", inner => {
437+
Assert.Equal(new Boundary("("), inner.LeftBoundary);
438+
Assert.Equal(new Boundary(")"), inner.RightBoundary);
439+
Assert.Collection(inner.InnerList,
440+
CheckAtom<Table>("", table => {
441+
Assert.Equal("matrix", table.Environment);
442+
Assert.Equal(0, table.InterRowAdditionalSpacing);
443+
Assert.Equal(18, table.InterColumnSpacing);
444+
Assert.Equal(2, table.NRows);
445+
Assert.Equal(2, table.NColumns);
446+
for (int col = 0; col < 2; col++) {
447+
Assert.Equal(ColumnAlignment.Center, table.GetAlignment(col));
448+
for (int row = 0; row < 2; row++) {
449+
Assert.Collection(table.Cells[row][col],
450+
CheckAtom<Style>("", style => Assert.Equal(LineStyle.Text, style.LineStyle)),
451+
atom => Assert.IsType<Number>(atom)
452+
);
453+
}
454+
}
455+
})
456+
);
457+
})
458+
);
459+
}));
460+
Assert.Equal(@"\color{red}{\left( \begin{matrix}1&2\\ 3&4\end{matrix}\right) }",
461+
LaTeXParser.MathListToLaTeX(list).ToString());
462+
}
422463

423464
[Fact]
424465
public void TestDeterminant() {
@@ -454,6 +495,21 @@ IEnumerable<Action<MathAtom>> Checkers() {
454495
Assert.Equal(@"\left| \begin{matrix}\sin (x)&\cos (x)\\ -\cos (x)&\sin (x)\end{matrix}\right| =1", LaTeXParser.MathListToLaTeX(list).ToString());
455496
}
456497

498+
[Fact]
499+
public void TestDefaultEmptyTable() {
500+
var list = ParseLaTeX(@"\\");
501+
var table = Assert.IsType<Table>(Assert.Single(list));
502+
CheckAtom<Table>("")(table);
503+
Assert.Null(table.Environment);
504+
Assert.Equal(1, table.InterRowAdditionalSpacing);
505+
Assert.Equal(0, table.InterColumnSpacing);
506+
Assert.Equal(2, table.NRows);
507+
Assert.Equal(1, table.NColumns);
508+
Assert.Equal(ColumnAlignment.Left, table.GetAlignment(0));
509+
Assert.Equal(ColumnAlignment.Center, table.GetAlignment(1));
510+
Assert.Collection(table.Cells, row0 => Assert.Empty(Assert.Single(row0)), Assert.Empty);
511+
Assert.Equal(@"\\ ", LaTeXParser.MathListToLaTeX(list).ToString());
512+
}
457513
[Fact]
458514
public void TestDefaultTable() {
459515
var list = ParseLaTeX(@"x \\ y");
@@ -473,6 +529,181 @@ public void TestDefaultTable() {
473529
Assert.Equal(@"x\\ y", LaTeXParser.MathListToLaTeX(list).ToString());
474530
}
475531

532+
[Theory]
533+
[InlineData(@"\left(x\\\right)")]
534+
[InlineData(@"\left(x \\ \right)")]
535+
[InlineData(@"\left( x\\ \right)")]
536+
[InlineData(@"\left( x\\ \right) ")]
537+
[InlineData(@"\left({x\\}\right) ")]
538+
[InlineData(@"\left({{x\\}}\right) ")]
539+
public void TestDefaultTableInInner(string input) {
540+
var list = ParseLaTeX(input);
541+
CheckAtom<Inner>("", inner => {
542+
Assert.Equal(new Boundary("("), inner.LeftBoundary);
543+
Assert.Equal(new Boundary(")"), inner.RightBoundary);
544+
CheckAtom<Table>("", table => {
545+
Assert.Null(table.Environment);
546+
Assert.Equal(1, table.InterRowAdditionalSpacing);
547+
Assert.Equal(0, table.InterColumnSpacing);
548+
Assert.Equal(2, table.NRows);
549+
Assert.Equal(1, table.NColumns);
550+
Assert.Equal(ColumnAlignment.Left, table.GetAlignment(0));
551+
Assert.IsType<Variable>(Assert.Single(table.Cells[0][0]));
552+
Assert.Empty(table.Cells[1][0]);
553+
})(Assert.Single(inner.InnerList));
554+
})(Assert.Single(list));
555+
Assert.Equal(@"\left( x\\ \right) ", LaTeXParser.MathListToLaTeX(list).ToString());
556+
}
557+
[Theory]
558+
[InlineData(@"\left(\\\right)")]
559+
[InlineData(@"\left( \\ \right) ")]
560+
[InlineData(@"\left({\\}\right) ")]
561+
[InlineData(@"\left({{\\}}\right) ")]
562+
public void TestEmptyTableInInner(string input) {
563+
var list = ParseLaTeX(input);
564+
CheckAtom<Inner>("", inner => {
565+
Assert.Equal(new Boundary("("), inner.LeftBoundary);
566+
Assert.Equal(new Boundary(")"), inner.RightBoundary);
567+
CheckAtom<Table>("", table => {
568+
Assert.Null(table.Environment);
569+
Assert.Equal(1, table.InterRowAdditionalSpacing);
570+
Assert.Equal(0, table.InterColumnSpacing);
571+
Assert.Equal(2, table.NRows);
572+
Assert.Equal(1, table.NColumns);
573+
for (int col = 0; col < 1; col++) {
574+
Assert.Equal(ColumnAlignment.Left, table.GetAlignment(col));
575+
for (int row = 0; row < 2; row++) {
576+
Assert.Empty(table.Cells[row][col]);
577+
}
578+
}
579+
})(Assert.Single(inner.InnerList));
580+
})(Assert.Single(list));
581+
Assert.Equal(@"\left( \\ \right) ", LaTeXParser.MathListToLaTeX(list).ToString());
582+
}
583+
[Theory]
584+
[InlineData(@"x\\1\left(2\right)3\\x")]
585+
[InlineData(@"x\\ 1\left( 2\right) 3\\ x")]
586+
public void TestInnerInTable(string input) {
587+
var list = ParseLaTeX(input);
588+
CheckAtom<Table>("", table => {
589+
Assert.Null(table.Environment);
590+
Assert.Equal(1, table.InterRowAdditionalSpacing);
591+
Assert.Equal(0, table.InterColumnSpacing);
592+
Assert.Equal(3, table.NRows);
593+
Assert.Equal(1, table.NColumns);
594+
for (int col = 0; col < 1; col++) {
595+
Assert.Equal(ColumnAlignment.Left, table.GetAlignment(col));
596+
for (int row = 0; row < 3; row++) {
597+
if (row == 1)
598+
Assert.Collection(
599+
table.Cells[row][col],
600+
CheckAtom<Number>("1"),
601+
CheckAtom<Inner>("", inner => {
602+
Assert.Equal(new Boundary("("), inner.LeftBoundary);
603+
Assert.Collection(inner.InnerList, CheckAtom<Number>("2"));
604+
Assert.Equal(new Boundary(")"), inner.RightBoundary);
605+
}),
606+
CheckAtom<Number>("3")
607+
);
608+
else
609+
Assert.Collection(
610+
table.Cells[row][col],
611+
CheckAtom<Variable>("x")
612+
);
613+
}
614+
}
615+
})(Assert.Single(list));
616+
Assert.Equal(@"x\\ 1\left( 2\right) 3\\ x", LaTeXParser.MathListToLaTeX(list).ToString());
617+
}
618+
[Theory]
619+
[InlineData(@"1\\2\left(3\begin{array}{ll}4&\left[5\\6\right]\\\left\{7\begin{cases}8\\9\end{cases}0\right\}a\end{array}b\right)c\\d", 0)]
620+
[InlineData(@"1\\ 2\left( 3\begin{array}{ll}4&\left[ 5\\ 6\right] \\ \left\{ 7\left\{ \, \begin{array}{l}\textstyle 8\\ \textstyle 9\end{array}\right. 0\right\} a\end{array}b\right) c\\ d", 1)]
621+
public void TestTablesAndInners(string input, float casesInterRowAdditionalSpacing) {
622+
var list = ParseLaTeX(input);
623+
CheckAtom<Table>("", table => {
624+
Assert.Null(table.Environment);
625+
Assert.Equal(1, table.InterRowAdditionalSpacing);
626+
Assert.Equal(0, table.InterColumnSpacing);
627+
Assert.Equal(3, table.NRows);
628+
Assert.Equal(1, table.NColumns);
629+
Assert.Equal(ColumnAlignment.Left, table.GetAlignment(0));
630+
Assert.Equal(ColumnAlignment.Center, table.GetAlignment(1));
631+
Assert.Collection(table.Cells[0][0], CheckAtom<Number>("1"));
632+
Assert.Collection(table.Cells[1][0],
633+
CheckAtom<Number>("2"),
634+
CheckAtom<Inner>("", inner => {
635+
Assert.Equal(new Boundary("("), inner.LeftBoundary);
636+
Assert.Equal(new Boundary(")"), inner.RightBoundary);
637+
Assert.Collection(inner.InnerList,
638+
CheckAtom<Number>("3"),
639+
CheckAtom<Table>("", array => {
640+
Assert.Equal("array", array.Environment);
641+
Assert.Equal(1, array.InterRowAdditionalSpacing);
642+
Assert.Equal(18, array.InterColumnSpacing);
643+
Assert.Equal(2, array.NRows);
644+
Assert.Equal(2, array.NColumns);
645+
Assert.Equal(ColumnAlignment.Left, array.GetAlignment(0));
646+
Assert.Equal(ColumnAlignment.Left, array.GetAlignment(1));
647+
Assert.Equal(ColumnAlignment.Center, array.GetAlignment(2));
648+
Assert.Collection(array.Cells[0][0], CheckAtom<Number>("4"));
649+
Assert.Collection(array.Cells[0][1], CheckAtom<Inner>("", inner56 => {
650+
Assert.Equal(new Boundary("["), inner56.LeftBoundary);
651+
Assert.Equal(new Boundary("]"), inner56.RightBoundary);
652+
Assert.Collection(inner56.InnerList, CheckAtom<Table>("", table56 => {
653+
Assert.Null(table56.Environment);
654+
Assert.Equal(1, table56.InterRowAdditionalSpacing);
655+
Assert.Equal(0, table56.InterColumnSpacing);
656+
Assert.Equal(2, table56.NRows);
657+
Assert.Equal(1, table56.NColumns);
658+
Assert.Equal(ColumnAlignment.Left, table56.GetAlignment(0));
659+
Assert.Equal(ColumnAlignment.Center, table56.GetAlignment(1));
660+
Assert.Collection(table56.Cells[0][0], CheckAtom<Number>("5"));
661+
Assert.Collection(table56.Cells[1][0], CheckAtom<Number>("6"));
662+
}));
663+
}));
664+
Assert.Collection(array.Cells[1][0],
665+
CheckAtom<Inner>("", innerCases => {
666+
Assert.Equal(new Boundary("{"), innerCases.LeftBoundary);
667+
Assert.Equal(new Boundary("}"), innerCases.RightBoundary);
668+
Assert.Collection(innerCases.InnerList,
669+
CheckAtom<Number>("7"),
670+
CheckAtom<Inner>("", innerCasesInner => {
671+
Assert.Equal(new Boundary("{"), innerCasesInner.LeftBoundary);
672+
Assert.Equal(Boundary.Empty, innerCasesInner.RightBoundary);
673+
Assert.Collection(innerCasesInner.InnerList,
674+
CheckAtom<Space>("", space => Assert.Equal(3, space.Length)),
675+
CheckAtom<Table>("", tableCases => {
676+
Assert.Equal("array", tableCases.Environment);
677+
Assert.Equal(casesInterRowAdditionalSpacing, tableCases.InterRowAdditionalSpacing);
678+
Assert.Equal(18, tableCases.InterColumnSpacing);
679+
Assert.Equal(2, tableCases.NRows);
680+
Assert.Equal(1, tableCases.NColumns);
681+
Assert.Equal(ColumnAlignment.Left, tableCases.GetAlignment(0));
682+
Assert.Equal(ColumnAlignment.Center, tableCases.GetAlignment(1));
683+
Assert.Collection(tableCases.Cells[0][0],
684+
CheckAtom<Style>("", style => Assert.Equal(LineStyle.Text, style.LineStyle)),
685+
CheckAtom<Number>("8"));
686+
Assert.Collection(tableCases.Cells[1][0],
687+
CheckAtom<Style>("", style => Assert.Equal(LineStyle.Text, style.LineStyle)),
688+
CheckAtom<Number>("9"));
689+
})
690+
);
691+
}),
692+
CheckAtom<Number>("0")
693+
);
694+
}),
695+
CheckAtom<Variable>("a")
696+
);
697+
}),
698+
CheckAtom<Variable>("b")
699+
);
700+
}),
701+
CheckAtom<Variable>("c"));
702+
Assert.Collection(table.Cells[2][0], CheckAtom<Variable>("d"));
703+
})(Assert.Single(list));
704+
Assert.Equal(@"1\\ 2\left( 3\begin{array}{ll}4&\left[ 5\\ 6\right] \\ \left\{ 7\left\{ \, \begin{array}{l}\textstyle 8\\ \textstyle 9\end{array}\right. 0\right\} a\end{array}b\right) c\\ d", LaTeXParser.MathListToLaTeX(list).ToString());
705+
}
706+
476707
[Fact]
477708
public void TestTableWithColumns() {
478709
var list = ParseLaTeX(@"x & y \\ z & w");
@@ -1017,7 +1248,7 @@ public void TestHelpfulErrorMessage(string input, int index, string expected) {
10171248
InlineData(@"1+\left", @"Error: Missing delimiter for left
10181249
1+\left
10191250
↑ (pos 7)"),
1020-
InlineData(@"\left{", @"Error: Missing \right
1251+
InlineData(@"\left{", @"Error: Missing \right for \left with delimiter {
10211252
\left{
10221253
↑ (pos 6)"),
10231254
InlineData(@"\left(\frac12\right", @"Error: Missing delimiter for right
@@ -1038,10 +1269,10 @@ public void TestHelpfulErrorMessage(string input, int index, string expected) {
10381269
InlineData(@"5 + 3 \right)", @"Error: Missing \left
10391270
5 + 3 \right)
10401271
↑ (pos 12)"),
1041-
InlineData(@"\left(\frac12", @"Error: Missing \right
1272+
InlineData(@"\left(\frac12", @"Error: Missing \right for \left with delimiter (
10421273
\left(\frac12
10431274
↑ (pos 13)"),
1044-
InlineData(@"\left(5 + \left| \frac12 \right)", @"Error: Missing \right
1275+
InlineData(@"\left(5 + \left| \frac12 \right)", @"Error: Missing \right for \left with delimiter (
10451276
···left| \frac12 \right)
10461277
↑ (pos 32)"),
10471278
InlineData(@"5+ \left|\frac12\right| \right)", @"Error: Missing \left
@@ -1059,7 +1290,10 @@ public void TestHelpfulErrorMessage(string input, int index, string expected) {
10591290
InlineData(@"\begin{matrix parens}", @"Error: Missing }
10601291
\begin{matrix parens}
10611292
↑ (pos 14)"), // no spaces in env
1062-
InlineData(@"\begin{matrix} x", @"Error: Missing \end
1293+
InlineData(@"\begin{matrix}", @"Error: Missing \end for \begin{matrix}
1294+
\begin{matrix}
1295+
↑ (pos 14)"),
1296+
InlineData(@"\begin{matrix} x", @"Error: Missing \end for \begin{matrix}
10631297
\begin{matrix} x
10641298
↑ (pos 16)"),
10651299
InlineData(@"\begin{matrix} x \end", @"Error: Missing {
@@ -1107,6 +1341,9 @@ public void TestHelpfulErrorMessage(string input, int index, string expected) {
11071341
InlineData(@"\color{red blue}{xyz}", @"Error: Missing }
11081342
\color{red blue}{xyz}
11091343
↑ (pos 11)"),
1344+
InlineData(@"\left(\begin{matrix}\right)", @"Error: Missing \end{matrix}
1345+
···(\begin{matrix}\right)
1346+
↑ (pos 26)"),
11101347
]
11111348
public void TestErrors(string badInput, string expected) {
11121349
var (list, actual) = LaTeXParser.MathListFromLaTeX(badInput);

CSharpMath.Forms.Example/CSharpMath.Forms.Example/TryPage.xaml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
<StackLayout>
99
<Entry x:Name="Entry" HorizontalOptions="FillAndExpand"/>
1010
<Label x:Name="Exit" HorizontalOptions="FillAndExpand"/>
11-
<Picker x:Name="Size"
12-
HorizontalOptions="Fill"
13-
ItemsSource="{x:Static local:TryPage.FontSizes}"/>
11+
<StackLayout Orientation="Horizontal">
12+
<Picker x:Name="Size"
13+
HorizontalOptions="FillAndExpand"
14+
ItemsSource="{x:Static local:TryPage.FontSizes}"/>
15+
<Button Text="Reset pan" Clicked="Button_Clicked" HorizontalOptions="End"/>
16+
</StackLayout>
1417
<math:MathView x:Name="View"
1518
HorizontalOptions="FillAndExpand"
1619
VerticalOptions="FillAndExpand"

CSharpMath.Forms.Example/CSharpMath.Forms.Example/TryPage.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,8 @@ public TryPage() {
2222
(View.LaTeX, View.ErrorMessage != null ? Color.Red : Color.Black);
2323
};
2424
}
25+
private void Button_Clicked(object sender, System.EventArgs e) {
26+
View.DisplacementX = View.DisplacementY = 0;
27+
}
2528
}
2629
}

CSharpMath.Rendering.Tests/CSharpMath.Rendering.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<PackageReference Include="Avalonia.Skia" Version="0.9.4" />
1212
<PackageReference Include="xunit" Version="2.4.1" />
1313
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
14+
<PackageReference Include="Xunit.SkippableFact" Version="1.4.8" />
1415
<PackageReference Include="coverlet.collector" Version="1.2.0" />
1516
</ItemGroup>
1617

-1.42 KB
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)