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: 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); 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); index = downIndex; self.InsertAndAdvance(ref index, insertionAtom, MathListSubIndexType.None); index = index.Previous ?? throw new InvalidCodePathException("Cannot go back after insertion?"); return;
public void TestRemoveAtomAtIndex() { var list = new MathList(); var atom = MathAtoms.Placeholder; var atom2 = MathAtoms.Times; list.Add(atom); list.Add(atom2); Assert.Equal(2, list.Count); list.RemoveAt(0); Assert.Single(list); Assert.Equal(atom2, list[0]); Assert.Throws <ArgumentOutOfRangeException>(() => list.RemoveAt(1)); Assert.Throws <ArgumentOutOfRangeException>(() => list.RemoveAt(2)); }