Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CSharpMath.Editor.Tests/MathKeyboardTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,14 @@ public void Return(params K[] inputs) =>
T(@"\frac{\square }{3}", K.Slash, K.D3, K.Left, K.Left, K.Backspace, K.Left),
T(@"1_3", K.D1, K.D2, K.Subscript, K.D3, K.Left, K.Left, K.Backspace),
T(@"1^2_3", K.D1, K.D4, K.Subscript, K.D3, K.Left, K.Left, K.Power, K.D2, K.Left, K.Left, K.Backspace),
T(@"1^3_2", K.D1, K.D4, K.Power, K.D3, K.Left, K.Left, K.Subscript, K.D2, K.Left, K.Left, K.Left, K.Left, K.Backspace)
T(@"1^3_2", K.D1, K.D4, K.Power, K.D3, K.Left, K.Left, K.Subscript, K.D2, K.Left, K.Left, K.Left, K.Left, K.Backspace),
T(@"■^6", K.Power, K.D6, K.Left, K.Left, K.Left, K.X, K.Left, K.Left, K.Left, K.Backspace),
T(@"\sqrt[■]{\square }", K.NthRoot, K.SmallA, K.Backspace),
T(@"\sqrt{■}", K.SquareRoot, K.SmallA, K.Backspace),
T(@"\frac{1}{■}", K.Slash, K.D6, K.Backspace),
T(@"■_5", K.Subscript, K.D5, K.Left, K.Left, K.Backspace, K.X, K.Left, K.Left, K.Left, K.Backspace),
T(@"7+1^x", K.D7, K.Plus, K.D1, K.D2, K.Power, K.X, K.Left, K.Left, K.Backspace),
T(@"7+■^x", K.D7, K.Plus, K.D1, K.Power, K.X, K.Left, K.Left, K.Backspace),
]
public void LeftRightBackspace(string latex, params K[] inputs) => Test(latex, inputs);

