diff --git a/src/WpfMath.Tests/ParserTests.fs b/src/WpfMath.Tests/ParserTests.fs index 2ba84784..cd6c6728 100644 --- a/src/WpfMath.Tests/ParserTests.fs +++ b/src/WpfMath.Tests/ParserTests.fs @@ -289,3 +289,11 @@ let colorModelsWithOpacity(text: string): unit = [] let multilineFormula(): unit = verifyParseResult @"line 1\\line 2\\line 3" + +[] +[] +let newLineAfterMatrix(text: string): unit = + verifyParseResultScenario + <| processSpecialChars text + <| text diff --git a/src/WpfMath.Tests/TestResults/ParserTests.multilineFormula.approved.txt b/src/WpfMath.Tests/TestResults/ParserTests.multilineFormula.approved.txt index 49601772..de3d4c44 100644 --- a/src/WpfMath.Tests/TestResults/ParserTests.multilineFormula.approved.txt +++ b/src/WpfMath.Tests/TestResults/ParserTests.multilineFormula.approved.txt @@ -1,185 +1,169 @@ { "TextStyle": null, "RootAtom": { - "PreviousAtom": null, - "Elements": [ - { - "MatrixCells": [ - [ + "MatrixCells": [ + [ + { + "PreviousAtom": null, + "Elements": [ { - "PreviousAtom": null, - "Elements": [ - { - "MatrixCells": [ - [ - { - "PreviousAtom": null, - "Elements": [ - { - "Character": "l", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 0, - "End": 1, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "i", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 1, - "End": 2, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "n", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 2, - "End": 3, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "e", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 3, - "End": 4, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "1", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 5, - "End": 6, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - } - ], - "Type": "Ordinary", - "Source": { - "Start": 0, - "End": 6, - "Length": 6, - "Source": "line 1\\\\line 2\\\\line 3" - } - } - ], - [ - { - "Character": "l", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 8, - "End": 9, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - } - ] - ], - "VerticalPadding": 0.35, - "HorizontalPadding": 0.35, - "MatrixCellAlignment": "Center", - "Type": "Ordinary", - "Source": { - "Start": 7, - "End": 9, - "Length": 2, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "i", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 9, - "End": 10, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "n", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 10, - "End": 11, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "e", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 11, - "End": 12, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "2", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 13, - "End": 14, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - } - ], + "Character": "l", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, "Type": "Ordinary", "Source": { "Start": 0, + "End": 1, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "i", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 1, + "End": 2, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "n", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 2, + "End": 3, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "e", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 3, + "End": 4, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "1", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 5, + "End": 6, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + } + ], + "Type": "Ordinary", + "Source": { + "Start": 0, + "End": 6, + "Length": 6, + "Source": "line 1\\\\line 2\\\\line 3" + } + } + ], + [ + { + "PreviousAtom": null, + "Elements": [ + { + "Character": "l", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 8, + "End": 9, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "i", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 9, + "End": 10, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "n", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 10, + "End": 11, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "e", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 11, + "End": 12, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "2", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 13, "End": 14, - "Length": 14, + "Length": 1, "Source": "line 1\\\\line 2\\\\line 3" } } ], - [ + "Type": "Ordinary", + "Source": { + "Start": 8, + "End": 14, + "Length": 6, + "Source": "line 1\\\\line 2\\\\line 3" + } + } + ], + [ + { + "PreviousAtom": null, + "Elements": [ { "Character": "l", "TextStyle": null, @@ -192,79 +176,74 @@ "Length": 1, "Source": "line 1\\\\line 2\\\\line 3" } + }, + { + "Character": "i", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 17, + "End": 18, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "n", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 18, + "End": 19, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "e", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 19, + "End": 20, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } + }, + { + "Character": "3", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 21, + "End": 22, + "Length": 1, + "Source": "line 1\\\\line 2\\\\line 3" + } } - ] - ], - "VerticalPadding": 0.35, - "HorizontalPadding": 0.35, - "MatrixCellAlignment": "Center", - "Type": "Ordinary", - "Source": { - "Start": 15, - "End": 17, - "Length": 2, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "i", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 17, - "End": 18, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "n", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 18, - "End": 19, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "e", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 19, - "End": 20, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" - } - }, - { - "Character": "3", - "TextStyle": null, - "IsDefaultTextStyle": true, - "IsTextSymbol": false, - "Type": "Ordinary", - "Source": { - "Start": 21, - "End": 22, - "Length": 1, - "Source": "line 1\\\\line 2\\\\line 3" + ], + "Type": "Ordinary", + "Source": { + "Start": 16, + "End": 22, + "Length": 6, + "Source": "line 1\\\\line 2\\\\line 3" + } } - } + ] ], + "VerticalPadding": 0.35, + "HorizontalPadding": 0.35, + "MatrixCellAlignment": "Left", "Type": "Ordinary", - "Source": { - "Start": 0, - "End": 22, - "Length": 22, - "Source": "line 1\\\\line 2\\\\line 3" - } + "Source": null } } \ No newline at end of file diff --git a/src/WpfMath.Tests/TestResults/ParserTests.newLineAfterMatrix.(matrix(line 1)line 2).approved.txt b/src/WpfMath.Tests/TestResults/ParserTests.newLineAfterMatrix.(matrix(line 1)line 2).approved.txt new file mode 100644 index 00000000..33f2cb84 --- /dev/null +++ b/src/WpfMath.Tests/TestResults/ParserTests.newLineAfterMatrix.(matrix(line 1)line 2).approved.txt @@ -0,0 +1,186 @@ +{ + "TextStyle": null, + "RootAtom": { + "MatrixCells": [ + [ + { + "MatrixCells": [ + [ + { + "PreviousAtom": null, + "Elements": [ + { + "Character": "l", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 8, + "End": 9, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + }, + { + "Character": "i", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 9, + "End": 10, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + }, + { + "Character": "n", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 10, + "End": 11, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + }, + { + "Character": "e", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 11, + "End": 12, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + }, + { + "Character": "1", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 13, + "End": 14, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + } + ], + "Type": "Ordinary", + "Source": { + "Start": 8, + "End": 14, + "Length": 6, + "Source": "\\matrix{line 1}\\\\line 2" + } + } + ] + ], + "VerticalPadding": 0.35, + "HorizontalPadding": 0.35, + "MatrixCellAlignment": "Center", + "Type": "Ordinary", + "Source": { + "Start": 1, + "End": 15, + "Length": 14, + "Source": "\\matrix{line 1}\\\\line 2" + } + } + ], + [ + { + "PreviousAtom": null, + "Elements": [ + { + "Character": "l", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 17, + "End": 18, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + }, + { + "Character": "i", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 18, + "End": 19, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + }, + { + "Character": "n", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 19, + "End": 20, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + }, + { + "Character": "e", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 20, + "End": 21, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + }, + { + "Character": "2", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 22, + "End": 23, + "Length": 1, + "Source": "\\matrix{line 1}\\\\line 2" + } + } + ], + "Type": "Ordinary", + "Source": { + "Start": 17, + "End": 23, + "Length": 6, + "Source": "\\matrix{line 1}\\\\line 2" + } + } + ] + ], + "VerticalPadding": 0.35, + "HorizontalPadding": 0.35, + "MatrixCellAlignment": "Left", + "Type": "Ordinary", + "Source": null + } +} \ No newline at end of file diff --git a/src/WpfMath.Tests/TestResults/ParserTests.newLineAfterMatrix.(pmatrix(line 1)line 2).approved.txt b/src/WpfMath.Tests/TestResults/ParserTests.newLineAfterMatrix.(pmatrix(line 1)line 2).approved.txt new file mode 100644 index 00000000..7c81d458 --- /dev/null +++ b/src/WpfMath.Tests/TestResults/ParserTests.newLineAfterMatrix.(pmatrix(line 1)line 2).approved.txt @@ -0,0 +1,209 @@ +{ + "TextStyle": null, + "RootAtom": { + "MatrixCells": [ + [ + { + "BaseAtom": { + "MatrixCells": [ + [ + { + "PreviousAtom": null, + "Elements": [ + { + "Character": "l", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 9, + "End": 10, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + { + "Character": "i", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 10, + "End": 11, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + { + "Character": "n", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 11, + "End": 12, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + { + "Character": "e", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 12, + "End": 13, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + { + "Character": "1", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 14, + "End": 15, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + } + ], + "Type": "Ordinary", + "Source": { + "Start": 9, + "End": 15, + "Length": 6, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + } + ] + ], + "VerticalPadding": 0.35, + "HorizontalPadding": 0.35, + "MatrixCellAlignment": "Center", + "Type": "Ordinary", + "Source": { + "Start": 1, + "End": 16, + "Length": 15, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + "LeftDelimeter": { + "IsDelimeter": true, + "Name": "lbrack", + "IsTextSymbol": false, + "Type": "Opening", + "Source": null + }, + "RightDelimeter": { + "IsDelimeter": true, + "Name": "rbrack", + "IsTextSymbol": false, + "Type": "Closing", + "Source": null + }, + "Type": "Ordinary", + "Source": { + "Start": 1, + "End": 16, + "Length": 15, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + } + ], + [ + { + "PreviousAtom": null, + "Elements": [ + { + "Character": "l", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 18, + "End": 19, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + { + "Character": "i", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 19, + "End": 20, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + { + "Character": "n", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 20, + "End": 21, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + { + "Character": "e", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 21, + "End": 22, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + }, + { + "Character": "2", + "TextStyle": null, + "IsDefaultTextStyle": true, + "IsTextSymbol": false, + "Type": "Ordinary", + "Source": { + "Start": 23, + "End": 24, + "Length": 1, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + } + ], + "Type": "Ordinary", + "Source": { + "Start": 18, + "End": 24, + "Length": 6, + "Source": "\\pmatrix{line 1}\\\\line 2" + } + } + ] + ], + "VerticalPadding": 0.35, + "HorizontalPadding": 0.35, + "MatrixCellAlignment": "Left", + "Type": "Ordinary", + "Source": null + } +} \ No newline at end of file diff --git a/src/WpfMath/Atoms/MatrixAtom.cs b/src/WpfMath/Atoms/MatrixAtom.cs index b75b22ca..e2a66b3d 100644 --- a/src/WpfMath/Atoms/MatrixAtom.cs +++ b/src/WpfMath/Atoms/MatrixAtom.cs @@ -10,15 +10,17 @@ namespace WpfMath.Atoms /// An atom representing a tabular arrangement of atoms. internal class MatrixAtom : Atom { + public const double DefaultPadding = 0.35; + public MatrixAtom( SourceSpan source, - List> cells, + IEnumerable> cells, MatrixCellAlignment matrixCellAlignment, - double verticalPadding = 0.35, - double horizontalPadding = 0.35) : base(source) + double verticalPadding = DefaultPadding, + double horizontalPadding = DefaultPadding) : base(source) { MatrixCells = new ReadOnlyCollection>( - cells.Select(row => new ReadOnlyCollection(row)).ToList()); + cells.Select(row => new ReadOnlyCollection(row.ToList())).ToList()); MatrixCellAlignment = matrixCellAlignment; VerticalPadding = verticalPadding; HorizontalPadding = horizontalPadding; diff --git a/src/WpfMath/Parsers/StandardCommands.cs b/src/WpfMath/Parsers/StandardCommands.cs index 8551009b..5755654c 100644 --- a/src/WpfMath/Parsers/StandardCommands.cs +++ b/src/WpfMath/Parsers/StandardCommands.cs @@ -55,25 +55,38 @@ private class NewLineCommand : ICommandParser public CommandProcessingResult ProcessCommand(CommandContext context) { var source = context.CommandSource; - var position = context.ArgumentsStartPosition; var prevFormulaAtom = context.Formula.RootAtom; - var topRow = new List(); - topRow.Add(prevFormulaAtom); - var rows = new List> {topRow}; - - var newContent = context.Parser.Parse( - TexFormulaParser.ReadElement(source, ref position), + var nextLineAtom = context.Parser.Parse( + source.Segment(context.ArgumentsStartPosition), context.Formula.TextStyle, - context.Environment); + context.Environment).RootAtom; - var bottomRow = new List(); - bottomRow.Add(newContent.RootAtom); - rows.Add(bottomRow); + // An optimization: if the new content itself is a matrix with suitable parameters, then we won't + // wrap it into another formula, but will combine it with the content on top. + var newMatrix = nextLineAtom is MatrixAtom m + && m.MatrixCellAlignment == MatrixCellAlignment.Left + && m.HorizontalPadding == MatrixAtom.DefaultPadding + && m.VerticalPadding == MatrixAtom.DefaultPadding + ? m + : null; - var start = context.CommandNameStartPosition; - var atomSource = source.Segment(start, position - start); - var atom = new MatrixAtom(atomSource, rows, MatrixCellAlignment.Center); + var topRow = new[] {prevFormulaAtom}; + var rows = new List> {topRow}; + if (newMatrix != null) + { + rows.AddRange(newMatrix.MatrixCells); + } + else + { + var bottomRow = new[] {nextLineAtom}; + rows.Add(bottomRow); + } + + // We'll always use source = null for the resulting matrix, because it's a structural element and not a + // useful atom generated from any particular sources. + var atom = new MatrixAtom(null, rows, MatrixCellAlignment.Left); + var position = source.Length; // we always parse the provided source until the end return new CommandProcessingResult(atom, position, AtomAppendMode.Replace); } } diff --git a/src/WpfMath/TexFormulaParser.cs b/src/WpfMath/TexFormulaParser.cs index 6d2f50d8..7f81ff18 100644 --- a/src/WpfMath/TexFormulaParser.cs +++ b/src/WpfMath/TexFormulaParser.cs @@ -699,7 +699,10 @@ private void ProcessEscapeSequence(TexFormula formula, true, environment); - var source = new SourceSpan(formulaSource.Source, formulaSource.Start, commandAtom.Source.End); + var source = new SourceSpan( + formulaSource.Source, + formulaSource.Start, + commandAtom.Source?.End ?? position); switch (appendMode) { case AtomAppendMode.Add: