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 have two blocks of code, reproduced at the bottom of this post, each of which provides significant utility. The first, which automatically formats outputs as 'input = output', consists of a \$PrePrint and a \$Post statement. The second, which allows easy inline combination of math and text, consists of a \$PreRead and a \$PrePrint. I’d like to implement both simultaneously, but can’t because only one \$PrePrint statement can be active in given session. I’d thus like to merge these into a single block of code, which contains just one \$PrePrint statement, enabling me to obtain their combined functionality, and thus easily produce outputs that combine input, output and text.
Details
The first piece of code (code block 1, below), written by Simon Rochester (Would like input and output printed on same line, w/o needing extra syntax), directs MMA to print input and output on a single line, in TraditionalForm, without the need for any added syntax. For example:
int = Integrate[x^2, x]
int/x
%/x
$\text{int}=\int x^2 \, dx=\frac{x^3}{3}$
$\frac{\text{int}}{x}=\frac{x^2}{3}$
$\frac{\%}{x}=\frac{x}{3}$
g[x_] := Sin[x]
g[Pi]
$g(x\_):=\sin(x)$
$g(\pi)=0$
a = 2
$a=2$
The second piece of code (code block 2, below), originally written by Mr. Wizard (Notebook formatting - easier descriptions for equations and results?), and which I extended with significant assistance from MB1965 (How to generalize this combined PreRead + PrePrint code?), enables me to output math and text on a single line, with minimal added syntax — I can put text before, after, or both before and after the math; I can also output text alone:
"Text before."; Integrate[x^2, x]
Integrate[x^2, x]; "Text after"
"Text before."; Integrate[x^2, x]; "Text after."
"Text only.";
$\color{blue}{\textit {Text before.}}\>\frac{x^3}{3}$
$\frac{x^3}{3} \>\>\color{blue}{\textit {Text after.}}$
$\color{blue}{\textit {Text before.}}\>\frac{x^3}{3}\>\>\color{blue}{\textit {Text after.}}$
$\color{blue}{\textit {Text only.}}$
Note that the semicolon is only needed as a separator (not a terminator), except in the "text only" case.
Objective
I’d like to implement both code blocks simultaneously, enabling me to obtain their combined functionality, e.g.:
"Letting"; int=Integrate[x^2,x]
"We find that"; int/x; ", as expected."
$\color{blue}{\textit {Letting}}\>\text{int}=\int x^2 \, dx=\frac{x^3}{3}$
$\color{blue}{\textit {We find that}}\>\frac{int}{x} = \frac{x^2}{3}\> \color{blue}{\textit {, as expected.}}$
Motivation
The rationale for this is to enable me to create, with minimal extra work, notebooks that are easily readable by non-MMA users. Thus, once the above objective is met, I can then use R. M.’s code-hiding palette (Is there a way to hide or toggle the visibility of code?) to remove all the input, leaving me with just the output alone.
Issues
The one issue I’ve noticed is that, while code block 1 will output both input and output even if there is normally no printed output, e.g.:
g[x_]:=Sin[x]
$g(\text{x$\_$}):=\sin (x)$
….code block 2 doesn’t output anything when there is no printed math output:
"Text before."; g[x_]:=Sin[x]
[No ouput]
MB1965 suggested this is because “whenever it [\$PreRead] encounters a Null return it doesn't bother to even check $PrePrint and simply returns nothing”. MB1965 further noted that, if an extra ""; ""
is added after the math (where the second pair of quotes can contain text, if text after the math is desired), MMA will then print all the quoted text:
"Text before."; g[x_] := Sin[x]; ""; ""
g[x_] := Sin[x]; ""; "Text after"
"Text before"; g[x_] := Sin[x]; ""; "Text after"
$\color{blue}{\textit {Text before.}}$
$\color{blue}{\textit {Text after.}}$
$\color{blue}{\textit {Text before.}}\>\>\>\color{blue}{\textit {Text after.}}$
It would be great if I could get a fix for this corner case in the merged code.
Code block 1
$PrePrint = (TraditionalForm@HoldForm[In[line] = #] /. line -> $Line /. DownValues[In] /.
{HoldPattern[a_ = a_] :> a,
HoldPattern[a_ = HoldForm[a_]] :> a,
HoldPattern[(c : (a_ = b_)) = b_] :> c,
HoldPattern[(a_ = b_) = c_] :> HoldForm[a = b = c]
}
) &;
$Post = (Replace[#, Null -> HoldForm[In[line]] /. line -> $Line /. DownValues[In]]) &;
Code block 2
$note1 = Null;
$note2 = Null;
$note3 = Null;
$PreRead =
Replace[#, {RowBox[{note1_String?(StringMatchQ[#, "\"*\""] &), ";",
body__, ";",
note2_String?(StringMatchQ[#, "\"*\""] &)}] :> ($note1 =
Style[ToExpression@note1, FontFamily -> "Times", Italic, FontSize -> 15, Blue]; $note2 =
Style[ToExpression@note2, FontFamily -> "Times", Italic, FontSize -> 15, Blue];
RowBox[{body}]),
RowBox[{body__, ";",
note_String?(StringMatchQ[#, "\"*\""] &)}] :> ($note2 =
Style[ToExpression@note, FontFamily -> "Times", Italic, FontSize -> 15, Blue];
$note1 = Null;
RowBox[{body}]),
RowBox[{note_String?(StringMatchQ[#, "\"*\""] &), ";",
body__}] :> ($note1 = Style[ToExpression@note, FontFamily -> "Times", Italic, FontSize -> 15, Blue];
$note2 = Null;
RowBox[{body}]),
RowBox[{note_String?(StringMatchQ[#, "\"*\""] &),
";"}] :> ($note3 = Style[ToExpression@note, FontFamily -> "Times", Italic, FontSize -> 15, Blue];
$note2 = Null; $note1 = Null;
RowBox[{note}]),
e_ :> ($note1 = Null; $note2 = Null; e)}] &;
$PrePrint = Which[($note1 == Null && $note2 == Null && $note3 =!=
Null), # &[$note3, $note3 = Null],
($note1 =!= Null && $note2 =!= Null && $note3 == Null), # &[
Row[{$note1, Spacer[5], Pane@#, Spacer[5], $note2}], $note1 =
Null, $note2 = Null],
($note1 =!= Null && $note2 =!= Null && $note3 == Null), # &[
Row[{$note1, Spacer[5], Pane@#, Spacer[5], $note2}], $note1 =
Null, $note2 = Null],
($note1 =!= Null && $note2 === Null && $note3 == Null), # &[
Row[{$note1, Spacer[5], Pane@#}], $note1 = Null],
($note1 === Null && $note2 =!= Null && $note3 == Null), # &[
Row[{Pane@#, Spacer[5], $note2}], $note2 = Null], True, #] &;