7

For example I have a block of code

Module[{}, a=1;b=2;...]

I want to have a function called gencode, so when I run gencode, it will generate an input cell which contains this block of code just like I type them by hand.

How to write this gencode?

matheorem
  • 17,132
  • 8
  • 45
  • 115

2 Answers2

9

CellPrint plus ExpressionCell are tools for generating cells. They do not hold their arguments, so some control of evaluation is necessary (Defer). [Update: In response to Szabolcs' comment about a default option value for CellPrint is GeneratedCell -> True (see also this comment by John Fultz), we should let options be passed.]

ClearAll[gencode];
SetAttributes[gencode, HoldAll];
gencode[code_, opts : OptionsPattern[Cell]] := 
 CellPrint@ExpressionCell[Defer@code, "Input", opts];

Examples:

Mathematica graphics

Or following Szabolcs:

gencode[Module[{a, b}, a = 1; b = 2; a + b], GeneratedCell -> False]
Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • 4
    +1, this is exactly what Defer is for. One note: the Cell will have GeneratedCell -> True . This means that Cell -> Delete All Output will delete it. It depends on the use case whether this is desired or not (I think usually it is not). One can always set GeneratedCell -> False in ExpressionCell. – Szabolcs Apr 30 '17 at 13:37
  • @Szabolcs Thanks for such valuable comment. +1 : ) – matheorem Apr 30 '17 at 14:20
  • I don't know whether this should be a separate question but how do I appropriately control evaluation in the case where for example I have set the value a=1 already and now want to generate b=1 by using something of the form gencode[b=a]? That is I do want to fully evaluate both b and a but I don't want to evaluate the final set. – Kvothe Mar 19 '21 at 19:04
  • 1
    @Kvothe With[{a = a}, gencode[b = a]]? Or did I misunderstand what you wanted? – Michael E2 Mar 19 '21 at 19:15
  • @MichaelE2, thanks! – Kvothe Mar 19 '21 at 19:33
  • When I use this with the optional argument "InitializationCell", I get an initialization cell but it wraps the text unlike it usually does for this cell type. If I convert it "again" to an initialization cell it doesn't wrap. Is there anyway to create non-wrapping text programmatically? (I feel I just wasted my question on a stupid one before and now I have a better one. Hope I didn't run out of your patience.) – Kvothe Mar 19 '21 at 19:38
  • @Kvothe In case it takes time, let's go to chat to work it out: https://chat.stackexchange.com/rooms/2234/wolfram-mathematica – Michael E2 Mar 19 '21 at 19:57
  • It is worth to mention here, that usage of CellPrint for producing "Input" cells is discouraged. – Alexey Popkov Jul 21 '22 at 05:12
  • @AlexeyPopkov Note that Szabolcs raised this issue in the first comment, and I adjusted the definition of gencode to handle the last example, which addresses John Fultz's concern. John is obviously the leading expert on the FE, but I think the issue with GeneratedCell -> True is fairly clear and not subtle. -- Updated to highlight the point. – Michael E2 Jul 21 '22 at 13:55
  • Unfortunately, it is more subtle than it should be. Try Do[gencode[#, GeneratedCell -> False] &[i], {i, 3}] - it prints in the reverse order! I don't know how to reproduce the behavior of NotebookWrite using CellPrint. Also, look at this example, which highlights why CellPrint shouldn't be used in general for producing "Input" cells. – Alexey Popkov Jul 22 '22 at 05:26
  • @AlexeyPopkov Do[gencode[#, GeneratedCell -> False] &[i], {i, 3}] does just what the docs for CellPrint say: It inserts the cell just below the cell being evaluated. It's in the proper order: The last cell printed is just under the evaluated cell. I rather think this example goes beyond the use-case in the OP. If you want to insert multiple cells in specific places in a notebook, that might deserve a separate question. For instance, CellPrint on a list of cells does what you seem to want. But maybe you want help with NotebookWrite. – Michael E2 Jul 23 '22 at 00:08
  • Here is a contradictory with the Docs: CellPrint with GeneratedCell -> False is a special case, while by default Do[gencode[#] &[i], {i, 3}] prints in the standard order (what contradicts the Docs, obviously). Also CellPrint[Table[Cell[ToString@i, "Input", GeneratedCell -> False], {i, 3}]] prints in the reverse order too, so it doesn't allow to reproduce the behavior of NotebookWrite (and also seems to be a bug). – Alexey Popkov Jul 23 '22 at 00:41
4

Here's another way:

NotebookWrite[
    EvaluationNotebook[]
  , Cell[ BoxData @ MakeBoxes @ Module[{a, b}, a = 1; b = 2; a + b], "Input"]
]

even this will do

NotebookWrite[
    EvaluationNotebook[]
  , MakeBoxes @ Module[{a, b}, a = 1; b = 2; a + b]
]

But only because "Input" is the default cell style.

Kuba
  • 136,707
  • 13
  • 279
  • 740