Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delete the input cell upon evaluation?

I would like to accomplish the following: upon evaluation of an input cell, it should self-destruct (i.e. delete itself). I tried to hack something together with SelectionMove and NotebookDelete, but didn't quite get what I wanted.

Here are potential use cases:

  • the command might be a shorthand for a series of other commands that will be generated dynamically and inserted into the notebook

  • the command might only be used for side effects (e.g. to set a notebook option or to open a new notebook); leaving the command in the notebook after evaluation serves no purpose and creates clutter

Edit: As per Mr. Wizard, the answer is SelectionMove[EvaluationNotebook[], Previous, Cell]; NotebookDelete[];. I don't know why it wasn't working for me before. Here is some code that uses this idiom.

writeAndEval[nb_, boxExpr_] := (NotebookWrite[nb, 
    CellGroupData[{Cell[BoxData[boxExpr], "Input"]}]];
   SelectionMove[nb, Previous, Cell];
   SelectionMove[nb, Next, Cell];
   SelectionEvaluate[nb]);

addTwoAndTwo[] := Module[{boxExpr},
  boxExpr = RowBox[{"2", "+", "2"}];
  SelectionMove[EvaluationNotebook[], Previous, Cell];
  NotebookDelete[];
  writeAndEval[EvaluationNotebook[], boxExpr];
  ]

Now, running addTwoAndTwo[] deletes the original input and makes it look as if you've evaluated "2+2". Of course, you can do all sorts of things instead and not necessarily print to the notebook.

Edit 2: Sasha's abstraction is quite elegant. If you are curious about "real-world" usage of this, check out the code I posted in the "what's in your toolbag" question: What is in your Mathematica tool bag?

like image 913
Leo Alekseyev Avatar asked May 06 '11 07:05

Leo Alekseyev


2 Answers

To affect all Input cells, evaluate this is the notebook:

SetOptions[EvaluationNotebook[], CellEvaluationFunction -> 
  ( (
    SelectionMove[EvaluationNotebook[], All, EvaluationCell]; NotebookDelete[];
    ToExpression@#
  )&)
]

If you only want to affect one cell, then select the cell and use the Options Inspector to set CellEvaluationFunction as above.

like image 138
Mr.Wizard Avatar answered Oct 12 '22 05:10

Mr.Wizard


Or, building on Mr. Wizard's solution, you can create a function SelfDestruct, which will delete the input cell, if you intend to only do this occasionally:

SetAttributes[SelfDestruct, HoldAllComplete];
SelfDestruct[e_] := (If[$FrontEnd =!= $Failed,
   SelectionMove[EvaluationNotebook[], All, EvaluationCell]; 
   NotebookDelete[]]; e)

Then evaluating 2+3//SelfDestruct outputs 5 and deletes the input cell. This usage scenario seems more appealing to me.

like image 24
Sasha Avatar answered Oct 12 '22 05:10

Sasha