NOTE: The finished code for this project can be found here, under "UPDATE": How do I alter this \$PreRead + \$PrePrint statement so it can be selectively deactivated?
SUMMARY
I'd like to get MMA to automatically print both input and output on the same line, in TraditionalForm, without having to add any extra syntax. Further, I'd like the output to be fully evaluate-able. For example:
int=Integrate[x^2,x]
$\text{int}=\int x^2 \, dx=\frac{x^3}{3}$
int/x
$\frac{\text{int}}{x}=\frac{x^2}{3}$
EDIT: I've been asked to edit my question to explain how it's different from How to show formula and substitute variable values?. So: The question here is not simply how to get input and output on the same line; rather, it's how to do this without needing to use any extra syntax, i.e., how to automate this functionality. See, for example, Partial Solution 1, below, which requires no extra syntax (except for a single line of code evaluated at the start of the notebook). Partial Solution 2 requires minimal extra syntax (a semicolon at the end of each input, followed by a single command), but even that's more than I want to have to do.
MOTIVATION
I want to automate the production of notebooks that are easily-readable by students and colleagues not familiar with MMA. Once the above is implemented, I would use @R. M.'s neat code-hiding palette (see Is there a way to hide or toggle the visibility of code?) to get rid of the input code, leaving me with just this:
$\text{int}=\int x^2 \, dx=\frac{x^3}{3}$
$\frac{\text{int}}{x}=\frac{x^2}{3}$
Note the purpose here is not to produce publication-quality notebooks, but rather to minimize the effort I need to expend to create easily-readable output.
Aside: Once I get this working, I will then want to figure out a way to merge text, input, and output into a single line (which I understand can be easily done in Maple). I'll save this for a separate question, but wanted to mention it here to give you an overall picture of what I'm trying to accomplish. For example, it would be wonderful if, using input as simple as this, I could get the following output: [UPDATE: We have now accomplished this; see Combined inline printing of input, output, and text, w/ minimal added syntax ]
""We find that"" Integrate[x^2,x] "", as expected.""
$\text{We find that }\int x^2 \, dx=\frac{x^3}{3}\text{, as expected.}$
I currently have two partial solutions. Both are close, but require expertise I don't have to be brought to completion.
PARTIAL SOLUTION 1
This uses a very cool line of code that @Simon Rochester created in reply to a related question I'd asked at Want to return name of last defined variable without explicitly naming it:
$PrePrint = (TraditionalForm@HoldForm[In[line] = #] /. line -> $Line /. DownValues[In]) &;
Here are examples of the output one gets after activating it:
Integrate[x^2, x]
$\int x^2 \, dx=\frac{x^3}{3}$
int=Integrate[x^2, x]
$\left(\text{int}=\int x^2 \, dx\right)=\frac{x^3}{3}$
int/x
$\frac{\text{int}}{x}=\frac{x^2}{3}$
%/x
$\frac{\%}{x}=\frac{x}{3}$
a = 2
$(a=2)=2$
g[x_]:=Sin[x]
[no output]
g[Pi]
$g(\pi )= 0$
This code has the advantage that I only need to activate it once, at the beginning of each notebook; no extra syntax is needed. And all its output is evaluate-able. However, there are three aspects of the output I'd like to change: (1) if there is an assignment, it adds an extra set of parentheses; (2) if the evaluation doesn't transform the input, one ends up with a redundancy in the output; and (3) with delayed assignments, there is no output at all (i.e., it doesn't return the input; contrast this with Partial Solution 2, below).
I don't understand the code, and thus lack the expertise to modify it. The two key mysteries for me are the $PrePrint command (which remains confusing even after reading the MMA documentation, as well as the references to it on MMA Stack Exchange), and the two concatenated ReplaceAll commands (which use only one arrow). I tried expanding the code using FullForm, but I'm still at loss -- if someone could help me understand it better, that would be great:
CompoundExpression
[
Set
[
$PrePrint,Function
[
ReplaceAll
[
ReplaceAll
[
TraditionalForm
[
HoldForm
[
Set
[
In[line],Slot[1]
]
]
]
, Rule[line,$Line]
]
,DownValues[In]
]
]
]
,Null
]
=Null
PARTIAL SOLUTION 2
This is my own attempt, which incorporates the DownValues[In] command @MichaelE2 used in his answer to the question mentioned above (Want to return name of last defined variable without explicitly naming it):
prettyPrint := Quiet@Block[
{parent = Extract[DownValues[In], {-2, 2}, HoldForm],
daughter1 = Extract[DownValues[In], {-2, 2, 1}, HoldForm],
daughter2 = Extract[DownValues[In], {-2, 2, 1}]},
If[
(! StringContainsQ[ToString@daughter1,
"=="]) &&
((! (Depth[parent] < 5 &&
StringContainsQ[ToString@parent, "["])
&& (Depth[parent] < 5 ||
StringContainsQ[ToString@parent, ":="])
||
(StringMatchQ[
ToString@Extract[DownValues[In], {-2, 2, 1, 2}, HoldForm],
ToString@Extract[DownValues[In], {-2, 2, 1, 2}]] &&
StringContainsQ[ToString@daughter1, "="]))),
Print[daughter1],
Print[daughter1, " = " , daughter2]]]
And here's what it produces:
Integrate[x^2, x];
prettyPrint[];
$\int x^2 \, dx=\frac{x^3}{3}$
int=Integrate[x^2, x];
prettyPrint[];
$\text{int}=\int x^2 \, dx=\frac{x^3}{3}$
int/x;
prettyPrint[];
$\frac{\text{int}}{x}=\frac{x^2}{3}$
%/x;
prettyPrint[];
$\frac{\%}{x}=\frac{\text{Null}[]}{x^2}$
a = 2;
prettyPrint[];
$a=2$
g[x_]:=Sin[x];
prettyPrint[];
$g(\text{x$\_$}):=\sin (x)$
g[Pi];
prettyPrint[];
$g(\pi )= 0$
[Note that the the output is in TraditionalForm because I've been able to accomplish this by setting output to TraditionalForm in Preferences->Evaluation, not because TraditionalForm is called in the code block.]
This code eliminates the extra parentheses and redundant outputs seen in Partial Solution 1, and properly reproduces delayed evaluations. However, it has two problems. First, it's much more cumbersome to use, requiring that it be called for each input. Second, I don't believe it has the generality of Simon's code, since here I've taken a brute-force approach, manually inspecting the forms of DownValues[In] associated with various commands, and using logic statements to distinguish between those that need to be handled one way vs. another. Thus it fails for certain types of inputs, e.g., those that use "%". The latter is not a significant issue in this application, since it's unlikely I would use % in such a notebook (it makes it harder for a non-MMA user to follow); in addition, I could probably correct this specific flaw (perhaps using DownValues[Out]). Nevertheless, it's an indicator that there could be other inputs on which it might also fail.
If you'd like to see what this code does with some other inputs, evaluate prettyPrint[], above, and then evaluate this cell:
b;
prettyPrint[];
a = 2 + 2 + 7 + 5;
prettyPrint[];
Length[{x1, y1, z1}];
prettyPrint[];
matrix1 = {{f1, f2}, {g1, g2}};
prettyPrint[];
matrix2 = Table[100 i + 10 j + k, {i, 3}, {j, 2}, {k, 4}];
prettyPrint[];
Length[matrix2];
prettyPrint[];
Solve[a x + y == 7 && b x - y == 1, {x, y}];
prettyPrint[];
truncatedQ =
Sum[Exp[-\[HBar]*\[Omega]/(2*k*T)]*
Exp[-j*\[HBar]*\[Omega]/(k*T)], {j, 0, n}];
prettyPrint[];
rotatingWaveApprox =
DSolve[{I*h*a2'[t] ==
a1[t]*\[Alpha]/2*Exp[-I*(\[Omega] - \[Omega]21)*t],
I*h*a1'[t] ==
a2[t]*\[Alpha]/2*Exp[I*(\[Omega] - \[Omega]21)*t]}, {a1[t],
a2[t]}, t] // FullSimplify;
prettyPrint[];
REQUESTS
Could you either (a) show me how to modify Partial Solution 1 to eliminate the extra parentheses and redundant output, and show delayed evaluations, or (b) show me how to incorporate Partial Solution 2 into a $PrePrint statement (so I wouldn't have to call it for every input)?
Clear[x]; c = HoldForm@Integrate[x^2, x]; str = "We find that " <> ToString[TraditionalForm@c] <> " = " <> ToString@ReleaseHold[TraditionalForm@c]
Here is screen shot !Mathematica graphics $\endgroup$c1=ReleaseHold[c];
. But maybe this could be applied to gain a solution to the 2nd part of this, which I'll be addressing as a separate question (see "Aside"). $\endgroup$