A Cell
can be made so that it is not possible to delete using the computer keyboard or the edit menu. To do this, use SetOptions[<cell_in_question>, Deletable->False]
, doing this manually using Cell > Show Expression, or make a style in your notebook's stylesheet that with that option set.
If you would like to make it so one can't edit your cells using the keyboard, you can set Editable->False
which can also be done in the Cell > Cell Properties menu.
Note that these cells can still be deleted by unsetting this option or by manually removing them in the Notebook
expression and using NotebookPut
. I'm sure there are other ways to do this as well that I simply don't know.
To fully lock a cell, consider reading through this question to get ideas.
As for storing print in a variable,
Print
creates a new cell with the style "Print"
. You can change this to "Input"
using, for example, Command-9 on a Mac. This will make it work like a normal "Input"
cell.
If you want to store the value from Print
in a variable, simply store it before printing or, if you absolutely must do it at run-time, wrap the following hacky function around your code:
$printCache = {};
cachedPrint[code_] :=
Internal`InheritedBlock[{Print},
Unprotect@Print;
Print[stuff__] /; (! TrueQ@$printCachingOverload) :=
Block[{$printCachingOverload = True},
AppendTo[$printCache, {stuff}];
Print[stuff]
];
Protect@Print;
code
];
cachedPrint~SetAttributes~HoldFirst;
Then use it like, say:
cachedPrint[Do[someSuperCoolFunction[x]; Print[x, " etc."], {x, 10}]]
It will print everything, but all the arguments to print will be stored in $printCache
e.g:
In[33]:= $printCache
Out[33]= {{1, " etc."}, {2, " etc."}, {3, " etc."}, {4, " etc."}, {5,
" etc."}, {6, " etc."}, {7, " etc."}, {8, " etc."}, {9,
" etc."}, {10, " etc."}}
And just to check that the DownValues
we set on Print
have not been saved:
In[34]:= DownValues@Print
Out[34]= {}
This is not the best way to do this. It's much easier to just store the value yourself, but if you have to capture it you can do it like this.
However, this kind of strategy is useful for capturing and rerouting messages by applying a similar overload strategy to Message
and capturing pieces of MessageName
. Of course, even better there is to use GeneralUtilities`WithMessageHandler
and work with the Failure
object.