7

I want to create a textual style that has some CellEvaluationFunction that processes the contents of the cell a certain way. Particularly, it has to do something with the contents of inline cells (formulas in the middle of the text).

The problem is that it seems the CellEvaluationFunction receives an already parsed string (something like what you would get when you "copy as input", so I lose the inline cells. If the cell is one of those that start with an empty box, boxdata, like in StandardForm or TraditionalForm, then the function does get the box structure, but then the writing is not the same: spaces become boxes, it formats as formulas, and inline cells get formatted as text.

How could I solve this?

Basic example

Cell[TextData[{
 "hello ",
 Cell[BoxData[
  FormBox[
   FractionBox["3", "x"], TraditionalForm]],
  FormatType->"TraditionalForm"]
}], "myText", CellEvaluationFunction->myEvalFun, Evaluatable->True]

suppose I want it turned into the string "hello PP\frac{3}{8}PP", and in general, the textual part remaining the same and the inline cells wrapped in PP in TeXForm

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
Rojo
  • 42,601
  • 7
  • 96
  • 188
  • @MikeHoneychurch yes, I see a red x^2 when I execute the output cell you get after executing the example – Rojo Mar 01 '12 at 00:29
  • @MikeHoneychurch, you actually are executing "the output cell" right? – Rojo Mar 01 '12 at 00:46
  • Could you please include a Cell Expression with appearance that you want, with inline boxes, etc.? – Mr.Wizard Mar 01 '12 at 00:56
  • 1
    Rojo, whoops. I've had several windows open and working on a few things at once. the result is lack of attention! – Mike Honeychurch Mar 01 '12 at 01:05
  • @Mr.Wizard there – Rojo Mar 01 '12 at 01:11
  • Thank you. By the way you are asking very interesting questions. – Mr.Wizard Mar 01 '12 at 01:35
  • I cannot figure out how to do this without changing StandardForm -- it appears to be wired this way. I will keep trying. – Mr.Wizard Mar 01 '12 at 01:56
  • @Mr.Wizard thanks and thanks for the help. I have A BIG interest in the front end, but the lack of documentation makes me dizzy. Perhaps I should post another general question where people can leave links and catalogue undocumented cell or notebook options, front end tokens, etc? Not sure if it fits well on the site... Otherwise, at least a question asking for resources to get a deep understanding of it... I'm on the verge of asking a new question about the front end role in the main loop... Parsing, blah, $PreRead, ___, $PrePrint, and exactly how MakeBoxes, the different forms, the Output... – Rojo Mar 01 '12 at 04:43
  • ...style, how it all fits in there, the $Output stream, etc. I'm only guessing so far... What steps are tweakable, what FrontEnd commands are executed. If you can, for example, choose the output to go to a different style other than Output. Anyway... I think that 3 questions in a row it's enough, so for now I'll wait, let the answers flow, sink, see where they lead, and see what important doubts remain... By the way (?), if you have the answer to that projecteuler problem, I'd enjoy checking to see why mine is wrong. Coding is fun, but I refuse to spend time finding what I did wrong, hehe – Rojo Mar 01 '12 at 04:46
  • 1
    @Rojo If you want to understand how the FE communicates with the kernel, you should learn to use LinkSnooper. I use it all the time to see what's actually being passed back and forth on the links. Look up LinkSnooper in the docs, which links to a Javadoc page that documents it. Given the sorts of things you express an interest in, I think you would find it a highly instructive tool. If you have any questions about using it, post them here and I'll try to keep an eye out for them. – John Fultz Mar 01 '12 at 12:20
  • @JohnFultz thanks for your answer. I'm finding LinkSnooper very revealing. I'm having trouble with the path strings in Windows (with spaces), but adding it manually to the contextpath environment var made it work, and then choosing mathkernel manually every time. – Rojo Mar 01 '12 at 21:23
  • :) I've self answered a lot of my doubts in this last hour, thanks – Rojo Mar 01 '12 at 21:44
  • @Rojo here's my Windows LinkSnooper kernel's "Arguments to MLOpen": -LinkMode Launch -LinkName '`javaw` -classpath "`jlinkjar`" com.wolfram.jlink.util.LinkSnooper -kernelname "MathKernel" -noinit' – John Fultz Mar 06 '12 at 02:51

1 Answers1

9

You're not going to get this to work on raw TextData cells. The FE evaluates TextData cells using EnterTextPacket, which merely sends a string along. And, so, the contents must be encoded as a string. Which means you're going to lose all of your typesetting structure. So, let's assume that you've embedded the above cell in a typeset cell where we'll have some more choices. E.g.,

Cell[BoxData[Cell[TextData[{
  "hello ",
  Cell[BoxData[
   FormBox[
    FractionBox["3", "x"], TraditionalForm]]]
 }]]], "myText",
 Evaluatable->True,
 CellEvaluationFunction->myEvalFun]

Now the FE is going to send an EnterExpressionPacket which maintains the full box structure, including inline cells, and that we can work with. From that starting point, I wrote a version of myEvalFun which works for your sample input. It's not very robust...in particular, it assumes that the cell contains one TextData cell with, at most, one level of BoxData cells inside of it. And that the contents of the TextData cell contain nothing other than strings and BoxData cells (other valid TextData contents include StyleBoxes, ButtonBoxes, and TextData cells). But I think it'll give you a good starting point to work from.

myEvalFun[boxes_, form_] := Module[{inlineExprs, val, topExpr},
  inlineExprs = 
   Cases[boxes, 
    Cell[val : BoxData[_], ___] :> 
     "PP" <> ToString[TeXForm[ToExpression[val, form]]] <> "PP", 
    Infinity];
  topExpr = boxes[[1]] /. Cell[_BoxData, ___] :> "``";
  topExpr = 
   topExpr /. {Cell[TextData[{val___String}], ___] :> StringJoin[val],
      Cell[val_String] :> val};
  If[StringQ[topExpr], StringForm[topExpr, Sequence @@ inlineExprs], 
   "Error"]]
John Fultz
  • 12,581
  • 58
  • 73