This version of ShowIt first shown by Leonid Shifrin is particularly useful, it can be used in conjunction with the function ReapTagsReapTags[]
defined below also.
It now uses the LetLLetL[]
function also from Leonid defined here (in order to avoid a nested With for printedExpr).
- The Print output using \$ShowIt = True
$ShowIt = True
allows to use it in the front end if you change its style to Input.
- \$ReverseIt = True
$ReverseIt = True
allows to Print the result of Print in a reverse order as asked in this question.
- The Message if you switch it on using On[Debug::ShowIt]
On[Debug::ShowIt]
prints a MathematicaMathematica message and would stop the code if you used a message breakpoint in MathematicaMathematica or Wolfram WorkbenchWolfram Workbench.
- \$SowIt = True
$SowIt = True
allows to store what would be printed with Print in a symbol.
To see the list of keys defined in the debugSymboldebugSymbol
containing the results extracted from a program you can use the function Keys.
- \$ConsoleIt = True
$ConsoleIt = True
allows to output what would be output with Print but in the MessagesMessages
console accessible in the menu Window>MessagesWindow > Messages
.
- \$GroupIt
$GroupIt
prints expressions in groups of two cells, for example xx
as title, and x=2;x=2;
as expression.
- The System`
System`*
context of ShowItShowIt
and ShowItListShowItList
allows to use them in the Private`Private`*
context of other packages without having to define the package in which these functions are defined (in BeginPackageBeginPackage[]
, see here for more info on the organisation of packages).
- ShowIt
ShowIt[]
is not shown inside another ShowItShowIt
.
- You can define a tag when calling ShowIt
ShowIt
, and restrict which tags let ShowItShowIt
output things using \$ShowItTagPattern$ShowItTagPattern
.
- You can use Debug`ShowIt
Debug`ShowIt
in parallel kernels (as System`ShowItSystem`ShowIt
is recognised as a Global` symbolGlobal` symbol
in a parallel kernel).
All in all ShowItShowIt
and the functions around it show a lot of different aspects of advanced evaluation in MathematicaMathematica that could be interesting to a lot of people.
(*Auxiliary functions*)
SetAttributes[ExtractSymbolName, HoldAll];
ExtractSymbolName[expr_] :=
Module[{T,SR = StringReplace[#, a__ ~~ "$" ~~ DigitCharacter .. :> a] &},
Defer[expr]
//. HoldPattern[System`ShowIt@x_] :> x
/. s_Symbol :> T@MakeExpression@SR@SymbolName@Unevaluated@s
/. T@_@x___ :> x
];
insertBelowEvaluationCell[expr_]:=
(
SelectionMove[EvaluationNotebook[],After,EvaluationCell];
NotebookWrite[EvaluationNotebook[],Cell[BoxData@ToBoxes[expr],"Print"]]
);
$OldLine=-1;
SetAttributes[PrintToConsole,HoldFirst];
PrintToConsole[Defer[expr_],reversePrint_:False]:=PrintToConsole[expr,reversePrint];
PrintToConsole[expr_,reversePrint_:False]:=
(
If[$OldLine!=$Line,
SelectionMove[MessagesNotebook[],After,Notebook];
NotebookWrite[MessagesNotebook[],
Cell[
BoxData@ToBoxes@"","Print",
CellLabel->"During evaluation of In["<>ToString[$Line-1]<>"]:=",
ShowCellLabel->True
]
];
];
If[$OldLine==$Line,
If[reversePrint,
SelectionMove[MessagesNotebook[],Previous,Cell];
SelectionMove[MessagesNotebook[],Before,Cell];
,
SelectionMove[MessagesNotebook[], After, Cell];
]
];
NotebookWrite[MessagesNotebook[],
Cell[
BoxData@ToBoxes@Defer@expr,"Print"
]
];
$OldLine=$Line;
);
SetAttributes[PrintGroupedCells, HoldAll]
PrintGroupedCells[label_, expr_] :=
Module[{tag = ToString@Unique[]},
CellPrint[
CellGroup[
{
ExpressionCell[label, "Item", CellTags -> tag]
,
ExpressionCell[expr, "Input", CellTags -> tag]
}
]
];
NotebookFind[EvaluationNotebook[], tag, All, CellTags];
FrontEndExecute[FrontEndToken["CellGroup"]];
FrontEndExecute[FrontEndToken["OpenCloseGroup"]];
SelectionMove[EvaluationNotebook[], After, Cell];
];
(*Main function*)
System`$ShowIt = True;
System$SowIt = False;
System`$ConsoleIt = False; System
$ReverseIt = False;
System`$GroupIt = False;
Off[System`Debug::ShowIt];
System`$ShowItTagPattern = None;
System`$SowIt = False;
System`$ConsoleIt = False;
System`$ReverseIt = False;
System`$GroupIt = False;
Off[System`Debug::ShowIt];
System`$ShowItTagPattern = None;
System`Debug::ShowIt = "`1`";
SetAttributes[System`ShowIt, HoldAll];
System`ShowIt[expr_,tag_:None]:=
LetL[{evaluatedExpr = expr,exprWithSymbolNamesCorrected = ExtractSymbolName@expr,printedExpr = Replace[Defer[CompoundExpression[exprWithSymbolNamesCorrected = evaluatedExpr,Null]],Defer[x_]:>x,{3}]},
If[MatchQ[tag,System`$ShowItTagPattern],
Message[Debug::ShowIt,printedExpr];
If[TrueQ@System`$ShowIt,
If[TrueQ@System`$ReverseIt,
insertBelowEvaluationCell[printedExpr];
,
If[TrueQ@System`$GroupIt,
PrintGroupedCells[exprWithSymbolNamesCorrected,printedExpr]
,
Print[printedExpr];
];
];
];
If[TrueQ@System`$ConsoleIt,
PrintToConsole[printedExpr,TrueQ@System`$ReverseIt];
];
If[TrueQ@System`$SowIt,
Sow[
evaluatedExpr
,
Function[deferedExpr, ToString@Unevaluated@deferedExpr, HoldFirst] @@ exprWithSymbolNamesCorrected
];
];
];
evaluatedExpr
];
SetSharedFunction[System`ShowItList];
SetAttributes[System`ShowItList, {HoldAll,Listable}];
System`ShowItList[expr_,tag_:None] := System`ShowIt[expr];
SetAttributes[ReapTags,HoldFirst];
ReapTags[expr_]:=
Module[{elements},
Reap[Check[expr,"failed"],_,(elements[#1]=If[Length@#2==1,First@#2,#2])&];
elements
];
SetSharedFunction[Debug`ShowIt];
SetAttributes[Debug`ShowIt,HoldFirst];
Debug`ShowIt[x_]:=ShowIt[x];
SetSharedFunction[Debug`ShowItList];
SetAttributes[Debug`ShowItList,HoldFirst];
Debug`ShowItList[x_]:=ShowItList[x];
The argument of ReapTagsReapTags
can be any expression including the call to a function which is hard to split into simple pieces thus using ReapReap[]
and SowSow[]
as underlying functions is useful in such a case.