xaml-math
xaml-math copied to clipboard
Support for \begin and \end named environments
Would be great if the engine/parser could support \begin and \end named environments.
Examples:
\begin{pmatrix} a_{11} & a_{12} \ a_{21} & a_{22} \end{pmatrix}
\begin{array}{c|c} 1 & 2 \ \hline 3 & 4 \end{array}
f(n) = \begin{cases} n/2 & \quad \text{if } n \text{ is even}\ -(n+1)/2 & \quad \text{if } n \text{ is odd} \end{cases}
\left(\begin{ array}{c} n \ r \end{array} \right) = \frac{n!}{r!(n-r)!}
TODO[F]
- [x]
pmatrix
(see #329) - [ ]
array
- [ ]
cases
We now have all the necessary tools in 0.7.0 (mainly, the ICommandEnvironment
interface), so it should be possible to implement in the current code base.
Hello, any update on the support for this ?
How would you implement this? I am not familiar with how the code works
It all starts in TexFormulaParser::ProcessCommand
. There's a huge switch
over known commands, and a fallback to WpfMath.Parsers.StandardCommands::Dictionary
.
I suggest that we need to add a new command named begin
into this dictionary; the purpose of the command will be to invoke a child parser and read everything until it encounters a corresponding \end
. The most comprehensive known parser is the MatrixCommandParser
, so maybe you can model your new environment parser after it.
There's no ready code to solve the task "parse until a keyword is meet", but, if you take a look at WpfMath.TexFormulaParser::ReadElementGroup
, it should be more or less straightforward.
There's always a catch, though. Here, the catch is nested environments. It's likely it's possible to construct a new ICommandEnvironment
and inject an \end
command into it, and then use that environment for nested parsing, in a way WpfMath.Parsers.Matrices.MatrixInternalEnvironment
is used.
Though, I think if nested environment handling is too complex for now, we may consider restricting us to a single environment (no nesting) for start.
After you've done the task of getting a SourceSpan
with the internal part between \begin
and \end
, everything else is more or less easy. Read the environment name from the first argument, and then, depending on the name, invoke nested formula parser by invoking WpfMath.Parsers.ICommandParser::ProcessCommand
with the right arguments.
Okay, thats what I have so far, I know it looks aweful
public CommandProcessingResult ProcessCommand(CommandContext context)
{
int position = context.ArgumentsStartPosition;
SourceSpan source = context.CommandSource;
SourceSpan element = TexFormulaParser.ReadElement(source, ref position);
string argument = element.ToString();
int endIndex = -1;
for (int i = position; position < source.End; i++)
{
if (source[i] == '\\' && source[i + 1] == 'e' && source[i + 2] == 'n' && source[i + 3] == 'd')
{
endIndex = i;
break;
}
}
string newContent = source.ToString().Substring(context.ArgumentsStartPosition + element.Length + 2, endIndex - (context.ArgumentsStartPosition + element.Length) - 2);
newContent = "\\" + argument + "{" + newContent + "}";
SourceSpan innerContent = new SourceSpan("Begin-End-Environment", newContent, 0, newContent.Length);
TexFormula content = context.Parser.Parse(innerContent);
return new CommandProcessingResult(content.RootAtom, position + 3);
}
}
When I try to use this command \begin{pmatrix} a_1 & a_2 & a_3 \ b_1 & b_2 & b_3 \ c_1 & c_2 & c_3 \end{pmatrix} it says that '&' is unknown. However, when I copy the pmatrix from newContent and insert it in the TextBox, it works. Any ideas why?
MatrixInternalEnvironment
solves this problem by overriding the ProcessUnknownCharacter
method: https://github.com/ForNeVeR/wpf-math/blob/10b9210b3108711e54bb480e8ed0485bd9c5cfc2/src/WpfMath/Parsers/Matrices/MatrixInternalEnvironment.cs#L27-L36
I believe that it doesn't work automatically because context.Parser.Parse(innerContent)
doesn't receive the command name (it expects to have \pmatrix …
to enter pmatrix-reading mode).
For beginning, you can try working that around by passing @"\pmatrix " + innerContent
as an argument.
This is newContent: \pmatrix{ a_1 & a_2 & a_3 \ b_1 & b_2 & b_3 \ c_1 & c_2 & c_3 } When I paste this in the TextBox it works, but when I parse it, it doesn't work
string newContent = source.ToString().Substring(context.ArgumentsStartPosition + element.Length + 2, endIndex - (context.ArgumentsStartPosition + element.Length) - 2);
newContent = "\\" + argument + "{" + newContent + "}";
TexFormula content = context.Parser.Parse(newContent);
return new CommandProcessingResult(content.RootAtom, position + 3);
content.RootAtom:
{FencedAtom { Source = pmatrix{ a_1 & a_2 & a_3 \\ b_1 & b_2 & b_3 \\ c_1 & c_2 & c_3 }, Type = Ordinary, BaseAtom = MatrixAtom { Source = pmatrix{ a_1 & a_2 & a_3 \\ b_1 & b_2 & b_3 \\ c_1 & c_2 & c_3 }, Type = Ordinary, MatrixCells = System.Collections.ObjectModel.ReadOnlyCollection'1[System.Collections.ObjectModel.ReadOnlyCollection'1[WpfMath.Atoms.Atom]], VerticalPadding = 0,35, HorizontalPadding = 0,35, MatrixCellAlignment = Center } }}
I fixed it and created a new pr. Let me know if there is anything I should change