Expand Down
49 changes: 37 additions & 12 deletions CSharpMath.Editor/Extensions/MathListEditingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace CSharpMath.Editor {
using Atoms;
using CSharpMath.Constants;
using Interfaces;
public static class MathListEditingExtensions {
static void InsertAtAtomIndexAndAdvance(this IMathList self, int atomIndex, IMathAtom atom, ref MathListIndex advance, MathListSubIndexType advanceType) {
Expand Down Expand Up @@ -85,8 +86,8 @@ public static void InsertAndAdvance(this IMathList self, ref MathListIndex index
}
}

public static void RemoveAt(this IMathList self, MathListIndex index) {
index = index ?? MathListIndex.Level0Index(0);
public static void RemoveAt(this IMathList 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) {
Expand All @@ -97,49 +98,73 @@ public static void RemoveAt(this IMathList self, MathListIndex index) {
var currentAtom = self.Atoms[index.AtomIndex];
if (currentAtom.Subscript == null && currentAtom.Superscript == null)
throw new SubIndexTypeMismatchException("Nuclear fission is not supported if there are no subscripts or superscripts.");
var downIndex = index.LevelDown();
if (index.AtomIndex > 0) {
var previous = self.Atoms[index.AtomIndex - 1];
if (previous.Subscript is null && previous.Superscript is null) {
if (previous.Subscript is null && previous.Superscript is null
&& previous.AtomType == Enumerations.MathAtomType.Number) {
previous.Superscript = currentAtom.Superscript;
previous.Subscript = 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;
}
}
// no previous atom or the previous atom sucks (has sub/super scripts)
currentAtom.Nucleus = "";
break;
// insert placeholder since previous atom isn't a number
var insertionAtom = MathAtoms.Placeholder;
// mark the placeholder as selected since that is the current insertion point.
insertionAtom.Nucleus = Symbols.BlackSquare;
insertionAtom.Subscript = currentAtom.Subscript;
insertionAtom.Superscript = currentAtom.Superscript;
self.RemoveAt(index.AtomIndex);
index = downIndex;
self.InsertAndAdvance(ref index, insertionAtom, MathListSubIndexType.None);
index = index.Previous;
return;
case MathListSubIndexType.Radicand:
case MathListSubIndexType.Degree:
if (!(self.Atoms[index.AtomIndex] is Radical radical && radical.AtomType == Enumerations.MathAtomType.Radical))
throw new SubIndexTypeMismatchException($"No radical found at index {index.AtomIndex}");
if (index.SubIndexType == MathListSubIndexType.Degree)
radical.Degree.RemoveAt(index.SubIndex);
radical.Degree.RemoveAt(ref index.SubIndex);
else
radical.Radicand.RemoveAt(index.SubIndex);
radical.Radicand.RemoveAt(ref index.SubIndex);
break;
case MathListSubIndexType.Numerator:
case MathListSubIndexType.Denominator:
if (!(self.Atoms[index.AtomIndex] is Fraction frac && frac.AtomType == Enumerations.MathAtomType.Fraction))
throw new SubIndexTypeMismatchException($"No fraction found at index {index.AtomIndex}");
if (index.SubIndexType == MathListSubIndexType.Numerator)
frac.Numerator.RemoveAt(index.SubIndex);
frac.Numerator.RemoveAt(ref index.SubIndex);
else
frac.Denominator.RemoveAt(index.SubIndex);
frac.Denominator.RemoveAt(ref index.SubIndex);
break;
case MathListSubIndexType.Subscript:
var current = self.Atoms[index.AtomIndex];
if (current.Subscript == null) throw new SubIndexTypeMismatchException($"No subscript for atom at index {index.AtomIndex}");
current.Subscript.RemoveAt(index.SubIndex);
current.Subscript.RemoveAt(ref index.SubIndex);
break;
case MathListSubIndexType.Superscript:
current = self.Atoms[index.AtomIndex];
if (current.Superscript == null) throw new SubIndexTypeMismatchException($"No superscript for atom at index {index.AtomIndex}");
current.Superscript.RemoveAt(index.SubIndex);
current.Superscript.RemoveAt(ref index.SubIndex);
break;
default:
throw new SubIndexTypeMismatchException("Invalid subindex type.");
}
if (index.AtBeginningOfLine && index.SubIndexType != MathListSubIndexType.None) {
// We have deleted to the beginning of the line and it is not the outermost line
if (self.AtomAt(index) is null) {
var insertionAtom = MathAtoms.Placeholder;
// mark the placeholder as selected since that is the current insertion point.
insertionAtom.Nucleus = Symbols.BlackSquare;
self.InsertAndAdvance(ref index, insertionAtom, MathListSubIndexType.None);
index = index.Previous;
}
}
}

public static void RemoveAtoms(this IMathList self, MathListRange? nullableRange) {
Expand Down
21 changes: 1 addition & 20 deletions CSharpMath.Editor/Keyboards/MathKeyboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -318,27 +318,8 @@ void DeleteBackwards() {
// delete the last atom from the list
var prevIndex = _insertionIndex.Previous;
if (HasText && !(prevIndex is null)) {
MathList.RemoveAt(prevIndex);
if (prevIndex.FinalSubIndexType is MathListSubIndexType.BetweenBaseAndScripts) {
// it was in the nucleus and we removed it, get out of the nucleus and get in the nucleus of the previous one.
var downIndex = prevIndex.LevelDown();
prevIndex = downIndex.Previous is MathListIndex downPrev
? downPrev.LevelUpWithSubIndex(MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))
: downIndex;
}
_insertionIndex = prevIndex;
if (_insertionIndex.AtBeginningOfLine && _insertionIndex.SubIndexType != MathListSubIndexType.None) {
// We have deleted to the beginning of the line and it is not the outermost line
var insertionAtom = MathList.AtomAt(_insertionIndex);
if (insertionAtom is null) {
// add a placeholder if we deleted everything in the list
insertionAtom = MathAtoms.Placeholder;
// mark the placeholder as selected since that is the current insertion point.
insertionAtom.Nucleus = Symbols.BlackSquare;
MathList.InsertAndAdvance(ref _insertionIndex, insertionAtom, MathListSubIndexType.None);
_insertionIndex = _insertionIndex.Previous;
}
}
MathList.RemoveAt(ref _insertionIndex);
}
}

Expand Down