Open bohrium opened 3 years ago
I agree, this is a common pain point for me as well, and I've been mulling over solutions in my head for a while. Getting the workflow right is tricky, but I'm happy to discuss possibilities. Although the examples you listed share a common syntax, I think they appear in quite different contexts and will need to be handled differently. We will also be limited by the commands supported by KaTeX / MathJax.
A x = \begin{bmatrix}
a_{11} & a_{12} \\
a_{21} & a_{22}
\end{bmatrix}
\begin{bmatrix}
x_1 \\ x_2
\end{bmatrix}
Tables tend to appear by themselves, so it might be as simple as enabling prosemirror-tables extension with some special code for serialization to LaTeX.
I suspect that everyone has different preferences for how to format multi-line derivations, so it might be difficult to standardize, especially when nested brackets are involved. Personally I tend to use multiple indented lines for nested brackets, and I'll often wrap manually if lines get too long. For example,
\begin{aligned}
\EE_{q(x)}\left[ (x-\mu_A)^T \Sigma_A^{-1} (x-\mu_A) \right]
&= \EE\left[
\trace\left( (x-\mu_A)^T \Sigma_A^{-1} (x-\mu_A) \right)
\right]
& \text{(trace of scalar)} \\
&= \EE\left[
\trace\left( \Sigma_A^{-1} (x-\mu_A) (x-\mu_A)^T \right)
\right]
& \text{(cyclicity)}\\
&= \trace\left( \EE\left[
\Sigma_A^{-1} (x-\mu_A) (x-\mu_A)^T
\right] \right)
&\text{(linearity)}\\
&= \trace\left( \Sigma_A^{-1} \EE\left[
(x-\mu_A) (x-\mu_A)^T
\right] \right)
&\text{(linearity)}\\
&= \trace\left( \Sigma_A^{-1} \left[
\Sigma_B + (\mu_B - \mu_A)(\mu_B - \mu_A)^T
\right] \right)
&\text{(eqn\;\ref{eqn:gauss-quadratic-form})} \\
&= \trace\left( \Sigma_A^{-1} \Sigma_B \right)
+ (\mu_B - \mu_A)^T \Sigma_A^{-1} (\mu_B - \mu_A)
&\text{(cyclicity; linearity)}
\end{aligned}
prosemirror-math
to be able to handle. The best tool I know of for editing commutative diagrams on the web is quiver, so worst case we might be able to introduce a new type of math node that makes it easy to embed diagrams made with quiver.Cool! Your points about differences in context implying differences in handling make a lot of sense to me. I'll mull over.
Quick comments:
quiver seems to generate tikz blocks, but katex does not support tikz's environments (I think). It seems they support the amscd "CD" environment (CD stands for commutative diagram), which is a very bare bones package that can express perhaps 80% of the simple diagrams a math student might draw and that can render them correctly perhaps 80% of the time.
matrices as sub-expressions : the general design problem is as you mention tricky, so I'll discuss the much easier case where I'm allowed to overfit to my own tastes :smile:. I would feel happy if the example given is auto formatted to look like
A x =
\begin{bmatrix}
loremipsum & 1 \\
0 & moocow
\end{bmatrix}
\begin{bmatrix}
whole \\
two-percent
\end{bmatrix}
However, I can imagine folks and cases that favor a more compact style such as:
A x = \begin{bmatrix} loremipsum & 1 \\
0 & moocow \end{bmatrix} \begin{bmatrix} whole \\ two-percent \end{bmatrix}
Here, only the "hard-to-parse" first matrix is formatted in an aligned way. I don't see how to approximate this latter style programatically --- or whether to so attempt would be useful.
multiline derivations: i bet the following two rules are common to many personal styles:
For example, both hold in the example you showed (for for the two values of k, we have c=0 and then c=4). So perhaps something good here be to insert spaces according to this "weak rule" rather than insisting on a canonical form. Thus, the formatter would not override extra newlines and extra indentation provided by the user.
Here's a simple example of what it would love to see when modifying a multiline derivation. Say we start with
\begin{align}
a
&= \left(
itwasthebestoftimes
\right)
moo & \left\langle
itwastheworstoftimes
\right\rangle& woah
& true \\
&= \left(
itwastheageofwisdom
\right)
cow & \left(
itwastheageoffoolishness
\right)_0 & woah \\
& true \\
& &
& woah
& true
\end{align}
Upon replacing "cow" by "iamafundamoomentallygoodcow", we see
\begin{align}
a
&= \left(
itwasthebestoftimes
\right)
moo & \left\langle
itwastheworstoftimes
\right\rangle& woah
& true \\
&= \left(
itwastheageofwisdom
\right)
iamafundamoomentallygoodcow & \left(
itwastheageoffoolishness
\right)_0 & woah \\
& true \\
& &
& woah
& true
\end{align}
Then, upon replacing the "\rangle" by ")", we see
\begin{align}
a
&= \left(
itwasthebestoftimes
\right)
moo & \left\langle
itwastheworstoftimes
\right) & woah
& true \\
&= \left(
itwastheageofwisdom
\right)
iamafundamoomentallygoodcow & \left(
itwastheageoffoolishness
\right)_0& woah \\
& true \\
& &
& woah
& true
\end{align}
As for diagrams, here are what some that come to mind. They go from most to least common and from least to most complex. From the implementation standpoint they are similar: each is a combination of basic parts. But from the usability standpoint each might say something different about what interfaces best aid mathematical writing.
lifting diagram
\begin{tikzcd}
& P \arrow[d, "g"] \arrow[ld, "l"', dotted] \\
X \arrow[r, "\pi"', two heads] & Y
\end{tikzcd}
causal model
\begin{tikzcd}
& \substack{\text{sensor}\\ \text{placement}} \arrow[rd] \arrow[rrd] & & \\
\substack{\text{attentive}\\ \text{nurse}} \arrow[ru] \arrow[rd] & & \substack{\text{sensor}\\ \text{reading}} \arrow[r] & \substack{\text{guessed}\\ \text{heartrate}} \\
& \substack{\text{true}\\ \text{heartrate}} \arrow[ru] & &
\end{tikzcd}
naturality
\begin{tikzcd}
& a \arrow[ldd, no head, dotted] \arrow[rd, no head, dotted] \arrow[rr] & & b \arrow[rd, no head, dotted] \arrow[dd, no head, dotted] & \\
& & Ga \arrow[rr] & & Gb \\
Fa \arrow[rrr] \arrow[rru, "\eta_a"] & & & Fb \arrow[ru, "\eta_b"] &
\end{tikzcd}
finite-state automaton
\begin{tikzcd}
\to q_0 \arrow[r, "a"] \arrow["b", loop, distance=2em, in=235, out=305] & q_1 \arrow[r, "a"] \arrow[l, "b"', bend left=49] & q_2 \arrow[r, "a"] \arrow[ll, "b"', bend left=49] & \boxed{q_3} \arrow["{a,b}", loop, distance=2em, in=235, out=305]
\end{tikzcd}
Let me know if any of these ideas sounds like a good starting point that I might try to implement!
I think we agree on the rough ux, so I'm happy to continue the feedback loop with you if you start on a prototype! Some things to ponder:
I plan to add support for MathJax, for those who want it, along with extensions like XyJax for commutative diagrams. It's unfortunate that the KaTeX \begin{CD}
environment doesn't support diagonal arrows. So, you can design with something like XyJax in mind.
How do you plan to implement this functionality? As an actual <table>
element that gets converted to LaTeX? Or as a string processor that adjusts the contents of the text input field automatically as you type? We'll need to think carefully about the right way for a user to "activate" the array-style editing mode, since having it on by default might confuse users. One option is to create a new NodeView
activated by a different character sequence (like $$matrix
or \begin{matrix}
etc) that offers the array-style mode. You can use the existing math NodeView as a reference.
In order to contribute code to this repo, it will be important to understand the transaction-based model of ProseMirror. The ProseMirror guide is a good starting point. Right now, the math editor appears in a NodeView that contains another mini-instance of ProseMirror. So, if you make any changes to how the inner editor behaves, they will need to respect the transactional model. (meaning you can't just set e.g. textField.textContent = adjustSpacing(textField.textContent)
every time you want to make a change)
One of the most annoying-times-frequency things among my latex experiences is making 2d grids by describing them using 1d text. Such grids include matrices, commutative diagrams, tables, multi-line derivations whose terms are aligned, and more. It'd be neat to provide a special "array mode" for parsing and editing text of the form
This is the syntax for the latex body in each of all four examples above. The cells(' latex expressions) will typically all differ in length, creating a headache (do we spend time inserting white-space to align the columns, maintaining this alignment when we modify the cells? or do we ignore alignment issues in the source code and just count in our head when editing each row?)
It would be nice if when one's cursor enters a latex block of the above form, the cells in the latex block automatically align (wrt the ampersands and line-break symbols). If I correctly understand the spirit of prosemirror-math, one wants to avoid having popup dialog boxes or editors separate from the text. So perhaps the alignment could be as simple as inserting appropriate whitespace when the block is "active"!