3
$\begingroup$

Short version: PasteButton will paste its contents at the input cursor. I am looking to create a similar button that will paste something into a new cell and evaluate that cell immediately.


Requirements:

  • Must paste content into a new cell (never inside an existing cell, regardless of the current selection).
  • The new cell may be created either below the position of the button or at/below the position of the input cursor (both are acceptable, first is preferred).
  • Must minimize dependency on dynamic evaluations. Ideally, it should use only the FE but not the kernel. (Think of evaluating the just created cell as adding it to the evaluation queue, i.e. an FE action, not a kernel action).
  • The button will be styled as a hyperlink and inlined into running text. It will be labelled with some code. This is the code that will be pasted and evaluated. The design should not interfere with this use case.

"What have you tried?"

From the documentation of Button,

enter image description here

Thus my first try was:

Button[Defer[1 + 1], None, BaseStyle -> "CopyEvaluateCell"]

There are two issues with this, one which I could solve and one which I could not.

  1. The contents of the output cell will be selected. This I could solve (see below).

  2. Evaluate the line above, press the button, evaluate the line again, press the button again. This creates an extra, unneeded, empty input cell (see red arrow below). This I could not solve.

enter image description here

I solve the first issue by looking up the ButtonFunction in the default stylesheet and modifying it. The original ButtonFunction was:

(FrontEndExecute[{
    FrontEnd`SelectionCreateCell[
     FrontEnd`InputNotebook[], All], 
    FrontEnd`NotebookApply[
     FrontEnd`InputNotebook[], #, All], 
    FrontEnd`SelectionEvaluateCreateCell[
     FrontEnd`InputNotebook[], All]}]& )

We can remove All from SelectionEvaluate to prevent the output from being selected. However, the second issue still remains.

Button[
  Defer[1 + 1], 
  None,
  ButtonFunction :> (FrontEndExecute[{
    FrontEnd`SelectionCreateCell[FrontEnd`InputNotebook[], All], 
    FrontEnd`NotebookApply[FrontEnd`InputNotebook[], #, All], 
    FrontEnd`SelectionEvaluateCreateCell[FrontEnd`InputNotebook[]]
  }] &)
]
$\endgroup$
5
$\begingroup$

This seems to fit your needs:

Button[
   Defer[1 + 1],
   FrontEndExecute[{
    FrontEnd`SelectionMove[FrontEnd`EvaluationCell[], After, Cell], 
    FrontEnd`NotebookWrite[FrontEnd`InputNotebook[], #, All], 
    FrontEnd`SelectionEvaluateCreateCell[FrontEnd`InputNotebook[]]
   }] &,
   Evaluator -> None
]
| improve this answer | |
$\endgroup$
  • $\begingroup$ Could the EvaluationNotebook[] and the InputNotebook[] even be different, and if yes, can that cause problems here (in some special edge case)? I assume that the EvaluationCell[] is in the EvaluationNotebook[]. $\endgroup$ – Szabolcs Dec 30 '19 at 11:07
  • $\begingroup$ @Szabolcs Haven't I copied the snippet I would have probably used EvaluationNotebook from the beginning. It could be different if somehow the button's parent notebook wasn't selected at a click event. That is the case for palettes which are WindowClickSelect-> False. TLDR: should not matter but you can use EvaluationNotebook to be safer. $\endgroup$ – Kuba Dec 30 '19 at 11:16
  • $\begingroup$ Here's a followup, if you have any tips: mathematica.stackexchange.com/q/212133/12 Otherwise, I'll just leave it as it is. $\endgroup$ – Szabolcs Dec 30 '19 at 11:43
  • $\begingroup$ For now, I worked around it by ensuring that the cell containing the button is always printed last. It seems to risky to try to deal with the cell groups (e.g. what if the user unexpectedly copies and pastes that cell to elsewhere)? $\endgroup$ – Szabolcs Dec 30 '19 at 11:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.