Skip to content
28 changes: 28 additions & 0 deletions CSharpMath.Core.Tests/Atom/LaTeXParserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,34 @@ public void TestUnderline() {
Assert.Equal(@"\underline{2}", LaTeXParser.MathListToLaTeX(list).ToString());
}

/// <summary>
/// Test underbrace without under
/// </summary>
[Fact]
public void TestUnderbrace() {
var list = ParseLaTeX(@"\underbrace{x}");

Assert.Collection(list,
CheckAtom<UnderAnnotation>("\u23df", underBrace =>
Assert.Collection(underBrace.InnerList, CheckAtom<Variable>("x"))
)
);
}

/// <summary>
/// Test underbrace with under (not implemented yet)
/// </summary>
// [Fact]
// public void TestUnderbraceWithUnder() {
// var list = ParseLaTeX(@"\underbrace{x}_{y}");

// Assert.Collection(list,
// CheckAtom<UnderAnnotation>("\u23df", underBrace =>
// Assert.Collection(underBrace.InnerList, CheckAtom<Variable>("x"))
// )
// );
// }

[Fact]
public void TestAccent() {
var list = ParseLaTeX(@"\bar x");
Expand Down
30 changes: 30 additions & 0 deletions CSharpMath/Atom/Atoms/UnderAnnotation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace CSharpMath.Atom.Atoms;
/// <summary>
/// Abstract name of under annotations implementation \underbrace, \underbracket etc..
/// </summary>
public sealed class UnderAnnotation : MathAtom, IMathListContainer {
public UnderAnnotation(string value, MathList innerList, MathList? underList = null) : base(value) {
InnerList = innerList;
UnderList = underList;
}

public MathList InnerList { get; }
public MathList? UnderList { get; }

System.Collections.Generic.IEnumerable<MathList> IMathListContainer.InnerLists =>
new[] { InnerList };
public new UnderAnnotation Clone(bool finalize) => (UnderAnnotation)base.Clone(finalize);
protected override MathAtom CloneInside(bool finalize) =>
new UnderAnnotation(Nucleus, InnerList.Clone(finalize), UnderList?.Clone(finalize));
public override bool ScriptsAllowed => true;
//depending on nucleus, DebugString will change to \underbrace , \underbracket etc..
public override string DebugString =>
new System.Text.StringBuilder(@"\underbrace")
.AppendInBracesOrLiteralNull(InnerList.DebugString)
.ToString();
public bool EqualsUnderAnnotation(UnderAnnotation other) =>
EqualsAtom(other) && InnerList.EqualsList(other.InnerList);
public override bool Equals(object obj) =>
obj is UnderAnnotation u ? EqualsUnderAnnotation(u) : false;
public override int GetHashCode() => (base.GetHashCode(), InnerList).GetHashCode();
}
8 changes: 8 additions & 0 deletions CSharpMath/Atom/LaTeXParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,14 @@ static bool MathAtomToLaTeX(MathAtom atom, StringBuilder builder,
builder.Append(@"\underline{");
MathListToLaTeX(under.InnerList, builder, currentFontStyle);
builder.Append('}');
break;
case UnderAnnotation underAnotation:
if (MathAtomToLaTeX(underAnotation, builder, out var underAnnotationCommand)) {
builder.Append(@$"\{underAnnotationCommand}{{");
MathListToLaTeX(underAnotation.InnerList, builder, currentFontStyle);
builder.Append('}');
}

break;
case Accent accent:
MathAtomToLaTeX(accent, builder, out _);
Expand Down
3 changes: 3 additions & 0 deletions CSharpMath/Atom/LaTeXSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ public static class LaTeXSettings {
parser.ReadArgument().Bind(mathList => Ok(new Overline(mathList))) },
{ @"\underline", (parser, accumulate, stopChar) =>
parser.ReadArgument().Bind(mathList => Ok(new Underline(mathList))) },
{ @"\underbrace", (parser, accumulate, stopChar) =>
parser.ReadArgument().Bind(mathList => Ok(new UnderAnnotation("\u23df", mathList)))},
//Adding under element should happen when adding sub script later or here?
{ @"\begin", (parser, accumulate, stopChar) =>
parser.ReadEnvironment().Bind(env =>
parser.ReadTable(env, null, false, stopChar)).Bind(Ok) },
Expand Down
Loading