6
$\begingroup$

Let's say I have a stylesheet with two slightly different "Output" and "Output2" styles.

"Input" generates "Output" which can be switched with "Output2" using Tab/Backspace.

The problem is that "Output2" is replaced with "Output" if you evaluate input again. I'd like to preserve changed style.

Unfortunately there is not much flexibility/documentation for GeneratedCellStyles

I have a solution but my approach looks ugly because one has to deal with exceptions like Input being the last cell in the notebook or protecting other styles which follow Input.

So the question is:

Is there something I've missed in cell/notebook options? Can my code be improved in any way?

The solution needs to work from a stylesheet level.

My approach

The fix is to use CellProlog/CellEpilog for "Input" style.

CreateDocument[
  { ExpressionCell[Defer[1 + 1], "Input"]
  , ExpressionCell[2, "Output2"]
  }
, StyleDefinitions -> Notebook[
    { Cell[StyleData[StyleDefinitions -> "Default.nb"]]
    , Cell[StyleData["Output"]
      , StyleKeyMapping -> {"Tab" -> "Output2"}]
    , Cell[StyleData["Output2", StyleDefinitions -> StyleData["Output"]  (*1*)]
      , Background -> RGBColor[1, 0, 1]
      , StyleKeyMapping -> {"Backspace" -> "Output"}
      ]
    , Cell[ (*here starts the solution*)
        StyleData["Input"]
      , CellProlog :> SetOptions[ (*2*)
          EvaluationCell[]
        , TaggingRules -> {"OutputStyle" -> Module[{nc = NextCell[], style}
          , Which[
              nc === None
            , Inherited
            , MemberQ[{"Output2"}
              , style = ("Style" /. Developer`CellInformation[nc] (*3*))
              ]
            , style
            , True
            , Inherited
            ]
          ]}]
        , CellEpilog :> Module[
            { nc = NextCell[]
            , style = CurrentValue[EvaluationCell[], {TaggingRules, "OutputStyle"}]
            }
          , Which[
              Or[nc === None, style === Inherited]
            , Null
            , True
            , SelectionMove[nc, All, Cell, AutoScroll -> False]
            ; FrontEndTokenExecute[EvaluationNotebook[], "Style", style](*4*)
            ; SelectionMove[EvaluationNotebook[], After, Cell]
            ]
          ]
        ]
      }
    ]
   ]

Refs

  1. Is there a way to base one style on another?

  2. SetOptions because of Notebook's TaggingRules inherit too much

  3. How can I get the style of selected cells?

  4. Set the style of a cell

$\endgroup$
  • $\begingroup$ If you substitute CellEpilog :> Module[...] by something like (this only works for 1+1 ... ) CellEvaluationFunction->((NotebookWrite[EvaluationNotebook[],Cell[BoxData@ToExpression@#,CurrentValue[EvaluationCell[], {TaggingRules, "OutputStyle"}]]])&) it sems to not flicker. $\endgroup$ – Rolf Mertig Nov 2 '17 at 13:17
  • $\begingroup$ @RolfMertig yep, so it does not work for input cells that contain no (1+1;) or multiple outputs (1+1 \n 1+1). $\endgroup$ – Kuba Nov 2 '17 at 14:00
1
$\begingroup$

Here's an improvement. We can drop CellEpilog and set "GeneratedCellStyles" from CellProlog using old code.

CreateDocument[
  { ExpressionCell[Defer[1 + 1], "Input"]
  , ExpressionCell[2, "Output2"]
  }
, StyleDefinitions -> Notebook[
    { Cell[StyleData[StyleDefinitions -> "Default.nb"]]
    , Cell[StyleData["Output"]
      , StyleKeyMapping -> {"Tab" -> "Output2"}
      ]
    , Cell[StyleData["Output2", StyleDefinitions -> StyleData["Output"]  (*1*)]
      , Background -> RGBColor[1, 0, 1]
      , StyleKeyMapping -> {"Backspace" -> "Output"}
      ]
    , Cell[StyleData["Input"]
      , CellProlog :> SetOptions[
          EvaluationCell[]
        , "GeneratedCellStyles" -> {
            "Output" -> Module[{nc = NextCell[]}
            , Which[
                nc === None, Inherited
              , "Output2" === ("Style" /. Developer`CellInformation[nc]), "Output2"
              , True, Inherited
              ]
            ]
          }
        ]
      ]
     }
   ]
 ]

I set the option for EvaluationCell so that in case of Abort it won't affect the whole notebook.

$\endgroup$

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.