From 45df37dcce97aa5a13f9f9d775a2921fdd6d6289 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Tue, 11 Aug 2020 10:31:11 +0100 Subject: [PATCH 01/16] Tidy MathListIndex --- .../Extensions/FractionDisplay.cs | 31 ++-- CSharpMath.Editor/Extensions/IGlyphDisplay.cs | 4 +- CSharpMath.Editor/Extensions/InnerDisplay.cs | 8 +- .../Extensions/LargeOpLimitsDisplay.cs | 16 +- CSharpMath.Editor/Extensions/ListDisplay.cs | 38 +++-- CSharpMath.Editor/MathKeyboard.cs | 2 +- CSharpMath.Editor/MathListIndex.cs | 138 +++++++++++------- CSharpMath.Editor/MathListRange.cs | 8 +- .../SubIndexTypeMismatchException.cs | 6 +- 9 files changed, 140 insertions(+), 111 deletions(-) diff --git a/CSharpMath.Editor/Extensions/FractionDisplay.cs b/CSharpMath.Editor/Extensions/FractionDisplay.cs index 13b59ad3..1db87663 100644 --- a/CSharpMath.Editor/Extensions/FractionDisplay.cs +++ b/CSharpMath.Editor/Extensions/FractionDisplay.cs @@ -17,32 +17,31 @@ public static MathListIndex IndexForPoint( //We are after the fraction ? MathListIndex.Level0Index(self.Range.End) : point.Y > self.LinePosition + PixelDelta - ? MathListIndex.IndexAtLocation(self.Range.Location, - MathListSubIndexType.Numerator, self.Numerator.IndexForPoint(context, point)) + ? new MathListIndex(self.Range.Location, + (MathListSubIndexType.Numerator, self.Numerator.IndexForPoint(context, point)!)) // TODO: validate that IndexForPoint is non-null : point.Y < self.LinePosition - PixelDelta - ? MathListIndex.IndexAtLocation(self.Range.Location, - MathListSubIndexType.Denominator, self.Denominator.IndexForPoint(context, point)) + ? new MathListIndex(self.Range.Location, + (MathListSubIndexType.Denominator, self.Denominator.IndexForPoint(context, point)!)) // TODO: validate that IndexForPoint is non-null : point.X > self.Position.X + self.Width / 2 ? MathListIndex.Level0Index(self.Range.End) : MathListIndex.Level0Index(self.Range.Location); public static PointF? PointForIndex( - this FractionDisplay self, - TypesettingContext _, - MathListIndex index) where TFont : IFont => - index.SubIndexType != MathListSubIndexType.None - ? throw new ArgumentException - ("The subindex must be none to get the closest point for it.", nameof(index)) - : index.AtomIndex == self.Range.End - // draw a caret after the fraction - ? self.Position.Plus(new PointF(self.DisplayBounds().Right, 0)) - // draw a caret before the fraction - : self.Position; + this FractionDisplay self, + TypesettingContext _, + MathListIndex index) where TFont : IFont => + index.SubIndexInfo == null ? + (index.AtomIndex == self.Range.End + // draw a caret after the fraction + ? self.Position.Plus(new PointF(self.DisplayBounds().Right, 0)) + // draw a caret before the fraction + : self.Position) + : throw new ArgumentException("The subindex must be none to get the closest point for it.", nameof(index)); public static void HighlightCharacterAt( this FractionDisplay self, MathListIndex index, Color color) where TFont : IFont { - if (index.SubIndexType != MathListSubIndexType.None) + if (index.SubIndexInfo != null) throw new ArgumentException ("The subindex must be none to get the highlight a character in it.", nameof(index)); self.Highlight(color); diff --git a/CSharpMath.Editor/Extensions/IGlyphDisplay.cs b/CSharpMath.Editor/Extensions/IGlyphDisplay.cs index c287f91c..62926d32 100644 --- a/CSharpMath.Editor/Extensions/IGlyphDisplay.cs +++ b/CSharpMath.Editor/Extensions/IGlyphDisplay.cs @@ -17,7 +17,7 @@ public static MathListIndex IndexForPoint( this IGlyphDisplay self, TypesettingContext _, MathListIndex index) where TFont : IFont => - index.SubIndexType != MathListSubIndexType.None + index.SubIndexInfo != null ? throw new ArgumentException ("The subindex must be none to get the closest point for it.", nameof(index)) : index.AtomIndex == self.Range.End @@ -29,7 +29,7 @@ public static MathListIndex IndexForPoint( public static void HighlightCharacterAt( this IGlyphDisplay self, MathListIndex index, Color color) where TFont : IFont { - if (index.SubIndexType != MathListSubIndexType.None) + if (index.SubIndexInfo != null) throw new ArgumentException ("The subindex must be none to get the highlight a character in it.", nameof(index)); self.Highlight(color); diff --git a/CSharpMath.Editor/Extensions/InnerDisplay.cs b/CSharpMath.Editor/Extensions/InnerDisplay.cs index 941a314a..0946b28a 100644 --- a/CSharpMath.Editor/Extensions/InnerDisplay.cs +++ b/CSharpMath.Editor/Extensions/InnerDisplay.cs @@ -16,14 +16,14 @@ public static MathListIndex IndexForPoint( : point.X > self.Position.X + self.Width - (self.Right?.Width / 2 ?? 0) //We are after the inner ? MathListIndex.Level0Index(self.Range.End) - : MathListIndex.IndexAtLocation(self.Range.Location, - MathListSubIndexType.Inner, self.Inner.IndexForPoint(context, point)); + : new MathListIndex(self.Range.Location, + (MathListSubIndexType.Inner, self.Inner.IndexForPoint(context, point)!)); // TODO: verify non-null public static PointF? PointForIndex( this InnerDisplay self, TypesettingContext _, MathListIndex index) where TFont : IFont => - index.SubIndexType != MathListSubIndexType.None + index.SubIndexInfo != null ? throw new ArgumentException ("The subindex must be none to get the closest point for it.", nameof(index)) : index.AtomIndex == self.Range.End @@ -35,7 +35,7 @@ public static MathListIndex IndexForPoint( public static void HighlightCharacterAt( this InnerDisplay self, MathListIndex index, Color color) where TFont : IFont { - if (index.SubIndexType != MathListSubIndexType.None) + if (index.SubIndexInfo != null) throw new ArgumentException ("The subindex must be none to get the highlight a character in it.", nameof(index)); self.Highlight(color); diff --git a/CSharpMath.Editor/Extensions/LargeOpLimitsDisplay.cs b/CSharpMath.Editor/Extensions/LargeOpLimitsDisplay.cs index 2f37f37e..c2e732ad 100644 --- a/CSharpMath.Editor/Extensions/LargeOpLimitsDisplay.cs +++ b/CSharpMath.Editor/Extensions/LargeOpLimitsDisplay.cs @@ -18,23 +18,23 @@ public static MathListIndex IndexForPoint( // We are after the large operator ? MathListIndex.Level0Index(self.Range.End) : self.UpperLimit is { } u && point.Y > self.Position.Y + u.Position.Y - PixelDelta - ? MathListIndex.IndexAtLocation(self.Range.Location, - MathListSubIndexType.Superscript, u.IndexForPoint(context, point)) + ? new MathListIndex(self.Range.Location, + (MathListSubIndexType.Superscript, u.IndexForPoint(context, point)!)) // TODO: verify non-null : self.LowerLimit is { } l && point.Y < self.Position.Y + l.Position.Y + l.DisplayBounds().Height + PixelDelta - ? MathListIndex.IndexAtLocation(self.Range.Location, - MathListSubIndexType.Subscript, l.IndexForPoint(context, point)) + ? new MathListIndex(self.Range.Location, + (MathListSubIndexType.Subscript, l.IndexForPoint(context, point)!)) // TODO: verify non-null : point.X > self.Position.X + self.Width * 3 / 4 ? MathListIndex.Level0Index(self.Range.End) : point.X > self.Position.X + self.Width / 2 - ? MathListIndex.IndexAtLocation(self.Range.Location, - MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)) + ? new MathListIndex(self.Range.Location, + (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))) : MathListIndex.Level0Index(self.Range.Location); public static PointF? PointForIndex( this LargeOpLimitsDisplay self, TypesettingContext _, MathListIndex index) where TFont : IFont => - index.SubIndexType != MathListSubIndexType.None + index.SubIndexInfo != null ? throw new ArgumentException ("The subindex must be none to get the closest point for it.", nameof(index)) : index.AtomIndex == self.Range.End @@ -46,7 +46,7 @@ public static MathListIndex IndexForPoint( public static void HighlightCharacterAt( this LargeOpLimitsDisplay self, MathListIndex index, Color color) where TFont : IFont { - if (index.SubIndexType != MathListSubIndexType.None) + if (index.SubIndexInfo != null) throw new ArgumentException ("The subindex must be none to get the highlight a character in it.", nameof(index)); self.Highlight(color); diff --git a/CSharpMath.Editor/Extensions/ListDisplay.cs b/CSharpMath.Editor/Extensions/ListDisplay.cs index 1d97117b..08b14bbd 100644 --- a/CSharpMath.Editor/Extensions/ListDisplay.cs +++ b/CSharpMath.Editor/Extensions/ListDisplay.cs @@ -1,8 +1,11 @@ namespace CSharpMath.Editor { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Drawing; using System.Linq; + using System.Threading; + using CSharpMath.Atom; using Display; using Display.Displays; using Display.FrontEnd; @@ -89,43 +92,38 @@ closestLine.LinePosition is LinePosition.Subscript if (closestLine.IndexInParent is int.MinValue) throw new ArgumentException ($"Index was not set for a {indexType} in the {nameof(ListDisplay)}.", nameof(self)); - return MathListIndex.IndexAtLocation(closestLine.IndexInParent, indexType, index); + return new MathListIndex(closestLine.IndexInParent, (indexType, index!)); // TODO: verify non-null } else if (displayWithPoint.HasScript) // The display list has a subscript or a superscript. // If the index is at the end of the atom, // then we need to put it before the sub/super script rather than after. if (index?.AtomIndex == displayWithPoint.Range.End) - return MathListIndex.IndexAtLocation - (index.AtomIndex - 1, MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); + return new MathListIndex( + index.AtomIndex - 1, (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))); return index; } public static PointF? PointForIndex (this ListDisplay self, TypesettingContext context, MathListIndex index) where TFont : IFont { - if (index is null) return null; PointF? position; if (index.AtomIndex == self.Range.End) { // Special case the edge of the range position = new PointF(self.Width, 0); - } else if (self.Range.Contains(index.AtomIndex) + } + else if (self.Range.Contains(index.AtomIndex) && self.SubDisplayForIndex(index) is IDisplay display) - switch (index.SubIndexType) { - case MathListSubIndexType.BetweenBaseAndScripts when index.SubIndex != null: - var nucleusPosition = index.AtomIndex + index.SubIndex.AtomIndex; - position = display.PointForIndex(context, MathListIndex.Level0Index(nucleusPosition)); - break; - case MathListSubIndexType.None: - position = display.PointForIndex(context, index); - break; - case var _ when index.SubIndex != null: - // Recurse - position = display.PointForIndex(context, index.SubIndex); - break; - default: - throw new ArgumentException("index.Subindex is null despite a non-None subindex type"); - } else + { + position = index.SubIndexInfo switch + { + (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex subIndex) => + display.PointForIndex(context, MathListIndex.Level0Index(index.AtomIndex + subIndex.AtomIndex)), + null => display.PointForIndex(context, index), + (_, MathListIndex subIndex) => display.PointForIndex(context, subIndex) + }; + } + else // Outside the range return null; if (position is PointF found) { diff --git a/CSharpMath.Editor/MathKeyboard.cs b/CSharpMath.Editor/MathKeyboard.cs index 104aaec8..a894a10e 100644 --- a/CSharpMath.Editor/MathKeyboard.cs +++ b/CSharpMath.Editor/MathKeyboard.cs @@ -148,7 +148,7 @@ static bool IsFullPlaceholderRequired(MathAtom mathAtom) => SetScript(prevAtom, LaTeXSettings.PlaceholderList); } _insertionIndex = prevIndexCorrected.LevelUpWithSubIndex - (subIndexType, MathListIndex.Level0Index(0)); + ((subIndexType, MathListIndex.Level0Index(0))); } } } diff --git a/CSharpMath.Editor/MathListIndex.cs b/CSharpMath.Editor/MathListIndex.cs index cb880cd3..aaeb18e5 100644 --- a/CSharpMath.Editor/MathListIndex.cs +++ b/CSharpMath.Editor/MathListIndex.cs @@ -1,8 +1,9 @@ +using System; +using System.Text.RegularExpressions; + namespace CSharpMath.Editor { ///The type of the subindex denotes what branch the path to the atom that this index points to takes. public enum MathListSubIndexType : byte { - ///The index denotes the whole atom, subIndex is null - None = 0, ///The position in the subindex is an index into the nucleus, must be 1 BetweenBaseAndScripts, ///The subindex indexes into the superscript @@ -37,36 +38,37 @@ public enum MathListSubIndexType : byte { * The level of an index is the number of nodes in the LinkedList to get to the final path. * */ public class MathListIndex { - private MathListIndex() { } ///The index of the associated atom. public int AtomIndex { get; set; } - ///The type of subindex, e.g. superscript, numerator etc. - public MathListSubIndexType SubIndexType { get; set; } - ///The index into the sublist. - public MathListIndex? SubIndex; + + public (MathListSubIndexType SubIndexType, MathListIndex SubIndex)? SubIndexInfo; + + public void ReplaceWith(MathListIndex replacement) { + AtomIndex = replacement.AtomIndex; + SubIndexInfo = replacement.SubIndexInfo; + } /** Factory function to create a `MathListIndex` with no subindexes. The index of the atom that the `MathListIndex` points at. */ - public static MathListIndex Level0Index(int index) => new MathListIndex { AtomIndex = index }; - /** Factory function to create at `MathListIndex` with a given subIndex. - The location at which the subIndex should is present. - The subIndex to be added. Can be nil. - The type of the subIndex. - */ - public static MathListIndex IndexAtLocation(int location, MathListSubIndexType type, MathListIndex? subIndex) => - new MathListIndex { AtomIndex = location, SubIndexType = type, SubIndex = subIndex }; + public static MathListIndex Level0Index(int index) => new MathListIndex(index, null); + public MathListIndex(int atomIndex, (MathListSubIndexType SubIndexType, MathListIndex SubIndex)? subIndexInfo) { + AtomIndex = atomIndex; + SubIndexInfo = subIndexInfo; + } ///Creates a new index by attaching this index at the end of the current one. - public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, MathListIndex? subIndex) => - SubIndexType is MathListSubIndexType.None ? IndexAtLocation(AtomIndex, type, subIndex) : - IndexAtLocation(AtomIndex, SubIndexType, SubIndex?.LevelUpWithSubIndex(type, subIndex)); + public MathListIndex LevelUpWithSubIndex((MathListSubIndexType SubIndexType, MathListIndex SubIndex)? subIndexInfo) => + SubIndexInfo == null ? new MathListIndex(AtomIndex, subIndexInfo) : + new MathListIndex(AtomIndex, + (SubIndexInfo.Value.SubIndexType, SubIndexInfo.Value.SubIndex.LevelUpWithSubIndex(subIndexInfo))); ///Creates a new index by removing the last index item. If this is the last one, then returns nil. public MathListIndex? LevelDown() => - SubIndexType is MathListSubIndexType.None ? null : - SubIndex?.LevelDown() is MathListIndex subIndex ? IndexAtLocation(AtomIndex, SubIndexType, subIndex) : - Level0Index(AtomIndex); + SubIndexInfo is null ? null : + SubIndexInfo.Value.SubIndex.LevelDown() is MathListIndex subIndex + ? new MathListIndex(AtomIndex, (SubIndexInfo.Value.SubIndexType, subIndex)) : + Level0Index(AtomIndex); /** * Returns the previous index if this index is not at the beginning of a line. @@ -75,58 +77,86 @@ public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, MathListInde * This returns if there is no previous index, i.e. * the innermost subindex points to the beginning of a line. */ - public MathListIndex? Previous => SubIndexType switch + public MathListIndex? Previous => SubIndexInfo switch { - MathListSubIndexType.None => AtomIndex > 0 ? Level0Index(AtomIndex - 1) : null, - _ => SubIndex?.Previous is MathListIndex prevSubIndex ? IndexAtLocation(AtomIndex, SubIndexType, prevSubIndex) : null, + null => AtomIndex > 0 ? Level0Index(AtomIndex - 1) : null, + (MathListSubIndexType SubIndexType, MathListIndex SubIndex) => + SubIndex.Previous is MathListIndex prevSubIndex + ? new MathListIndex(AtomIndex, (SubIndexType, prevSubIndex)) + : null, }; ///Returns the next index. - public MathListIndex Next => SubIndexType switch + public MathListIndex Next => SubIndexInfo switch { - MathListSubIndexType.None => Level0Index(AtomIndex + 1), - MathListSubIndexType.BetweenBaseAndScripts => IndexAtLocation(AtomIndex + 1, SubIndexType, SubIndex), - _ => IndexAtLocation(AtomIndex, SubIndexType, SubIndex?.Next), + null => Level0Index(AtomIndex + 1), + (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex _) => + new MathListIndex(AtomIndex + 1, SubIndexInfo), + (MathListSubIndexType subIndexType, MathListIndex index) => + new MathListIndex(AtomIndex, (subIndexType, index.Next)) }; ///Returns true if any of the subIndexes of this index have the given type. public bool HasSubIndexOfType(MathListSubIndexType subIndexType) => - SubIndexType == subIndexType ? true : - SubIndex != null ? SubIndex.HasSubIndexOfType(subIndexType) : false; - + SubIndexInfo switch + { + null => false, + (MathListSubIndexType subIndexType2, MathListIndex subIndex) => + subIndexType == subIndexType2 || subIndex.HasSubIndexOfType(subIndexType) + }; + /// Same, or differing only with respect to the final AtomIdex. public bool AtSameLevel(MathListIndex other) => - SubIndexType != other.SubIndexType ? false : - // No subindexes, they are at the same level. - SubIndexType == MathListSubIndexType.None ? true : - // the subindexes are used in different atoms - AtomIndex != other.AtomIndex ? false : - SubIndex != null && other.SubIndex != null ? SubIndex.AtSameLevel(other.SubIndex) : - // No subindexes, they are at the same level. - true; + (SubIndexInfo, other.SubIndexInfo) switch + { + (null, null) => true, + ((_, _), null) => false, + (null, (_, _)) => false, + ((MathListSubIndexType aType, MathListIndex aIndex), (MathListSubIndexType bType, MathListIndex bIndex)) => + aType == bType && AtomIndex == other.AtomIndex && aIndex.AtSameLevel(bIndex) + }; public int FinalIndex => - SubIndexType is MathListSubIndexType.None || SubIndex is null ? AtomIndex : SubIndex.FinalIndex; + SubIndexInfo switch + { + null => AtomIndex, + (_, MathListIndex subIndex) => subIndex.FinalIndex + }; ///Returns the type of the innermost sub index. - public MathListSubIndexType FinalSubIndexType => - SubIndex?.SubIndex is null ? SubIndexType : SubIndex.FinalSubIndexType; - - public MathListIndex FinalSubIndexParent => - SubIndex?.SubIndex is null ? this : SubIndex.FinalSubIndexParent; + public MathListSubIndexType? FinalSubIndexType => + SubIndexInfo switch + { + null => null, + (MathListSubIndexType type, MathListIndex subIndex) => + subIndex.SubIndexInfo == null ? type : subIndex.FinalSubIndexType + }; public override string ToString() => - SubIndex is null ? - $@"[{AtomIndex}]" : - $@"[{AtomIndex}, {SubIndexType}:{SubIndex.ToString().Trim('[', ']')}]"; + SubIndexInfo switch + { + null => $@"[{AtomIndex}]", + (MathListSubIndexType type, MathListIndex subIndex) => + $@"[{AtomIndex}, {type}:{subIndex.ToString().Trim('[', ']')}]" + }; - public bool EqualsToIndex(MathListIndex index) => - index is null || AtomIndex != index.AtomIndex || SubIndexType != index.SubIndexType ? false : - SubIndex != null && index.SubIndex != null ? SubIndex.EqualsToIndex(index.SubIndex) : - index.SubIndex == null; + public bool EqualsToIndex(MathListIndex other) => + (SubIndexInfo, other.SubIndexInfo) switch + { + (null, null) => true, + ((_, _), null) => false, + (null, (_, _)) => false, + ((MathListSubIndexType aType, MathListIndex aIndex), (MathListSubIndexType bType, MathListIndex bIndex)) => + aType == bType && aIndex.EqualsToIndex(bIndex) + }; public override bool Equals(object obj) => obj is MathListIndex index && EqualsToIndex(index); - public override int GetHashCode() => - unchecked((AtomIndex * 31 + (int)SubIndexType) * 31 + (SubIndex?.GetHashCode() ?? -1)); + public override int GetHashCode() => unchecked( + SubIndexInfo switch + { + null => AtomIndex * 31 - 1, + (MathListSubIndexType type, MathListIndex subIndex) => + AtomIndex * 31 +(int)type * 31 + subIndex.GetHashCode() + }); } } \ No newline at end of file diff --git a/CSharpMath.Editor/MathListRange.cs b/CSharpMath.Editor/MathListRange.cs index ab3e9ac2..04b83788 100644 --- a/CSharpMath.Editor/MathListRange.cs +++ b/CSharpMath.Editor/MathListRange.cs @@ -16,9 +16,11 @@ public MathListRange(Range range) => public MathListIndex Start { get; } public int Length { get; } public MathListRange? SubIndexRange => - Start.SubIndex != null - ? new MathListRange(Start.SubIndex, Length) - : new MathListRange?(); + Start.SubIndexInfo switch + { + null => new MathListRange?(), + (_, MathListIndex subIndex) => new MathListRange(subIndex, Length) + }; public Range FinalRange => new Range(Start.FinalIndex, Length); public override string ToString() => $"({Start}, {Length})"; public static MathListRange operator +(MathListRange left, MathListRange right) { diff --git a/CSharpMath.Editor/SubIndexTypeMismatchException.cs b/CSharpMath.Editor/SubIndexTypeMismatchException.cs index 3333cd00..7faf4cef 100644 --- a/CSharpMath.Editor/SubIndexTypeMismatchException.cs +++ b/CSharpMath.Editor/SubIndexTypeMismatchException.cs @@ -7,8 +7,8 @@ public class SubIndexTypeMismatchException : InvalidOperationException { public SubIndexTypeMismatchException(Type atomType, MathListIndex index) : base( $"{atomType} not found at index {index.AtomIndex}.") { } public SubIndexTypeMismatchException(MathListIndex index) : base( - Array.IndexOf(typeof(MathListSubIndexType).GetEnumValues(), index.SubIndexType) == -1 - ? $"{index.SubIndexType} is an invalid subindex type." - : $"{index.SubIndexType} not found at index {index.AtomIndex}.") { } + Array.IndexOf(typeof(MathListSubIndexType).GetEnumValues(), index.SubIndexInfo!.Value.SubIndexType) == -1 + ? $"{index.SubIndexInfo!.Value.SubIndexType} is an invalid subindex type." + : $"{index.SubIndexInfo!.Value.SubIndexType} not found at index {index.AtomIndex}.") { } } } From ea1dacf49b7ee4a9ee3c743d17785c5e1df6feb9 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Tue, 11 Aug 2020 12:36:39 +0100 Subject: [PATCH 02/16] builds --- .editorconfig | 4 +- CSharpMath.Editor.Tests/IndexForPointTests.cs | 9 +- CSharpMath.Editor/Extensions/ListDisplay.cs | 50 +-- CSharpMath.Editor/Extensions/MathList.cs | 334 ++++++++++-------- .../Extensions/RadicalDisplay.cs | 10 +- .../Extensions/TextLineDisplay.cs | 6 +- CSharpMath.Editor/MathKeyboard.cs | 66 ++-- 7 files changed, 263 insertions(+), 216 deletions(-) diff --git a/.editorconfig b/.editorconfig index aa8fd5de..aec79a9a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -19,11 +19,11 @@ dotnet_sort_system_directives_first = true # C# formatting settings # https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference#c-formatting-settings csharp_new_line_before_catch = false -csharp_new_line_before_else = false +#csharp_new_line_before_else = false csharp_new_line_before_finally = false csharp_new_line_before_members_in_object_initializers = false csharp_new_line_before_members_in_anonymous_types = false -csharp_new_line_before_open_brace = none +#csharp_new_line_before_open_brace = none csharp_new_line_between_query_expression_clauses = false # Indentation options diff --git a/CSharpMath.Editor.Tests/IndexForPointTests.cs b/CSharpMath.Editor.Tests/IndexForPointTests.cs index b2a3f5aa..95416ba8 100644 --- a/CSharpMath.Editor.Tests/IndexForPointTests.cs +++ b/CSharpMath.Editor.Tests/IndexForPointTests.cs @@ -19,12 +19,11 @@ public void Add((double x, double y) point, mathListIndex = MathListIndex.Level0Index( subIndexRecursive[^1].subIndex); for (var i = subIndexRecursive.Length - 2; i >= 0; i--) - mathListIndex = MathListIndex.IndexAtLocation( + mathListIndex = new MathListIndex( subIndexRecursive[i].subIndex, - subIndexRecursive[i + 1].subType, - mathListIndex); - mathListIndex = MathListIndex.IndexAtLocation(index, - subIndexRecursive[0].subType, mathListIndex); + (subIndexRecursive[i + 1].subType, mathListIndex)); + mathListIndex = new MathListIndex(index, + (subIndexRecursive[0].subType, mathListIndex)); goto default; default: AddRow(new PointF((float)point.x, (float)point.y), mathListIndex); diff --git a/CSharpMath.Editor/Extensions/ListDisplay.cs b/CSharpMath.Editor/Extensions/ListDisplay.cs index 08b14bbd..b2a560a2 100644 --- a/CSharpMath.Editor/Extensions/ListDisplay.cs +++ b/CSharpMath.Editor/Extensions/ListDisplay.cs @@ -138,14 +138,18 @@ closestLine.LinePosition is LinePosition.Subscript public static void HighlightCharacterAt(this ListDisplay self, MathListIndex index, Color color) where TFont : IFont { - if (self.Range.Contains(index.AtomIndex) - && self.SubDisplayForIndex(index) is IDisplay display) - if (index.SubIndexType is MathListSubIndexType.BetweenBaseAndScripts - || index.SubIndexType is MathListSubIndexType.None) - display.HighlightCharacterAt(index, color); - else if (index.SubIndex != null) - // Recurse - display.HighlightCharacterAt(index.SubIndex, color); + if (self.Range.Contains(index.AtomIndex) && self.SubDisplayForIndex(index) is IDisplay display) + { + switch (index.SubIndexInfo) { + case (MathListSubIndexType.BetweenBaseAndScripts, _): + case null: + display.HighlightCharacterAt(index, color); break; + case (_, MathListIndex subIndex): + // Recurse + display.HighlightCharacterAt(subIndex, color); break; + default:break; + } + } } public static void Highlight(this ListDisplay self, Color color) @@ -157,43 +161,43 @@ public static void Highlight(this ListDisplay self public static IDisplay? SubDisplayForIndex( this ListDisplay self, MathListIndex index) where TFont : IFont { // Inside the range - if (index.SubIndexType is MathListSubIndexType.Superscript - || index.SubIndexType is MathListSubIndexType.Subscript) + if (index.SubIndexInfo is (MathListSubIndexType.Superscript,_) + || index.SubIndexInfo is (MathListSubIndexType.Subscript,_)) foreach (var display in self.Displays) switch (display) { case ListDisplay list when index.AtomIndex == list.IndexInParent // This is the right character for the sub/superscript, check that it's type matches the index && (list.LinePosition is LinePosition.Subscript - && index.SubIndexType is MathListSubIndexType.Subscript + && index.SubIndexInfo is (MathListSubIndexType.Subscript,_) || list.LinePosition is LinePosition.Superscript - && index.SubIndexType is MathListSubIndexType.Superscript): + && index.SubIndexInfo is (MathListSubIndexType.Superscript,_)): return list; case LargeOpLimitsDisplay largeOps when largeOps.Range.Contains(index.AtomIndex): - return index.SubIndexType is MathListSubIndexType.Subscript + return index.SubIndexInfo is (MathListSubIndexType.Subscript,_) ? largeOps.LowerLimit : largeOps.UpperLimit; } else foreach (var display in self.Displays) if (!(display is ListDisplay) && display.Range.Contains(index.AtomIndex)) //not a subscript/superscript and ... jackpot, the the index is in the range of this atom. - switch (index.SubIndexType) { - case MathListSubIndexType.None: - case MathListSubIndexType.BetweenBaseAndScripts: + switch (index.SubIndexInfo) { + case null: + case (MathListSubIndexType.BetweenBaseAndScripts, _): return display; - case MathListSubIndexType.Degree when display is RadicalDisplay radical: + case (MathListSubIndexType.Degree, _) when display is RadicalDisplay radical: return radical.Degree; - case MathListSubIndexType.Radicand when display is RadicalDisplay radical: + case (MathListSubIndexType.Radicand, _) when display is RadicalDisplay radical: return radical.Radicand; - case MathListSubIndexType.Numerator when display is FractionDisplay fraction: + case (MathListSubIndexType.Numerator, _) when display is FractionDisplay fraction: return fraction.Numerator; - case MathListSubIndexType.Denominator when display is FractionDisplay fraction: + case (MathListSubIndexType.Denominator, _) when display is FractionDisplay fraction: return fraction.Denominator; - case MathListSubIndexType.Inner when display is InnerDisplay inner: + case (MathListSubIndexType.Inner, _) when display is InnerDisplay inner: return inner.Inner; - case MathListSubIndexType.Superscript: - case MathListSubIndexType.Subscript: + case (MathListSubIndexType.Superscript, _): + case (MathListSubIndexType.Subscript, _): throw new InvalidCodePathException ("Superscripts and subscripts should have been handled in a separate case above."); default: diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index 050f0870..2019482a 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -5,7 +5,7 @@ namespace CSharpMath.Editor { using Atoms = Atom.Atoms; using Structures; partial class Extensions { - static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathAtom atom, ref MathListIndex advance, MathListSubIndexType advanceType) { + static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathAtom atom, ref MathListIndex advance, MathListSubIndexType? advanceType) { if (atomIndex < 0 || atomIndex > self.Count) throw new IndexOutOfRangeException($"Index {atomIndex} is out of bounds for list of size {self.Atoms.Count}"); // Test for placeholder to the right of index, e.g. \sqrt{‸■} -> \sqrt{2‸} @@ -16,22 +16,20 @@ static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathA } else self.Insert(atomIndex, atom); advance = advanceType switch { - MathListSubIndexType.None => advance.Next, - _ => advance.LevelUpWithSubIndex(advanceType, MathListIndex.Level0Index(0)), + null => advance.Next, + MathListSubIndexType advanceT => advance.LevelUpWithSubIndex((advanceT, MathListIndex.Level0Index(0))), }; } /// Inserts and modifies to advance to the next position. - public static void InsertAndAdvance(this MathList self, ref MathListIndex index, MathAtom atom, MathListSubIndexType advanceType) { + public static void InsertAndAdvance(this MathList self, ref MathListIndex index, MathAtom atom, MathListSubIndexType? advanceType) { index ??= MathListIndex.Level0Index(0); if (index.AtomIndex > self.Atoms.Count) throw new IndexOutOfRangeException($"Index {index.AtomIndex} is out of bounds for list of size {self.Atoms.Count}"); - switch (index.SubIndexType) { - case MathListSubIndexType.None: + switch (index.SubIndexInfo) { + case null: self.InsertAtAtomIndexAndAdvance(index.AtomIndex, atom, ref index, advanceType); break; - case var _ when index.SubIndex is null: - throw new InvalidCodePathException("index.SubIndex is null despite non-None subindex type"); - case MathListSubIndexType.BetweenBaseAndScripts: + case (MathListSubIndexType.BetweenBaseAndScripts,_): var currentAtom = self.Atoms[index.AtomIndex]; if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) throw new SubIndexTypeMismatchException(index); @@ -43,37 +41,48 @@ public static void InsertAndAdvance(this MathList self, ref MathListIndex index, currentAtom.Superscript.Clear(); var atomIndex = index.AtomIndex; // Prevent further subindexing inside BetweenBaseAndScripts - if (advanceType != MathListSubIndexType.None + if (advanceType != null && index.LevelDown() is MathListIndex levelDown) index = levelDown.Next; self.InsertAtAtomIndexAndAdvance(atomIndex + 1, atom, ref index, advanceType); break; - case MathListSubIndexType.Degree: - case MathListSubIndexType.Radicand: - if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); - if (index.SubIndexType == MathListSubIndexType.Degree) - radical.Degree.InsertAndAdvance(ref index.SubIndex, atom, advanceType); - else radical.Radicand.InsertAndAdvance(ref index.SubIndex, atom, advanceType); - break; - case MathListSubIndexType.Numerator: - case MathListSubIndexType.Denominator: - if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); - if (index.SubIndexType == MathListSubIndexType.Numerator) - frac.Numerator.InsertAndAdvance(ref index.SubIndex, atom, advanceType); - else - frac.Denominator.InsertAndAdvance(ref index.SubIndex, atom, advanceType); - break; - case MathListSubIndexType.Subscript: - self.Atoms[index.AtomIndex].Subscript.InsertAndAdvance(ref index.SubIndex, atom, advanceType); + case (MathListSubIndexType.Degree, MathListIndex subIndex): + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); + radical.Degree.InsertAndAdvance(ref subIndex, atom, advanceType); + break; + } + case (MathListSubIndexType.Radicand, MathListIndex subIndex): + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); + radical.Radicand.InsertAndAdvance(ref subIndex, atom, advanceType); + break; + } + case (MathListSubIndexType.Numerator, MathListIndex subIndex): + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); + frac.Numerator.InsertAndAdvance(ref subIndex, atom, advanceType); + break; + } + case (MathListSubIndexType.Denominator, MathListIndex subIndex): + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); + frac.Denominator.InsertAndAdvance(ref subIndex, atom, advanceType); + break; + } + case (MathListSubIndexType.Subscript, MathListIndex subIndex): + self.Atoms[index.AtomIndex].Subscript.InsertAndAdvance(ref subIndex, atom, advanceType); break; - case MathListSubIndexType.Superscript: - self.Atoms[index.AtomIndex].Superscript.InsertAndAdvance(ref index.SubIndex, atom, advanceType); + case (MathListSubIndexType.Superscript, MathListIndex subIndex): + self.Atoms[index.AtomIndex].Superscript.InsertAndAdvance(ref subIndex, atom, advanceType); break; - case MathListSubIndexType.Inner: + case (MathListSubIndexType.Inner, MathListIndex subIndex): if (!(self.Atoms[index.AtomIndex] is Atoms.Inner inner)) throw new SubIndexTypeMismatchException(typeof(Atoms.Inner), index); - inner.InnerList.InsertAndAdvance(ref index.SubIndex, atom, advanceType); + inner.InnerList.InsertAndAdvance(ref subIndex, atom, advanceType); break; default: throw new SubIndexTypeMismatchException(index); @@ -84,89 +93,102 @@ public static void RemoveAt(this MathList self, ref MathListIndex index) { index ??= MathListIndex.Level0Index(0); if (index.AtomIndex > self.Atoms.Count) throw new IndexOutOfRangeException($"Index {index.AtomIndex} is out of bounds for list of size {self.Atoms.Count}"); - switch (index.SubIndexType) { - case MathListSubIndexType.None: + switch (index.SubIndexInfo) { + case null: self.RemoveAt(index.AtomIndex); break; - case var _ when index.SubIndex is null: - throw new InvalidCodePathException("index.SubIndex is null despite non-None subindex type"); - case MathListSubIndexType.BetweenBaseAndScripts: - var currentAtom = self.Atoms[index.AtomIndex]; - if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) - throw new SubIndexTypeMismatchException(index); - var downIndex = index.LevelDown(); - if (downIndex is null) throw new InvalidCodePathException("downIndex is null"); - if (index.AtomIndex > 0 && - self.Atoms[index.AtomIndex - 1] is MathAtom previous && - previous.Subscript.IsEmpty() && - previous.Superscript.IsEmpty() && - previous switch - { - Atoms.BinaryOperator _ => false, - Atoms.UnaryOperator _ => false, - Atoms.Relation _ => false, - Atoms.Punctuation _ => false, - Atoms.Space _ => false, - _ => true - }) { - previous.Superscript.Append(currentAtom.Superscript); - previous.Subscript.Append(currentAtom.Subscript); + case (MathListSubIndexType.BetweenBaseAndScripts,_): + { + var currentAtom = self.Atoms[index.AtomIndex]; + if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) + throw new SubIndexTypeMismatchException(index); + var downIndex = index.LevelDown(); + if (downIndex is null) throw new InvalidCodePathException("downIndex is null"); + if (index.AtomIndex > 0 && + self.Atoms[index.AtomIndex - 1] is MathAtom previous && + previous.Subscript.IsEmpty() && + previous.Superscript.IsEmpty() && + previous switch + { + Atoms.BinaryOperator _ => false, + Atoms.UnaryOperator _ => false, + Atoms.Relation _ => false, + Atoms.Punctuation _ => false, + Atoms.Space _ => false, + _ => true + }) + { + previous.Superscript.Append(currentAtom.Superscript); + previous.Subscript.Append(currentAtom.Subscript); + self.RemoveAt(index.AtomIndex); + // it was in the nucleus and we removed it, get out of the nucleus and get in the nucleus of the previous one. + index = downIndex.Previous is MathListIndex downPrev + ? downPrev.LevelUpWithSubIndex((MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))) + : downIndex; + break; + } + // insert placeholder since we couldn't place the scripts in previous atom + var insertionAtom = LaTeXSettings.Placeholder; + insertionAtom.Subscript.Append(currentAtom.Subscript); + insertionAtom.Superscript.Append(currentAtom.Superscript); self.RemoveAt(index.AtomIndex); - // it was in the nucleus and we removed it, get out of the nucleus and get in the nucleus of the previous one. - index = downIndex.Previous is MathListIndex downPrev - ? downPrev.LevelUpWithSubIndex(MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)) - : downIndex; + index = downIndex; + self.InsertAndAdvance(ref index, insertionAtom, null); + index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); + return; + } + case (MathListSubIndexType.Radicand, MathListIndex subIndex): + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); + radical.Radicand.RemoveAt(ref subIndex); break; } - // insert placeholder since we couldn't place the scripts in previous atom - var insertionAtom = LaTeXSettings.Placeholder; - insertionAtom.Subscript.Append(currentAtom.Subscript); - insertionAtom.Superscript.Append(currentAtom.Superscript); - self.RemoveAt(index.AtomIndex); - index = downIndex; - self.InsertAndAdvance(ref index, insertionAtom, MathListSubIndexType.None); - index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); - return; - case MathListSubIndexType.Radicand: - case MathListSubIndexType.Degree: - if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); - if (index.SubIndexType == MathListSubIndexType.Degree) - radical.Degree.RemoveAt(ref index.SubIndex); - else radical.Radicand.RemoveAt(ref index.SubIndex); - break; - case MathListSubIndexType.Numerator: - case MathListSubIndexType.Denominator: - if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); - if (index.SubIndexType == MathListSubIndexType.Numerator) - frac.Numerator.RemoveAt(ref index.SubIndex); - else frac.Denominator.RemoveAt(ref index.SubIndex); - break; - case MathListSubIndexType.Subscript: + case (MathListSubIndexType.Degree, MathListIndex subIndex): + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); + radical.Degree.RemoveAt(ref subIndex); + break; + } + case (MathListSubIndexType.Numerator, MathListIndex subIndex): + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); + frac.Numerator.RemoveAt(ref subIndex); + break; + } + case (MathListSubIndexType.Denominator, MathListIndex subIndex): + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); + frac.Denominator.RemoveAt(ref subIndex); + break; + } + case (MathListSubIndexType.Subscript, MathListIndex subIndex): var current = self.Atoms[index.AtomIndex]; if (current.Subscript.IsEmpty()) throw new SubIndexTypeMismatchException(index); - current.Subscript.RemoveAt(ref index.SubIndex); + current.Subscript.RemoveAt(ref subIndex); break; - case MathListSubIndexType.Superscript: + case (MathListSubIndexType.Superscript, MathListIndex subIndex): current = self.Atoms[index.AtomIndex]; if (current.Superscript.IsEmpty()) throw new SubIndexTypeMismatchException(index); - current.Superscript.RemoveAt(ref index.SubIndex); + current.Superscript.RemoveAt(ref subIndex); break; - case MathListSubIndexType.Inner: + case (MathListSubIndexType.Inner, MathListIndex subIndex): if (!(self.Atoms[index.AtomIndex] is Atoms.Inner inner)) throw new SubIndexTypeMismatchException(typeof(Atoms.Inner), index); - inner.InnerList.RemoveAt(ref index.SubIndex); + inner.InnerList.RemoveAt(ref subIndex); break; default: throw new SubIndexTypeMismatchException(index); } - if (index.Previous is null && index.SubIndexType != MathListSubIndexType.None) { + if (index.Previous is null && index.SubIndexInfo != null) { // We have deleted to the beginning of the line and it is not the outermost line if (self.AtomAt(index) is null) { - self.InsertAndAdvance(ref index, LaTeXSettings.Placeholder, MathListSubIndexType.None); + self.InsertAndAdvance(ref index, LaTeXSettings.Placeholder, null); index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); ; } } @@ -175,41 +197,53 @@ public static void RemoveAt(this MathList self, ref MathListIndex index) { public static void RemoveAtoms(this MathList self, MathListRange? nullableRange) { if (!(nullableRange is MathListRange range)) return; var start = range.Start; - switch (start.SubIndexType) { - case MathListSubIndexType.None: + switch (start.SubIndexInfo) { + case null: self.RemoveAtoms(start.AtomIndex, range.Length); break; - case var _ when start.SubIndex is null: - throw new InvalidCodePathException("start.SubIndex is null despite non-None subindex type"); - case MathListSubIndexType.BetweenBaseAndScripts: + case (MathListSubIndexType.BetweenBaseAndScripts,_): throw new NotSupportedException("Nuclear fission is not supported"); - case MathListSubIndexType.Radicand: - case MathListSubIndexType.Degree: - if (!(self.Atoms[start.AtomIndex] is Atoms.Radical radical)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), start); - if (start.SubIndexType == MathListSubIndexType.Degree) - radical.Degree.RemoveAtoms(range.SubIndexRange); - else radical.Radicand.RemoveAtoms(range.SubIndexRange); - break; - case MathListSubIndexType.Numerator: - case MathListSubIndexType.Denominator: - if (!(self.Atoms[start.AtomIndex] is Atoms.Fraction frac)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), start); - if (start.SubIndexType == MathListSubIndexType.Numerator) + case (MathListSubIndexType.Radicand, _): + { + if (!(self.Atoms[start.AtomIndex] is Atoms.Radical radical)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), start); + radical.Radicand.RemoveAtoms(range.SubIndexRange); + break; + } + case (MathListSubIndexType.Degree, _): + { + if (!(self.Atoms[start.AtomIndex] is Atoms.Radical radical)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), start); + radical.Radicand.RemoveAtoms(range.SubIndexRange); + break; + } + case (MathListSubIndexType.Numerator,_): + { + if (!(self.Atoms[start.AtomIndex] is Atoms.Fraction frac)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), start); frac.Numerator.RemoveAtoms(range.SubIndexRange); - else frac.Denominator.RemoveAtoms(range.SubIndexRange); - break; - case MathListSubIndexType.Subscript: + break; + } + case (MathListSubIndexType.Denominator,_): + { + if (!(self.Atoms[start.AtomIndex] is Atoms.Fraction frac)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), start); + if (start.SubIndexInfo is (MathListSubIndexType.Numerator,_)) + frac.Numerator.RemoveAtoms(range.SubIndexRange); + else frac.Denominator.RemoveAtoms(range.SubIndexRange); + break; + } + case (MathListSubIndexType.Subscript,_): var current = self.Atoms[start.AtomIndex]; if (current.Subscript.IsEmpty()) throw new SubIndexTypeMismatchException(start); current.Subscript.RemoveAtoms(range.SubIndexRange); break; - case MathListSubIndexType.Superscript: + case (MathListSubIndexType.Superscript,_): current = self.Atoms[start.AtomIndex]; if (current.Superscript.IsEmpty()) throw new SubIndexTypeMismatchException(start); current.Superscript.RemoveAtoms(range.SubIndexRange); break; - case MathListSubIndexType.Inner: + case (MathListSubIndexType.Inner,_): if (!(self.Atoms[start.AtomIndex] is Atoms.Inner inner)) throw new SubIndexTypeMismatchException(typeof(Atoms.Inner), start); inner.InnerList.RemoveAtoms(range.SubIndexRange); @@ -220,35 +254,45 @@ public static void RemoveAtoms(this MathList self, MathListRange? nullableRange) public static MathAtom? AtomAt(this MathList self, MathListIndex? index) { if (index is null || index.AtomIndex >= self.Atoms.Count) return null; var atom = self.Atoms[index.AtomIndex]; - switch (index.SubIndexType) { - case MathListSubIndexType.None: + switch (index.SubIndexInfo) { + case null: return atom; - case var _ when index.SubIndex is null: - throw new InvalidCodePathException("index.SubIndex is null despite non-None subindex type"); - case MathListSubIndexType.BetweenBaseAndScripts: + case (MathListSubIndexType.BetweenBaseAndScripts,_): return null; - case MathListSubIndexType.Subscript: - return atom.Subscript.AtomAt(index.SubIndex); - case MathListSubIndexType.Superscript: - return atom.Superscript.AtomAt(index.SubIndex); - case MathListSubIndexType.Radicand: - case MathListSubIndexType.Degree: - return - atom is Atoms.Radical radical - ? index.SubIndexType == MathListSubIndexType.Degree - ? radical.Degree.AtomAt(index.SubIndex) - : radical.Radicand.AtomAt(index.SubIndex) - : null; - case MathListSubIndexType.Numerator: - case MathListSubIndexType.Denominator: - return - atom is Atoms.Fraction frac - ? index.SubIndexType == MathListSubIndexType.Denominator - ? frac.Denominator.AtomAt(index.SubIndex) - : frac.Numerator.AtomAt(index.SubIndex) - : null; - case MathListSubIndexType.Inner: - return atom is Atoms.Inner inner ? inner.InnerList.AtomAt(index.SubIndex) : null; + case (MathListSubIndexType.Subscript, MathListIndex subIndex): + return atom.Subscript.AtomAt(subIndex); + case (MathListSubIndexType.Superscript, MathListIndex subIndex): + return atom.Superscript.AtomAt(subIndex); + case (MathListSubIndexType.Radicand, MathListIndex subIndex): + { + return + atom is Atoms.Radical radical + ? radical.Radicand.AtomAt(subIndex) + : null; + } + case (MathListSubIndexType.Degree, MathListIndex subIndex): + { + return + atom is Atoms.Radical radical + ? radical.Degree.AtomAt(subIndex) + : null; + } + case (MathListSubIndexType.Numerator, MathListIndex subIndex): + { + return + atom is Atoms.Fraction frac + ? frac.Numerator.AtomAt(subIndex) + : null; + } + case (MathListSubIndexType.Denominator, MathListIndex subIndex): + { + return + atom is Atoms.Fraction frac + ? frac.Denominator.AtomAt(subIndex) + : null; + } + case (MathListSubIndexType.Inner, MathListIndex subIndex): + return atom is Atoms.Inner inner ? inner.InnerList.AtomAt(subIndex) : null; default: throw new SubIndexTypeMismatchException(index); } diff --git a/CSharpMath.Editor/Extensions/RadicalDisplay.cs b/CSharpMath.Editor/Extensions/RadicalDisplay.cs index 56fcdc05..29648e69 100644 --- a/CSharpMath.Editor/Extensions/RadicalDisplay.cs +++ b/CSharpMath.Editor/Extensions/RadicalDisplay.cs @@ -20,15 +20,15 @@ public static MathListIndex IndexForPoint( : DistanceFromPointToRect(point, self.Degree != null ? new RectangleF(self.Degree.Position, self.Degree.DisplayBounds().Size) : default) < DistanceFromPointToRect(point, new RectangleF(self.Radicand.Position, self.Radicand.DisplayBounds().Size)) ? self.Degree != null - ? MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Degree, self.Degree.IndexForPoint(context, point)) + ? new MathListIndex(self.Range.Location, (MathListSubIndexType.Degree, self.Degree.IndexForPoint(context, point)!)) // TODO: verify/handle null : MathListIndex.Level0Index(self.Range.Location) - : MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Radicand, self.Radicand.IndexForPoint(context, point)); - + : new MathListIndex(self.Range.Location, (MathListSubIndexType.Radicand, self.Radicand.IndexForPoint(context, point)!)); // TODO: verify/handle null + public static PointF? PointForIndex( this RadicalDisplay self, TypesettingContext _, MathListIndex index) where TFont : IFont { - if (index.SubIndexType != MathListSubIndexType.None) + if (index.SubIndexInfo != null) throw new ArgumentException("The subindex must be none to get the closest point for it.", nameof(index)); if (index.AtomIndex == self.Range.End) @@ -42,7 +42,7 @@ public static void HighlightCharacterAt( this RadicalDisplay self, MathListIndex index, Color color) where TFont : IFont { - if (index.SubIndexType != MathListSubIndexType.None) + if (index.SubIndexInfo != null) throw new ArgumentException("The subindex must be none to get the highlight a character in it.", nameof(index)); self.Highlight(color); } diff --git a/CSharpMath.Editor/Extensions/TextLineDisplay.cs b/CSharpMath.Editor/Extensions/TextLineDisplay.cs index 4fd9ed97..87743618 100644 --- a/CSharpMath.Editor/Extensions/TextLineDisplay.cs +++ b/CSharpMath.Editor/Extensions/TextLineDisplay.cs @@ -142,7 +142,7 @@ public static int StringIndexToCodepointIndex(System.Text.StringBuilder str, int (this TextLineDisplay self, TypesettingContext context, MathListIndex index) where TFont : IFont { float offset; - if (!(index.SubIndexType is MathListSubIndexType.None)) + if (!(index.SubIndexInfo is null)) throw new ArgumentException ($"An index in a {nameof(TextLineDisplay)} cannot have sub-indexes.", nameof(index)); if (index.AtomIndex == self.Range.End) @@ -165,10 +165,10 @@ public static void HighlightCharacterAt if (!self.Range.Contains(index.AtomIndex)) throw new ArgumentOutOfRangeException (nameof(index), index, $"The index is not in the range {self.Range}."); - if (index.SubIndexType is MathListSubIndexType.None) + if (index.SubIndexInfo is null) throw new ArgumentException ("The subindex type must not be none to be able to highlight it.", nameof(index)); - if (index.SubIndexType is MathListSubIndexType.BetweenBaseAndScripts) + if (index.SubIndexInfo is (MathListSubIndexType.BetweenBaseAndScripts,_)) throw new ArgumentException("Nucleus highlighting is not supported.", nameof(index)); // index is in unicode code points, while attrString is not var (run, charIndex) = self.GetRunAndCharIndexFromCodepointIndex(index.AtomIndex - self.Range.Location); diff --git a/CSharpMath.Editor/MathKeyboard.cs b/CSharpMath.Editor/MathKeyboard.cs index a894a10e..7f336f08 100644 --- a/CSharpMath.Editor/MathKeyboard.cs +++ b/CSharpMath.Editor/MathKeyboard.cs @@ -181,7 +181,7 @@ void HandleSlashButton() { numerator.Push(new Atoms.Number("1")); if (MathList.AtomAt(_insertionIndex.Previous) is Atoms.Fraction) // Add a times symbol - MathList.InsertAndAdvance(ref _insertionIndex, LaTeXSettings.Times, MathListSubIndexType.None); + MathList.InsertAndAdvance(ref _insertionIndex, LaTeXSettings.Times, null); MathList.InsertAndAdvance(ref _insertionIndex, new Atoms.Fraction( new MathList(numerator), LaTeXSettings.PlaceholderList @@ -199,7 +199,7 @@ void MoveCursorLeft() { case null: // At beginning of line var levelDown = _insertionIndex.LevelDown(); switch (_insertionIndex.FinalSubIndexType) { - case MathListSubIndexType.None: + case null: goto default; case var _ when levelDown is null: throw new InvalidCodePathException("Null levelDown despite non-None FinalSubIndexType"); @@ -209,41 +209,41 @@ void MoveCursorLeft() { throw new InvalidCodePathException("Invalid levelDown"); if (scriptAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Subscript, - MathListIndex.Level0Index(scriptAtom.Subscript.Count)); + ((MathListSubIndexType.Subscript, + MathListIndex.Level0Index(scriptAtom.Subscript.Count))); else goto case MathListSubIndexType.Subscript; break; case MathListSubIndexType.Subscript: _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); + ((MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))); break; case MathListSubIndexType.BetweenBaseAndScripts: if (MathList.AtomAt(levelDown) is Atoms.Radical rad && rad.Radicand.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Radicand, - MathListIndex.Level0Index(rad.Radicand.Count)); + ((MathListSubIndexType.Radicand, + MathListIndex.Level0Index(rad.Radicand.Count))); else if (MathList.AtomAt(levelDown) is Atoms.Fraction frac && frac.Denominator.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Denominator, - MathListIndex.Level0Index(frac.Denominator.Count)); + ((MathListSubIndexType.Denominator, + MathListIndex.Level0Index(frac.Denominator.Count))); else if (MathList.AtomAt(levelDown) is Atoms.Inner inner && inner.InnerList.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Inner, - MathListIndex.Level0Index(inner.InnerList.Count)); + ((MathListSubIndexType.Inner, + MathListIndex.Level0Index(inner.InnerList.Count))); else goto case MathListSubIndexType.Radicand; break; case MathListSubIndexType.Radicand: if (MathList.AtomAt(levelDown) is Atoms.Radical radDeg && radDeg.Degree.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Degree, MathListIndex.Level0Index(radDeg.Degree.Count)); + ((MathListSubIndexType.Degree, MathListIndex.Level0Index(radDeg.Degree.Count))); else goto case MathListSubIndexType.Denominator; break; case MathListSubIndexType.Denominator: if (MathList.AtomAt(levelDown) is Atoms.Fraction fracNum && fracNum.Numerator.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Numerator, MathListIndex.Level0Index(fracNum.Numerator.Count)); + ((MathListSubIndexType.Numerator, MathListIndex.Level0Index(fracNum.Numerator.Count))); else goto default; break; @@ -257,23 +257,23 @@ void MoveCursorLeft() { break; case { Superscript: var s } when s.IsNonEmpty(): _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Superscript, MathListIndex.Level0Index(s.Count)); + ((MathListSubIndexType.Superscript, MathListIndex.Level0Index(s.Count))); break; case { Subscript: var s } when s.IsNonEmpty(): _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Subscript, MathListIndex.Level0Index(s.Count)); + ((MathListSubIndexType.Subscript, MathListIndex.Level0Index(s.Count))); break; case Atoms.Inner { InnerList: var l }: _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Inner, MathListIndex.Level0Index(l.Count)); + ((MathListSubIndexType.Inner, MathListIndex.Level0Index(l.Count))); break; case Atoms.Radical { Radicand: var r }: _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Radicand, MathListIndex.Level0Index(r.Count)); + ((MathListSubIndexType.Radicand, MathListIndex.Level0Index(r.Count))); break; case Atoms.Fraction { Denominator: var d }: _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Denominator, MathListIndex.Level0Index(d.Count)); + ((MathListSubIndexType.Denominator, MathListIndex.Level0Index(d.Count))); break; default: _insertionIndex = prev; @@ -299,7 +299,7 @@ void MoveCursorRight() { var levelDown = _insertionIndex.LevelDown(); var levelDownAtom = MathList.AtomAt(levelDown); switch (_insertionIndex.FinalSubIndexType) { - case MathListSubIndexType.None: + case null: goto default; case var _ when levelDown is null: throw new InvalidCodePathException("Null levelDown despite non-None FinalSubIndexType"); @@ -308,14 +308,14 @@ void MoveCursorRight() { case MathListSubIndexType.Degree: if (levelDownAtom is Atoms.Radical) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Radicand, MathListIndex.Level0Index(0)); + ((MathListSubIndexType.Radicand, MathListIndex.Level0Index(0))); else throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), levelDown); break; case MathListSubIndexType.Numerator: if (levelDownAtom is Atoms.Fraction) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Denominator, MathListIndex.Level0Index(0)); + ((MathListSubIndexType.Denominator, MathListIndex.Level0Index(0))); else throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), levelDown); break; @@ -324,21 +324,21 @@ void MoveCursorRight() { case MathListSubIndexType.Inner: if (levelDownAtom.Superscript.IsNonEmpty() || levelDownAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); + ((MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))); else goto default; break; case MathListSubIndexType.BetweenBaseAndScripts: if (levelDownAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Subscript, MathListIndex.Level0Index(0)); + ((MathListSubIndexType.Subscript, MathListIndex.Level0Index(0))); else goto case MathListSubIndexType.Subscript; break; case MathListSubIndexType.Subscript: if (levelDownAtom.Superscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Superscript, MathListIndex.Level0Index(0)); + ((MathListSubIndexType.Superscript, MathListIndex.Level0Index(0))); else goto default; break; @@ -353,25 +353,25 @@ void MoveCursorRight() { if (levelDown is null) throw new InvalidCodePathException ("_insertionIndex.FinalSubIndexType is BetweenBaseAndScripts but levelDown is null"); - _insertionIndex = levelDown.LevelUpWithSubIndex( + _insertionIndex = levelDown.LevelUpWithSubIndex(( a.Subscript.IsNonEmpty() ? MathListSubIndexType.Subscript : MathListSubIndexType.Superscript, - MathListIndex.Level0Index(0)); + MathListIndex.Level0Index(0))); break; case Atoms.Inner _: - _insertionIndex = _insertionIndex.LevelUpWithSubIndex(MathListSubIndexType.Inner, MathListIndex.Level0Index(0)); + _insertionIndex = _insertionIndex.LevelUpWithSubIndex((MathListSubIndexType.Inner, MathListIndex.Level0Index(0))); break; case Atoms.Fraction _: _insertionIndex = _insertionIndex.LevelUpWithSubIndex - (MathListSubIndexType.Numerator, MathListIndex.Level0Index(0)); + ((MathListSubIndexType.Numerator, MathListIndex.Level0Index(0))); break; case Atoms.Radical rad: - _insertionIndex = _insertionIndex.LevelUpWithSubIndex( + _insertionIndex = _insertionIndex.LevelUpWithSubIndex(( rad.Degree.IsNonEmpty() ? MathListSubIndexType.Degree : MathListSubIndexType.Radicand, - MathListIndex.Level0Index(0)); + MathListIndex.Level0Index(0))); break; case var a when a.Superscript.IsNonEmpty() || a.Subscript.IsNonEmpty(): _insertionIndex = _insertionIndex.LevelUpWithSubIndex - (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); + ((MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))); break; case Atoms.Placeholder _ when MathList.AtomAt(_insertionIndex.Next) is null: // Skip right side of placeholders when end of line @@ -403,7 +403,7 @@ void InsertAtom(MathAtom a) => Atoms.Fraction _ => MathListSubIndexType.Numerator, Atoms.Radical { Degree: { } d } when IsPlaceholderList(d) => MathListSubIndexType.Degree, Atoms.Radical _ => MathListSubIndexType.Radicand, - _ => MathListSubIndexType.None + _ => null }); void InsertSymbolName(string name, bool subscript = false, bool superscript = false) { var atom = @@ -855,7 +855,7 @@ public void InsertMathList(MathList list, PointF point) { // insert at the given index - but don't consider sublevels at this point var index = MathListIndex.Level0Index(detailedIndex.AtomIndex); foreach (var atom in list.Atoms) { - MathList.InsertAndAdvance(ref index, atom, MathListSubIndexType.None); + MathList.InsertAndAdvance(ref index, atom, null); } InsertionIndex = index; // move the index to the end of the new list. } From 1624b51a0ada064597fe457076ec58b3949e1b43 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Tue, 11 Aug 2020 12:42:52 +0100 Subject: [PATCH 03/16] fix --- CSharpMath.Editor/Extensions/MathList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index 2019482a..68bcde11 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -214,7 +214,7 @@ public static void RemoveAtoms(this MathList self, MathListRange? nullableRange) { if (!(self.Atoms[start.AtomIndex] is Atoms.Radical radical)) throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), start); - radical.Radicand.RemoveAtoms(range.SubIndexRange); + radical.Degree.RemoveAtoms(range.SubIndexRange); break; } case (MathListSubIndexType.Numerator,_): From d0629bfbe9bab9809a6c3a5433886cfaa6748175 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Tue, 11 Aug 2020 12:44:17 +0100 Subject: [PATCH 04/16] tidy --- CSharpMath.Editor/Extensions/MathList.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index 68bcde11..17ced7ba 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -228,9 +228,7 @@ public static void RemoveAtoms(this MathList self, MathListRange? nullableRange) { if (!(self.Atoms[start.AtomIndex] is Atoms.Fraction frac)) throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), start); - if (start.SubIndexInfo is (MathListSubIndexType.Numerator,_)) - frac.Numerator.RemoveAtoms(range.SubIndexRange); - else frac.Denominator.RemoveAtoms(range.SubIndexRange); + frac.Denominator.RemoveAtoms(range.SubIndexRange); break; } case (MathListSubIndexType.Subscript,_): From a6946102a1d57c5c47625231d2e496ffadacaf93 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Tue, 11 Aug 2020 13:05:24 +0100 Subject: [PATCH 05/16] tidy --- CSharpMath.Editor/Extensions/MathList.cs | 4 +- CSharpMath.Editor/MathKeyboard.cs | 58 ++++++++++++------------ CSharpMath.Editor/MathListIndex.cs | 12 +++-- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index 17ced7ba..02af0b85 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -17,7 +17,7 @@ static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathA advance = advanceType switch { null => advance.Next, - MathListSubIndexType advanceT => advance.LevelUpWithSubIndex((advanceT, MathListIndex.Level0Index(0))), + MathListSubIndexType advanceT => advance.LevelUpWithSubIndex(advanceT, MathListIndex.Level0Index(0)), }; } /// Inserts and modifies to advance to the next position. @@ -123,7 +123,7 @@ public static void RemoveAt(this MathList self, ref MathListIndex index) { self.RemoveAt(index.AtomIndex); // it was in the nucleus and we removed it, get out of the nucleus and get in the nucleus of the previous one. index = downIndex.Previous is MathListIndex downPrev - ? downPrev.LevelUpWithSubIndex((MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))) + ? downPrev.LevelUpWithSubIndex(MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)) : downIndex; break; } diff --git a/CSharpMath.Editor/MathKeyboard.cs b/CSharpMath.Editor/MathKeyboard.cs index 7f336f08..36695010 100644 --- a/CSharpMath.Editor/MathKeyboard.cs +++ b/CSharpMath.Editor/MathKeyboard.cs @@ -148,7 +148,7 @@ static bool IsFullPlaceholderRequired(MathAtom mathAtom) => SetScript(prevAtom, LaTeXSettings.PlaceholderList); } _insertionIndex = prevIndexCorrected.LevelUpWithSubIndex - ((subIndexType, MathListIndex.Level0Index(0))); + (subIndexType, MathListIndex.Level0Index(0)); } } } @@ -209,41 +209,41 @@ void MoveCursorLeft() { throw new InvalidCodePathException("Invalid levelDown"); if (scriptAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Subscript, - MathListIndex.Level0Index(scriptAtom.Subscript.Count))); + (MathListSubIndexType.Subscript, + MathListIndex.Level0Index(scriptAtom.Subscript.Count)); else goto case MathListSubIndexType.Subscript; break; case MathListSubIndexType.Subscript: _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))); + (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); break; case MathListSubIndexType.BetweenBaseAndScripts: if (MathList.AtomAt(levelDown) is Atoms.Radical rad && rad.Radicand.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Radicand, - MathListIndex.Level0Index(rad.Radicand.Count))); + (MathListSubIndexType.Radicand, + MathListIndex.Level0Index(rad.Radicand.Count)); else if (MathList.AtomAt(levelDown) is Atoms.Fraction frac && frac.Denominator.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Denominator, - MathListIndex.Level0Index(frac.Denominator.Count))); + (MathListSubIndexType.Denominator, + MathListIndex.Level0Index(frac.Denominator.Count)); else if (MathList.AtomAt(levelDown) is Atoms.Inner inner && inner.InnerList.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Inner, - MathListIndex.Level0Index(inner.InnerList.Count))); + (MathListSubIndexType.Inner, + MathListIndex.Level0Index(inner.InnerList.Count)); else goto case MathListSubIndexType.Radicand; break; case MathListSubIndexType.Radicand: if (MathList.AtomAt(levelDown) is Atoms.Radical radDeg && radDeg.Degree.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Degree, MathListIndex.Level0Index(radDeg.Degree.Count))); + (MathListSubIndexType.Degree, MathListIndex.Level0Index(radDeg.Degree.Count)); else goto case MathListSubIndexType.Denominator; break; case MathListSubIndexType.Denominator: if (MathList.AtomAt(levelDown) is Atoms.Fraction fracNum && fracNum.Numerator.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Numerator, MathListIndex.Level0Index(fracNum.Numerator.Count))); + (MathListSubIndexType.Numerator, MathListIndex.Level0Index(fracNum.Numerator.Count)); else goto default; break; @@ -257,23 +257,23 @@ void MoveCursorLeft() { break; case { Superscript: var s } when s.IsNonEmpty(): _insertionIndex = prev.LevelUpWithSubIndex - ((MathListSubIndexType.Superscript, MathListIndex.Level0Index(s.Count))); + (MathListSubIndexType.Superscript, MathListIndex.Level0Index(s.Count)); break; case { Subscript: var s } when s.IsNonEmpty(): _insertionIndex = prev.LevelUpWithSubIndex - ((MathListSubIndexType.Subscript, MathListIndex.Level0Index(s.Count))); + (MathListSubIndexType.Subscript, MathListIndex.Level0Index(s.Count)); break; case Atoms.Inner { InnerList: var l }: _insertionIndex = prev.LevelUpWithSubIndex - ((MathListSubIndexType.Inner, MathListIndex.Level0Index(l.Count))); + (MathListSubIndexType.Inner, MathListIndex.Level0Index(l.Count)); break; case Atoms.Radical { Radicand: var r }: _insertionIndex = prev.LevelUpWithSubIndex - ((MathListSubIndexType.Radicand, MathListIndex.Level0Index(r.Count))); + (MathListSubIndexType.Radicand, MathListIndex.Level0Index(r.Count)); break; case Atoms.Fraction { Denominator: var d }: _insertionIndex = prev.LevelUpWithSubIndex - ((MathListSubIndexType.Denominator, MathListIndex.Level0Index(d.Count))); + (MathListSubIndexType.Denominator, MathListIndex.Level0Index(d.Count)); break; default: _insertionIndex = prev; @@ -308,14 +308,14 @@ void MoveCursorRight() { case MathListSubIndexType.Degree: if (levelDownAtom is Atoms.Radical) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Radicand, MathListIndex.Level0Index(0))); + (MathListSubIndexType.Radicand, MathListIndex.Level0Index(0)); else throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), levelDown); break; case MathListSubIndexType.Numerator: if (levelDownAtom is Atoms.Fraction) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Denominator, MathListIndex.Level0Index(0))); + (MathListSubIndexType.Denominator, MathListIndex.Level0Index(0)); else throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), levelDown); break; @@ -324,21 +324,21 @@ void MoveCursorRight() { case MathListSubIndexType.Inner: if (levelDownAtom.Superscript.IsNonEmpty() || levelDownAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))); + (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); else goto default; break; case MathListSubIndexType.BetweenBaseAndScripts: if (levelDownAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Subscript, MathListIndex.Level0Index(0))); + (MathListSubIndexType.Subscript, MathListIndex.Level0Index(0)); else goto case MathListSubIndexType.Subscript; break; case MathListSubIndexType.Subscript: if (levelDownAtom.Superscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - ((MathListSubIndexType.Superscript, MathListIndex.Level0Index(0))); + (MathListSubIndexType.Superscript, MathListIndex.Level0Index(0)); else goto default; break; @@ -353,25 +353,25 @@ void MoveCursorRight() { if (levelDown is null) throw new InvalidCodePathException ("_insertionIndex.FinalSubIndexType is BetweenBaseAndScripts but levelDown is null"); - _insertionIndex = levelDown.LevelUpWithSubIndex(( + _insertionIndex = levelDown.LevelUpWithSubIndex( a.Subscript.IsNonEmpty() ? MathListSubIndexType.Subscript : MathListSubIndexType.Superscript, - MathListIndex.Level0Index(0))); + MathListIndex.Level0Index(0)); break; case Atoms.Inner _: - _insertionIndex = _insertionIndex.LevelUpWithSubIndex((MathListSubIndexType.Inner, MathListIndex.Level0Index(0))); + _insertionIndex = _insertionIndex.LevelUpWithSubIndex(MathListSubIndexType.Inner, MathListIndex.Level0Index(0)); break; case Atoms.Fraction _: _insertionIndex = _insertionIndex.LevelUpWithSubIndex - ((MathListSubIndexType.Numerator, MathListIndex.Level0Index(0))); + (MathListSubIndexType.Numerator, MathListIndex.Level0Index(0)); break; case Atoms.Radical rad: - _insertionIndex = _insertionIndex.LevelUpWithSubIndex(( + _insertionIndex = _insertionIndex.LevelUpWithSubIndex( rad.Degree.IsNonEmpty() ? MathListSubIndexType.Degree : MathListSubIndexType.Radicand, - MathListIndex.Level0Index(0))); + MathListIndex.Level0Index(0)); break; case var a when a.Superscript.IsNonEmpty() || a.Subscript.IsNonEmpty(): _insertionIndex = _insertionIndex.LevelUpWithSubIndex - ((MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))); + (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); break; case Atoms.Placeholder _ when MathList.AtomAt(_insertionIndex.Next) is null: // Skip right side of placeholders when end of line diff --git a/CSharpMath.Editor/MathListIndex.cs b/CSharpMath.Editor/MathListIndex.cs index aaeb18e5..ddf5d169 100644 --- a/CSharpMath.Editor/MathListIndex.cs +++ b/CSharpMath.Editor/MathListIndex.cs @@ -59,10 +59,14 @@ public MathListIndex(int atomIndex, (MathListSubIndexType SubIndexType, MathList } ///Creates a new index by attaching this index at the end of the current one. - public MathListIndex LevelUpWithSubIndex((MathListSubIndexType SubIndexType, MathListIndex SubIndex)? subIndexInfo) => - SubIndexInfo == null ? new MathListIndex(AtomIndex, subIndexInfo) : - new MathListIndex(AtomIndex, - (SubIndexInfo.Value.SubIndexType, SubIndexInfo.Value.SubIndex.LevelUpWithSubIndex(subIndexInfo))); + public MathListIndex LevelUpWithSubIndex(MathListSubIndexType subIndexType, MathListIndex subIndex) => + SubIndexInfo switch + { + null => new MathListIndex(AtomIndex, (subIndexType, subIndex)), + (MathListSubIndexType thisSubIndType, MathListIndex thisSubIndex) => + new MathListIndex(AtomIndex, + (thisSubIndType, thisSubIndex.LevelUpWithSubIndex(subIndexType, subIndex))) + }; ///Creates a new index by removing the last index item. If this is the last one, then returns nil. public MathListIndex? LevelDown() => SubIndexInfo is null ? null : From c2a2fbe8000bc08453c3c08fa7463a498b159fac Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Tue, 11 Aug 2020 13:07:38 +0100 Subject: [PATCH 06/16] reduce diff --- CSharpMath.Editor/MathListIndex.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CSharpMath.Editor/MathListIndex.cs b/CSharpMath.Editor/MathListIndex.cs index ddf5d169..2edb4d3d 100644 --- a/CSharpMath.Editor/MathListIndex.cs +++ b/CSharpMath.Editor/MathListIndex.cs @@ -59,13 +59,13 @@ public MathListIndex(int atomIndex, (MathListSubIndexType SubIndexType, MathList } ///Creates a new index by attaching this index at the end of the current one. - public MathListIndex LevelUpWithSubIndex(MathListSubIndexType subIndexType, MathListIndex subIndex) => + public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, MathListIndex subIndex) => SubIndexInfo switch { - null => new MathListIndex(AtomIndex, (subIndexType, subIndex)), + null => new MathListIndex(AtomIndex, (type, subIndex)), (MathListSubIndexType thisSubIndType, MathListIndex thisSubIndex) => new MathListIndex(AtomIndex, - (thisSubIndType, thisSubIndex.LevelUpWithSubIndex(subIndexType, subIndex))) + (thisSubIndType, thisSubIndex.LevelUpWithSubIndex(type, subIndex))) }; ///Creates a new index by removing the last index item. If this is the last one, then returns nil. public MathListIndex? LevelDown() => From 53650f0f18a339076fed8a0487fed88d931705e8 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Tue, 11 Aug 2020 13:15:12 +0100 Subject: [PATCH 07/16] tidy --- CSharpMath.Editor/MathListIndex.cs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/CSharpMath.Editor/MathListIndex.cs b/CSharpMath.Editor/MathListIndex.cs index 2edb4d3d..62797046 100644 --- a/CSharpMath.Editor/MathListIndex.cs +++ b/CSharpMath.Editor/MathListIndex.cs @@ -63,16 +63,20 @@ public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, MathListInde SubIndexInfo switch { null => new MathListIndex(AtomIndex, (type, subIndex)), - (MathListSubIndexType thisSubIndType, MathListIndex thisSubIndex) => + (MathListSubIndexType thisType, MathListIndex thisSubIndex) => new MathListIndex(AtomIndex, - (thisSubIndType, thisSubIndex.LevelUpWithSubIndex(type, subIndex))) + (thisType, thisSubIndex.LevelUpWithSubIndex(type, subIndex))) }; ///Creates a new index by removing the last index item. If this is the last one, then returns nil. public MathListIndex? LevelDown() => - SubIndexInfo is null ? null : - SubIndexInfo.Value.SubIndex.LevelDown() is MathListIndex subIndex - ? new MathListIndex(AtomIndex, (SubIndexInfo.Value.SubIndexType, subIndex)) : - Level0Index(AtomIndex); + SubIndexInfo switch + { + null => null, + (MathListSubIndexType type, MathListIndex subIndex) => + subIndex.LevelDown() is MathListIndex levelledDownSubIndex + ? new MathListIndex(AtomIndex, (type, levelledDownSubIndex)) : + Level0Index(AtomIndex) + }; /** * Returns the previous index if this index is not at the beginning of a line. @@ -84,9 +88,9 @@ public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, MathListInde public MathListIndex? Previous => SubIndexInfo switch { null => AtomIndex > 0 ? Level0Index(AtomIndex - 1) : null, - (MathListSubIndexType SubIndexType, MathListIndex SubIndex) => - SubIndex.Previous is MathListIndex prevSubIndex - ? new MathListIndex(AtomIndex, (SubIndexType, prevSubIndex)) + (MathListSubIndexType type, MathListIndex subIndex) => + subIndex.Previous is MathListIndex prevSubIndex + ? new MathListIndex(AtomIndex, (type, prevSubIndex)) : null, }; @@ -105,8 +109,8 @@ public bool HasSubIndexOfType(MathListSubIndexType subIndexType) => SubIndexInfo switch { null => false, - (MathListSubIndexType subIndexType2, MathListIndex subIndex) => - subIndexType == subIndexType2 || subIndex.HasSubIndexOfType(subIndexType) + (MathListSubIndexType type, MathListIndex subIndex) => + subIndexType == type || subIndex.HasSubIndexOfType(subIndexType) }; /// Same, or differing only with respect to the final AtomIdex. public bool AtSameLevel(MathListIndex other) => From 82f4a778aaa669db307fb1ed196a9393011cb8f3 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Tue, 11 Aug 2020 13:21:18 +0100 Subject: [PATCH 08/16] reduce diff --- CSharpMath.Editor/Extensions/MathList.cs | 72 ++++++++++++------------ 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index 02af0b85..cb1bbb9c 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -97,46 +97,44 @@ public static void RemoveAt(this MathList self, ref MathListIndex index) { case null: self.RemoveAt(index.AtomIndex); break; - case (MathListSubIndexType.BetweenBaseAndScripts,_): + case (MathListSubIndexType.BetweenBaseAndScripts,_): { + var currentAtom = self.Atoms[index.AtomIndex]; + if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) + throw new SubIndexTypeMismatchException(index); + var downIndex = index.LevelDown(); + if (downIndex is null) throw new InvalidCodePathException("downIndex is null"); + if (index.AtomIndex > 0 && + self.Atoms[index.AtomIndex - 1] is MathAtom previous && + previous.Subscript.IsEmpty() && + previous.Superscript.IsEmpty() && + previous switch + { + Atoms.BinaryOperator _ => false, + Atoms.UnaryOperator _ => false, + Atoms.Relation _ => false, + Atoms.Punctuation _ => false, + Atoms.Space _ => false, + _ => true + }) { - var currentAtom = self.Atoms[index.AtomIndex]; - if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) - throw new SubIndexTypeMismatchException(index); - var downIndex = index.LevelDown(); - if (downIndex is null) throw new InvalidCodePathException("downIndex is null"); - if (index.AtomIndex > 0 && - self.Atoms[index.AtomIndex - 1] is MathAtom previous && - previous.Subscript.IsEmpty() && - previous.Superscript.IsEmpty() && - previous switch - { - Atoms.BinaryOperator _ => false, - Atoms.UnaryOperator _ => false, - Atoms.Relation _ => false, - Atoms.Punctuation _ => false, - Atoms.Space _ => false, - _ => true - }) - { - previous.Superscript.Append(currentAtom.Superscript); - previous.Subscript.Append(currentAtom.Subscript); - self.RemoveAt(index.AtomIndex); - // it was in the nucleus and we removed it, get out of the nucleus and get in the nucleus of the previous one. - index = downIndex.Previous is MathListIndex downPrev - ? downPrev.LevelUpWithSubIndex(MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)) - : downIndex; - break; - } - // insert placeholder since we couldn't place the scripts in previous atom - var insertionAtom = LaTeXSettings.Placeholder; - insertionAtom.Subscript.Append(currentAtom.Subscript); - insertionAtom.Superscript.Append(currentAtom.Superscript); + previous.Superscript.Append(currentAtom.Superscript); + previous.Subscript.Append(currentAtom.Subscript); self.RemoveAt(index.AtomIndex); - index = downIndex; - self.InsertAndAdvance(ref index, insertionAtom, null); - index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); - return; + // it was in the nucleus and we removed it, get out of the nucleus and get in the nucleus of the previous one. + index = downIndex.Previous is MathListIndex downPrev + ? downPrev.LevelUpWithSubIndex(MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)) + : downIndex; + break; } + // insert placeholder since we couldn't place the scripts in previous atom + var insertionAtom = LaTeXSettings.Placeholder; + insertionAtom.Subscript.Append(currentAtom.Subscript); + insertionAtom.Superscript.Append(currentAtom.Superscript); + self.RemoveAt(index.AtomIndex); + index = downIndex; + self.InsertAndAdvance(ref index, insertionAtom, null); + index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); + return; } case (MathListSubIndexType.Radicand, MathListIndex subIndex): { if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) From f4b027130475409d3e8401ae90528ee57387c951 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Wed, 12 Aug 2020 08:54:44 +0100 Subject: [PATCH 09/16] tidy --- CSharpMath.Editor/Extensions/MathList.cs | 3 +++ CSharpMath.Editor/MathListIndex.cs | 13 ++----------- NuGet.Config | 6 ++++++ 3 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 NuGet.Config diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index cb1bbb9c..47ad0dcc 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -14,11 +14,14 @@ static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathA atom.Subscript.Append(placeholder.Subscript); self[atomIndex] = atom; } else self.Insert(atomIndex, atom); + System.Diagnostics.Debug.WriteLine("atom: " + atom.ToString()); + System.Diagnostics.Debug.WriteLine("advance: " + advance.ToString()); advance = advanceType switch { null => advance.Next, MathListSubIndexType advanceT => advance.LevelUpWithSubIndex(advanceT, MathListIndex.Level0Index(0)), }; + System.Diagnostics.Debug.WriteLine("advance: " + advance.ToString()); } /// Inserts and modifies to advance to the next position. public static void InsertAndAdvance(this MathList self, ref MathListIndex index, MathAtom atom, MathListSubIndexType? advanceType) { diff --git a/CSharpMath.Editor/MathListIndex.cs b/CSharpMath.Editor/MathListIndex.cs index 62797046..2e2f04f7 100644 --- a/CSharpMath.Editor/MathListIndex.cs +++ b/CSharpMath.Editor/MathListIndex.cs @@ -1,6 +1,3 @@ -using System; -using System.Text.RegularExpressions; - namespace CSharpMath.Editor { ///The type of the subindex denotes what branch the path to the atom that this index points to takes. public enum MathListSubIndexType : byte { @@ -44,14 +41,8 @@ public class MathListIndex { public (MathListSubIndexType SubIndexType, MathListIndex SubIndex)? SubIndexInfo; - public void ReplaceWith(MathListIndex replacement) { - AtomIndex = replacement.AtomIndex; - SubIndexInfo = replacement.SubIndexInfo; - } - - /** Factory function to create a `MathListIndex` with no subindexes. - The index of the atom that the `MathListIndex` points at. - */ + /// Factory function to create a `MathListIndex` with no subindexes. + /// The index of the atom that the `MathListIndex` points at. public static MathListIndex Level0Index(int index) => new MathListIndex(index, null); public MathListIndex(int atomIndex, (MathListSubIndexType SubIndexType, MathListIndex SubIndex)? subIndexInfo) { AtomIndex = atomIndex; diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 00000000..3f0e0034 --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 24c8a5f26ae3bcc6e896ee6d7232713aff982d55 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Wed, 12 Aug 2020 09:19:01 +0100 Subject: [PATCH 10/16] Add debug code --- CSharpMath.Editor/Extensions/MathList.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index 47ad0dcc..1868a4ab 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -4,6 +4,7 @@ namespace CSharpMath.Editor { using Atom; using Atoms = Atom.Atoms; using Structures; + using System.Diagnostics; partial class Extensions { static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathAtom atom, ref MathListIndex advance, MathListSubIndexType? advanceType) { if (atomIndex < 0 || atomIndex > self.Count) @@ -14,18 +15,18 @@ static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathA atom.Subscript.Append(placeholder.Subscript); self[atomIndex] = atom; } else self.Insert(atomIndex, atom); - System.Diagnostics.Debug.WriteLine("atom: " + atom.ToString()); - System.Diagnostics.Debug.WriteLine("advance: " + advance.ToString()); + Debug.WriteLine("InsertAtAtomIndexAndAdvance atom: " + atom.ToString()); + Debug.WriteLine("InsertAtAtomIndexAndAdvance advance before: " + advance.ToString()); advance = advanceType switch { null => advance.Next, MathListSubIndexType advanceT => advance.LevelUpWithSubIndex(advanceT, MathListIndex.Level0Index(0)), }; - System.Diagnostics.Debug.WriteLine("advance: " + advance.ToString()); + Debug.WriteLine("InsertAtAtomIndexAndAdvance advance after: " + advance.ToString()); } /// Inserts and modifies to advance to the next position. public static void InsertAndAdvance(this MathList self, ref MathListIndex index, MathAtom atom, MathListSubIndexType? advanceType) { - index ??= MathListIndex.Level0Index(0); + Debug.WriteLine("InsertAndAdvance index before: " + index.ToString()); if (index.AtomIndex > self.Atoms.Count) throw new IndexOutOfRangeException($"Index {index.AtomIndex} is out of bounds for list of size {self.Atoms.Count}"); switch (index.SubIndexInfo) { @@ -90,6 +91,7 @@ public static void InsertAndAdvance(this MathList self, ref MathListIndex index, default: throw new SubIndexTypeMismatchException(index); } + Debug.WriteLine("InsertAndAdvance index at end: " + index.ToString()); } public static void RemoveAt(this MathList self, ref MathListIndex index) { From af39ff034e602958eb938728684b29bf6d64a98d Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Wed, 12 Aug 2020 20:42:21 +0100 Subject: [PATCH 11/16] Documentation --- CSharpMath.Editor/MathListIndex.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CSharpMath.Editor/MathListIndex.cs b/CSharpMath.Editor/MathListIndex.cs index 2e2f04f7..e9aab30f 100644 --- a/CSharpMath.Editor/MathListIndex.cs +++ b/CSharpMath.Editor/MathListIndex.cs @@ -49,7 +49,7 @@ public MathListIndex(int atomIndex, (MathListSubIndexType SubIndexType, MathList SubIndexInfo = subIndexInfo; } - ///Creates a new index by attaching this index at the end of the current one. + ///Creates a new index by replacing the leaf with IndexInfo (type, subIndex). public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, MathListIndex subIndex) => SubIndexInfo switch { @@ -85,7 +85,8 @@ subIndex.Previous is MathListIndex prevSubIndex : null, }; - ///Returns the next index. + ///Returns the next index. With the exception of BetweenBaseAndScripts, + ///this adds 1 to the AtomIndex of the leaf. public MathListIndex Next => SubIndexInfo switch { null => Level0Index(AtomIndex + 1), From d319df6144ac09cd82771b07e66b221fde1f59b2 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Wed, 12 Aug 2020 23:12:56 +0100 Subject: [PATCH 12/16] wip --- CSharpMath.Editor/Extensions/MathList.cs | 147 ++++++++++++----------- CSharpMath.Editor/MathKeyboard.cs | 50 ++++---- CSharpMath.Editor/MathListIndex.cs | 10 +- 3 files changed, 104 insertions(+), 103 deletions(-) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index 1868a4ab..0a7dcee6 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -6,7 +6,9 @@ namespace CSharpMath.Editor { using Structures; using System.Diagnostics; partial class Extensions { - static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathAtom atom, ref MathListIndex advance, MathListSubIndexType? advanceType) { + /// Inserts at position inside the leaf self, + /// returning a resultant index relative to self. + static MathListIndex InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathAtom atom, MathListSubIndexType? advanceType) { if (atomIndex < 0 || atomIndex > self.Count) throw new IndexOutOfRangeException($"Index {atomIndex} is out of bounds for list of size {self.Atoms.Count}"); // Test for placeholder to the right of index, e.g. \sqrt{‸■} -> \sqrt{2‸} @@ -15,87 +17,88 @@ static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathA atom.Subscript.Append(placeholder.Subscript); self[atomIndex] = atom; } else self.Insert(atomIndex, atom); - Debug.WriteLine("InsertAtAtomIndexAndAdvance atom: " + atom.ToString()); - Debug.WriteLine("InsertAtAtomIndexAndAdvance advance before: " + advance.ToString()); - advance = advanceType switch + return advanceType switch { - null => advance.Next, - MathListSubIndexType advanceT => advance.LevelUpWithSubIndex(advanceT, MathListIndex.Level0Index(0)), + null => MathListIndex.Level0Index(atomIndex + 1), + MathListSubIndexType advanceT => new MathListIndex(atomIndex, (advanceT, MathListIndex.Level0Index(0))), }; - Debug.WriteLine("InsertAtAtomIndexAndAdvance advance after: " + advance.ToString()); } - /// Inserts and modifies to advance to the next position. - public static void InsertAndAdvance(this MathList self, ref MathListIndex index, MathAtom atom, MathListSubIndexType? advanceType) { - Debug.WriteLine("InsertAndAdvance index before: " + index.ToString()); - if (index.AtomIndex > self.Atoms.Count) + /// Inserts at relative to self, + /// returning an updated relative index. + public static MathListIndex InsertAndAdvance(this MathList self, MathListIndex index, MathAtom atom, MathListSubIndexType? advanceType) { + int atomIndex = index.AtomIndex; + if (atomIndex > self.Atoms.Count) throw new IndexOutOfRangeException($"Index {index.AtomIndex} is out of bounds for list of size {self.Atoms.Count}"); switch (index.SubIndexInfo) { case null: - self.InsertAtAtomIndexAndAdvance(index.AtomIndex, atom, ref index, advanceType); - break; - case (MathListSubIndexType.BetweenBaseAndScripts,_): - var currentAtom = self.Atoms[index.AtomIndex]; - if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) - throw new SubIndexTypeMismatchException(index); - if (atom.Subscript.IsNonEmpty() || atom.Superscript.IsNonEmpty()) - throw new ArgumentException("Cannot fuse with an atom that already has a subscript or a superscript"); - atom.Subscript.Append(currentAtom.Subscript); - atom.Superscript.Append(currentAtom.Superscript); - currentAtom.Subscript.Clear(); - currentAtom.Superscript.Clear(); - var atomIndex = index.AtomIndex; - // Prevent further subindexing inside BetweenBaseAndScripts - if (advanceType != null - && index.LevelDown() is MathListIndex levelDown) index = levelDown.Next; - self.InsertAtAtomIndexAndAdvance(atomIndex + 1, atom, ref index, advanceType); - break; - case (MathListSubIndexType.Degree, MathListIndex subIndex): - { - if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); - radical.Degree.InsertAndAdvance(ref subIndex, atom, advanceType); - break; - } - case (MathListSubIndexType.Radicand, MathListIndex subIndex): - { - if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); - radical.Radicand.InsertAndAdvance(ref subIndex, atom, advanceType); - break; - } - case (MathListSubIndexType.Numerator, MathListIndex subIndex): - { - if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); - frac.Numerator.InsertAndAdvance(ref subIndex, atom, advanceType); - break; - } - case (MathListSubIndexType.Denominator, MathListIndex subIndex): - { - if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); - frac.Denominator.InsertAndAdvance(ref subIndex, atom, advanceType); - break; + return self.InsertAtAtomIndexAndAdvance(atomIndex, atom, advanceType); + case (MathListSubIndexType type, MathListIndex subIndex): + switch (type) { + case MathListSubIndexType.BetweenBaseAndScripts: + { + var currentAtom = self.Atoms[index.AtomIndex]; + if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) + throw new SubIndexTypeMismatchException(index); + if (atom.Subscript.IsNonEmpty() || atom.Superscript.IsNonEmpty()) + throw new ArgumentException("Cannot fuse with an atom that already has a subscript or a superscript"); + atom.Subscript.Append(currentAtom.Subscript); + atom.Superscript.Append(currentAtom.Superscript); + currentAtom.Subscript.Clear(); + currentAtom.Superscript.Clear(); + // Prevent further subindexing inside BetweenBaseAndScripts + if (advanceType != null + && index.LevelDown() is MathListIndex levelDown) index = levelDown.Next; + return self.InsertAtAtomIndexAndAdvance(atomIndex + 1, atom, advanceType); + } + case MathListSubIndexType.Degree: + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); + return new MathListIndex(atomIndex, + (MathListSubIndexType.Degree, radical.Degree.InsertAndAdvance(subIndex, atom, advanceType))); + } + case MathListSubIndexType.Radicand: + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); + return new MathListIndex(atomIndex, + (MathListSubIndexType.Radicand, radical.Radicand.InsertAndAdvance(subIndex, atom, advanceType))); + } + case MathListSubIndexType.Numerator: + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); + return new MathListIndex(atomIndex, + (MathListSubIndexType.Radicand, frac.Numerator.InsertAndAdvance(subIndex, atom, advanceType))); + } + case MathListSubIndexType.Denominator: + { + if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); + return new MathListIndex(atomIndex, + (MathListSubIndexType.Radicand, frac.Denominator.InsertAndAdvance(subIndex, atom, advanceType))); + } + case MathListSubIndexType.Subscript: + return new MathListIndex(atomIndex, + ( MathListSubIndexType.Subscript, + self.Atoms[index.AtomIndex].Subscript.InsertAndAdvance(subIndex, atom, advanceType))); + case MathListSubIndexType.Superscript: + return new MathListIndex(atomIndex, + ( MathListSubIndexType.Superscript, + self.Atoms[index.AtomIndex].Subscript.InsertAndAdvance(subIndex, atom, advanceType))); + case MathListSubIndexType.Inner: + if (!(self.Atoms[index.AtomIndex] is Atoms.Inner inner)) + throw new SubIndexTypeMismatchException(typeof(Atoms.Inner), index); + return new MathListIndex(atomIndex, + ( MathListSubIndexType.Inner, + inner.InnerList.InsertAndAdvance(subIndex, atom, advanceType))); + default: + throw new SubIndexTypeMismatchException(index); } - case (MathListSubIndexType.Subscript, MathListIndex subIndex): - self.Atoms[index.AtomIndex].Subscript.InsertAndAdvance(ref subIndex, atom, advanceType); - break; - case (MathListSubIndexType.Superscript, MathListIndex subIndex): - self.Atoms[index.AtomIndex].Superscript.InsertAndAdvance(ref subIndex, atom, advanceType); - break; - case (MathListSubIndexType.Inner, MathListIndex subIndex): - if (!(self.Atoms[index.AtomIndex] is Atoms.Inner inner)) - throw new SubIndexTypeMismatchException(typeof(Atoms.Inner), index); - inner.InnerList.InsertAndAdvance(ref subIndex, atom, advanceType); - break; - default: - throw new SubIndexTypeMismatchException(index); } - Debug.WriteLine("InsertAndAdvance index at end: " + index.ToString()); } public static void RemoveAt(this MathList self, ref MathListIndex index) { - index ??= MathListIndex.Level0Index(0); if (index.AtomIndex > self.Atoms.Count) throw new IndexOutOfRangeException($"Index {index.AtomIndex} is out of bounds for list of size {self.Atoms.Count}"); switch (index.SubIndexInfo) { @@ -127,7 +130,7 @@ public static void RemoveAt(this MathList self, ref MathListIndex index) { self.RemoveAt(index.AtomIndex); // it was in the nucleus and we removed it, get out of the nucleus and get in the nucleus of the previous one. index = downIndex.Previous is MathListIndex downPrev - ? downPrev.LevelUpWithSubIndex(MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)) + ? downPrev.LevelUpWithSubIndex(MathListSubIndexType.BetweenBaseAndScripts, 1) : downIndex; break; } diff --git a/CSharpMath.Editor/MathKeyboard.cs b/CSharpMath.Editor/MathKeyboard.cs index 36695010..5a0c78ac 100644 --- a/CSharpMath.Editor/MathKeyboard.cs +++ b/CSharpMath.Editor/MathKeyboard.cs @@ -148,7 +148,7 @@ static bool IsFullPlaceholderRequired(MathAtom mathAtom) => SetScript(prevAtom, LaTeXSettings.PlaceholderList); } _insertionIndex = prevIndexCorrected.LevelUpWithSubIndex - (subIndexType, MathListIndex.Level0Index(0)); + (subIndexType, 0); } } } @@ -209,41 +209,37 @@ void MoveCursorLeft() { throw new InvalidCodePathException("Invalid levelDown"); if (scriptAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Subscript, - MathListIndex.Level0Index(scriptAtom.Subscript.Count)); + (MathListSubIndexType.Subscript, scriptAtom.Subscript.Count); else goto case MathListSubIndexType.Subscript; break; case MathListSubIndexType.Subscript: _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); + (MathListSubIndexType.BetweenBaseAndScripts, 1); break; case MathListSubIndexType.BetweenBaseAndScripts: if (MathList.AtomAt(levelDown) is Atoms.Radical rad && rad.Radicand.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Radicand, - MathListIndex.Level0Index(rad.Radicand.Count)); + (MathListSubIndexType.Radicand, rad.Radicand.Count); else if (MathList.AtomAt(levelDown) is Atoms.Fraction frac && frac.Denominator.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Denominator, - MathListIndex.Level0Index(frac.Denominator.Count)); + (MathListSubIndexType.Denominator, frac.Denominator.Count); else if (MathList.AtomAt(levelDown) is Atoms.Inner inner && inner.InnerList.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Inner, - MathListIndex.Level0Index(inner.InnerList.Count)); + (MathListSubIndexType.Inner, inner.InnerList.Count); else goto case MathListSubIndexType.Radicand; break; case MathListSubIndexType.Radicand: if (MathList.AtomAt(levelDown) is Atoms.Radical radDeg && radDeg.Degree.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Degree, MathListIndex.Level0Index(radDeg.Degree.Count)); + (MathListSubIndexType.Degree, radDeg.Degree.Count); else goto case MathListSubIndexType.Denominator; break; case MathListSubIndexType.Denominator: if (MathList.AtomAt(levelDown) is Atoms.Fraction fracNum && fracNum.Numerator.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Numerator, MathListIndex.Level0Index(fracNum.Numerator.Count)); + (MathListSubIndexType.Numerator, fracNum.Numerator.Count); else goto default; break; @@ -257,23 +253,23 @@ void MoveCursorLeft() { break; case { Superscript: var s } when s.IsNonEmpty(): _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Superscript, MathListIndex.Level0Index(s.Count)); + (MathListSubIndexType.Superscript, s.Count); break; case { Subscript: var s } when s.IsNonEmpty(): _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Subscript, MathListIndex.Level0Index(s.Count)); + (MathListSubIndexType.Subscript, s.Count); break; case Atoms.Inner { InnerList: var l }: _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Inner, MathListIndex.Level0Index(l.Count)); + (MathListSubIndexType.Inner, l.Count); break; case Atoms.Radical { Radicand: var r }: _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Radicand, MathListIndex.Level0Index(r.Count)); + (MathListSubIndexType.Radicand, r.Count); break; case Atoms.Fraction { Denominator: var d }: _insertionIndex = prev.LevelUpWithSubIndex - (MathListSubIndexType.Denominator, MathListIndex.Level0Index(d.Count)); + (MathListSubIndexType.Denominator, d.Count); break; default: _insertionIndex = prev; @@ -308,14 +304,14 @@ void MoveCursorRight() { case MathListSubIndexType.Degree: if (levelDownAtom is Atoms.Radical) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Radicand, MathListIndex.Level0Index(0)); + (MathListSubIndexType.Radicand, 0); else throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), levelDown); break; case MathListSubIndexType.Numerator: if (levelDownAtom is Atoms.Fraction) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Denominator, MathListIndex.Level0Index(0)); + (MathListSubIndexType.Denominator, 0); else throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), levelDown); break; @@ -324,21 +320,21 @@ void MoveCursorRight() { case MathListSubIndexType.Inner: if (levelDownAtom.Superscript.IsNonEmpty() || levelDownAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); + (MathListSubIndexType.BetweenBaseAndScripts, 1); else goto default; break; case MathListSubIndexType.BetweenBaseAndScripts: if (levelDownAtom.Subscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Subscript, MathListIndex.Level0Index(0)); + (MathListSubIndexType.Subscript, 0); else goto case MathListSubIndexType.Subscript; break; case MathListSubIndexType.Subscript: if (levelDownAtom.Superscript.IsNonEmpty()) _insertionIndex = levelDown.LevelUpWithSubIndex - (MathListSubIndexType.Superscript, MathListIndex.Level0Index(0)); + (MathListSubIndexType.Superscript, 0); else goto default; break; @@ -355,23 +351,23 @@ void MoveCursorRight() { ("_insertionIndex.FinalSubIndexType is BetweenBaseAndScripts but levelDown is null"); _insertionIndex = levelDown.LevelUpWithSubIndex( a.Subscript.IsNonEmpty() ? MathListSubIndexType.Subscript : MathListSubIndexType.Superscript, - MathListIndex.Level0Index(0)); + 0); break; case Atoms.Inner _: - _insertionIndex = _insertionIndex.LevelUpWithSubIndex(MathListSubIndexType.Inner, MathListIndex.Level0Index(0)); + _insertionIndex = _insertionIndex.LevelUpWithSubIndex(MathListSubIndexType.Inner, 0); break; case Atoms.Fraction _: _insertionIndex = _insertionIndex.LevelUpWithSubIndex - (MathListSubIndexType.Numerator, MathListIndex.Level0Index(0)); + (MathListSubIndexType.Numerator, 0); break; case Atoms.Radical rad: _insertionIndex = _insertionIndex.LevelUpWithSubIndex( rad.Degree.IsNonEmpty() ? MathListSubIndexType.Degree : MathListSubIndexType.Radicand, - MathListIndex.Level0Index(0)); + 0); break; case var a when a.Superscript.IsNonEmpty() || a.Subscript.IsNonEmpty(): _insertionIndex = _insertionIndex.LevelUpWithSubIndex - (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)); + (MathListSubIndexType.BetweenBaseAndScripts, 1); break; case Atoms.Placeholder _ when MathList.AtomAt(_insertionIndex.Next) is null: // Skip right side of placeholders when end of line diff --git a/CSharpMath.Editor/MathListIndex.cs b/CSharpMath.Editor/MathListIndex.cs index e9aab30f..3f8303e9 100644 --- a/CSharpMath.Editor/MathListIndex.cs +++ b/CSharpMath.Editor/MathListIndex.cs @@ -1,3 +1,5 @@ +using System.Runtime.InteropServices.ComTypes; + namespace CSharpMath.Editor { ///The type of the subindex denotes what branch the path to the atom that this index points to takes. public enum MathListSubIndexType : byte { @@ -49,14 +51,14 @@ public MathListIndex(int atomIndex, (MathListSubIndexType SubIndexType, MathList SubIndexInfo = subIndexInfo; } - ///Creates a new index by replacing the leaf with IndexInfo (type, subIndex). - public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, MathListIndex subIndex) => + ///Creates a new index by replacing the leaf with IndexInfo (type, Level0Index(innerAtomIndex)). + public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, int innerAtomIndex) => SubIndexInfo switch { - null => new MathListIndex(AtomIndex, (type, subIndex)), + null => new MathListIndex(AtomIndex, (type, Level0Index(innerAtomIndex))), (MathListSubIndexType thisType, MathListIndex thisSubIndex) => new MathListIndex(AtomIndex, - (thisType, thisSubIndex.LevelUpWithSubIndex(type, subIndex))) + (thisType, thisSubIndex.LevelUpWithSubIndex(type, innerAtomIndex))) }; ///Creates a new index by removing the last index item. If this is the last one, then returns nil. public MathListIndex? LevelDown() => From 7b38420100b929485e3064387d897bc264ed4af0 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Wed, 12 Aug 2020 23:15:55 +0100 Subject: [PATCH 13/16] wip --- CSharpMath.Editor/Extensions/MathList.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index 0a7dcee6..cfe56695 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -95,6 +95,7 @@ public static MathListIndex InsertAndAdvance(this MathList self, MathListIndex i default: throw new SubIndexTypeMismatchException(index); } + default: throw new Exception("Can switch expressions be nested?"); } } From b2cd1aca685c6d756b8e32da6eb02505c71270b8 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Thu, 13 Aug 2020 13:41:18 +0100 Subject: [PATCH 14/16] fix --- CSharpMath.Editor/Extensions/MathList.cs | 26 ++++++++++++------------ CSharpMath.Editor/MathKeyboard.cs | 14 ++++++------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index cfe56695..bf5a19f9 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -85,7 +85,7 @@ public static MathListIndex InsertAndAdvance(this MathList self, MathListIndex i case MathListSubIndexType.Superscript: return new MathListIndex(atomIndex, ( MathListSubIndexType.Superscript, - self.Atoms[index.AtomIndex].Subscript.InsertAndAdvance(subIndex, atom, advanceType))); + self.Atoms[index.AtomIndex].Superscript.InsertAndAdvance(subIndex, atom, advanceType))); case MathListSubIndexType.Inner: if (!(self.Atoms[index.AtomIndex] is Atoms.Inner inner)) throw new SubIndexTypeMismatchException(typeof(Atoms.Inner), index); @@ -99,14 +99,14 @@ public static MathListIndex InsertAndAdvance(this MathList self, MathListIndex i } } - public static void RemoveAt(this MathList self, ref MathListIndex index) { + public static void RemoveAt(this MathList self, MathListIndex index) { if (index.AtomIndex > self.Atoms.Count) throw new IndexOutOfRangeException($"Index {index.AtomIndex} is out of bounds for list of size {self.Atoms.Count}"); switch (index.SubIndexInfo) { case null: self.RemoveAt(index.AtomIndex); break; - case (MathListSubIndexType.BetweenBaseAndScripts,_): { + case (MathListSubIndexType.BetweenBaseAndScripts,_): { // TODO fix this var currentAtom = self.Atoms[index.AtomIndex]; if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) throw new SubIndexTypeMismatchException(index); @@ -141,53 +141,53 @@ public static void RemoveAt(this MathList self, ref MathListIndex index) { insertionAtom.Superscript.Append(currentAtom.Superscript); self.RemoveAt(index.AtomIndex); index = downIndex; - self.InsertAndAdvance(ref index, insertionAtom, null); + self.InsertAndAdvance(index, insertionAtom, null); index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); return; } case (MathListSubIndexType.Radicand, MathListIndex subIndex): { if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); - radical.Radicand.RemoveAt(ref subIndex); + radical.Radicand.RemoveAt(subIndex); break; } case (MathListSubIndexType.Degree, MathListIndex subIndex): { if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); - radical.Degree.RemoveAt(ref subIndex); + radical.Degree.RemoveAt(subIndex); break; } case (MathListSubIndexType.Numerator, MathListIndex subIndex): { if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); - frac.Numerator.RemoveAt(ref subIndex); + frac.Numerator.RemoveAt(subIndex); break; } case (MathListSubIndexType.Denominator, MathListIndex subIndex): { if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); - frac.Denominator.RemoveAt(ref subIndex); + frac.Denominator.RemoveAt(subIndex); break; } case (MathListSubIndexType.Subscript, MathListIndex subIndex): var current = self.Atoms[index.AtomIndex]; if (current.Subscript.IsEmpty()) throw new SubIndexTypeMismatchException(index); - current.Subscript.RemoveAt(ref subIndex); + current.Subscript.RemoveAt(subIndex); break; case (MathListSubIndexType.Superscript, MathListIndex subIndex): current = self.Atoms[index.AtomIndex]; if (current.Superscript.IsEmpty()) throw new SubIndexTypeMismatchException(index); - current.Superscript.RemoveAt(ref subIndex); + current.Superscript.RemoveAt(subIndex); break; case (MathListSubIndexType.Inner, MathListIndex subIndex): if (!(self.Atoms[index.AtomIndex] is Atoms.Inner inner)) throw new SubIndexTypeMismatchException(typeof(Atoms.Inner), index); - inner.InnerList.RemoveAt(ref subIndex); + inner.InnerList.RemoveAt(subIndex); break; default: throw new SubIndexTypeMismatchException(index); @@ -195,8 +195,8 @@ public static void RemoveAt(this MathList self, ref MathListIndex index) { if (index.Previous is null && index.SubIndexInfo != null) { // We have deleted to the beginning of the line and it is not the outermost line if (self.AtomAt(index) is null) { - self.InsertAndAdvance(ref index, LaTeXSettings.Placeholder, null); - index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); ; + self.InsertAndAdvance(index, LaTeXSettings.Placeholder, null); + //index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); ; } } } diff --git a/CSharpMath.Editor/MathKeyboard.cs b/CSharpMath.Editor/MathKeyboard.cs index 5a0c78ac..f0057073 100644 --- a/CSharpMath.Editor/MathKeyboard.cs +++ b/CSharpMath.Editor/MathKeyboard.cs @@ -115,7 +115,7 @@ void CreateEmptyAtom() { // Create an empty atom and move the insertion index up. var emptyAtom = LaTeXSettings.Placeholder; SetScript(emptyAtom, LaTeXSettings.PlaceholderList); - MathList.InsertAndAdvance(ref _insertionIndex, emptyAtom, subIndexType); + _insertionIndex = MathList.InsertAndAdvance(_insertionIndex, emptyAtom, subIndexType); } static bool IsFullPlaceholderRequired(MathAtom mathAtom) => mathAtom switch @@ -181,14 +181,14 @@ void HandleSlashButton() { numerator.Push(new Atoms.Number("1")); if (MathList.AtomAt(_insertionIndex.Previous) is Atoms.Fraction) // Add a times symbol - MathList.InsertAndAdvance(ref _insertionIndex, LaTeXSettings.Times, null); - MathList.InsertAndAdvance(ref _insertionIndex, new Atoms.Fraction( + _insertionIndex = MathList.InsertAndAdvance(_insertionIndex, LaTeXSettings.Times, null); + _insertionIndex = MathList.InsertAndAdvance(_insertionIndex, new Atoms.Fraction( new MathList(numerator), LaTeXSettings.PlaceholderList ), MathListSubIndexType.Denominator); } void InsertInner(string left, string right) => - MathList.InsertAndAdvance(ref _insertionIndex, + _insertionIndex = MathList.InsertAndAdvance(_insertionIndex, new Atoms.Inner(new Boundary(left), LaTeXSettings.PlaceholderList, new Boundary(right)), MathListSubIndexType.Inner); @@ -387,13 +387,13 @@ void DeleteBackwards() { // delete the last atom from the list if (HasText && _insertionIndex.Previous is MathListIndex previous) { _insertionIndex = previous; - MathList.RemoveAt(ref _insertionIndex); + MathList.RemoveAt(_insertionIndex); } } static bool IsPlaceholderList(MathList ml) => ml.Count == 1 && ml[0] is Atoms.Placeholder; void InsertAtom(MathAtom a) => - MathList.InsertAndAdvance(ref _insertionIndex, a, + _insertionIndex = MathList.InsertAndAdvance(_insertionIndex, a, a switch { Atoms.Fraction _ => MathListSubIndexType.Numerator, @@ -851,7 +851,7 @@ public void InsertMathList(MathList list, PointF point) { // insert at the given index - but don't consider sublevels at this point var index = MathListIndex.Level0Index(detailedIndex.AtomIndex); foreach (var atom in list.Atoms) { - MathList.InsertAndAdvance(ref index, atom, null); + index = MathList.InsertAndAdvance(index, atom, null); } InsertionIndex = index; // move the index to the end of the new list. } From 4e0998c59ba299e852ef7888cf7e2c7fdc3174e8 Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Thu, 13 Aug 2020 13:43:55 +0100 Subject: [PATCH 15/16] TODO --- CSharpMath.Editor/Extensions/MathList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CSharpMath.Editor/Extensions/MathList.cs b/CSharpMath.Editor/Extensions/MathList.cs index bf5a19f9..65e05745 100644 --- a/CSharpMath.Editor/Extensions/MathList.cs +++ b/CSharpMath.Editor/Extensions/MathList.cs @@ -34,7 +34,7 @@ public static MathListIndex InsertAndAdvance(this MathList self, MathListIndex i return self.InsertAtAtomIndexAndAdvance(atomIndex, atom, advanceType); case (MathListSubIndexType type, MathListIndex subIndex): switch (type) { - case MathListSubIndexType.BetweenBaseAndScripts: + case MathListSubIndexType.BetweenBaseAndScripts: // TODO: finish this section { var currentAtom = self.Atoms[index.AtomIndex]; if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) From 3936e72000831988bde6884a2a031e7b83f3bb8a Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Sat, 15 Aug 2020 19:45:29 +0100 Subject: [PATCH 16/16] readonly props --- CSharpMath.Editor/MathListIndex.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CSharpMath.Editor/MathListIndex.cs b/CSharpMath.Editor/MathListIndex.cs index 3f8303e9..1529c6b8 100644 --- a/CSharpMath.Editor/MathListIndex.cs +++ b/CSharpMath.Editor/MathListIndex.cs @@ -39,9 +39,9 @@ public enum MathListSubIndexType : byte { public class MathListIndex { ///The index of the associated atom. - public int AtomIndex { get; set; } + public int AtomIndex { get; } - public (MathListSubIndexType SubIndexType, MathListIndex SubIndex)? SubIndexInfo; + public readonly (MathListSubIndexType SubIndexType, MathListIndex SubIndex)? SubIndexInfo; /// Factory function to create a `MathListIndex` with no subindexes. /// The index of the atom that the `MathListIndex` points at.