3
$\begingroup$

Given a NotebookObject I'd like to know what settings all of its Cells have. This could be useful if I needed to distribute my notebook to a friend who didn't have my stylesheet, say.

Any way to do this?

$\endgroup$
2
$\begingroup$

We'll do this in two parts. First, we'll resolve the inheritance chain (very simple since multiple inheritance isn't supported) then we'll merge all the cells and styles.

Making the chain

This is pretty easy. We just use the fact that we can pull a notebook's stylesheet like:

Lookup[NotebookInformation[nb], "StyleDefinitions", {}]

And if it inherits from a different stylesheet that sheet is in the second argument.

So we can build the chain like:

processSheet // Clear
processSheet[{nb_NotebookObject, {implements_NotebookObject, ___}}] :=
   implements;
processSheet[_] := Nothing;
getSheet // Clear;
getSheet[nb_NotebookObject] :=

  processSheet@Lookup[NotebookInformation[nb], "StyleDefinitions", {}];
getSheet[e_] := e;
getStyleSheetChain[nb_NotebookObject] :=
 Rest@
  Module[{s = <||>},
   FixedPointList[
    getSheet, 
    Replace[Lookup[NotebookInformation[nb], "StyleDefinitions", {}],
     {
      {n_NotebookObject} :> n,
      {n_NotebookObject, {i_, ___}} :> i
      }
     ]
    ]
   ]

Making the mapping

Next we need to get the full chain of styles. This is a pretty obvious process, so I'll just drop the code:

mergeStyles[styles_]:=
  Merge[
    {
      styles
      },
    If[AnyTrue[#, ListQ[#]&&OptionQ[#]&],
      Merge[Flatten@#, Last],
      Last@#
      ]&
    ];
mergeStyleSet[styles_]:=
  Merge[
    Normal/@styles,
    mergeStyles
    ];

getStyleChain[nbs:{__NotebookObject}]:=
  Module[
    {
      cells=Cells/@nbs,
      names,
      ops
      },
    ops=ConstantArray[<||>, Length@nbs];
    MapIndexed[
      Replace[
        #,
        {
          Cell[StyleData[name:_String|All, env:_String|None:None], o___?OptionQ]:>
            Set[
              ops[[#2[[1]], Key@If[env===None, name, {name, env}] ]],
              Merge[
                {
                  Normal@Replace[
                      ops[[#2[[1]], Key@If[env===None, name, {name, env}]]], 
                      Except[_Association]:><||>
                      ],
                  o
                  },
                Last
                ]
              ],
          c:Cell[
            StyleData[
              name:_String|All, env:_String|None:None,
              StyleDefinitions->StyleData[parent_]
              ], 
            o___?OptionQ
            ]:>
            With[
              {
                inherited=
                  mergeStyles@
                    Flatten@List@Lookup[ops[[;;#2[[1]]-1]], Key@parent, <||>]
                },
              Set[
                ops[[#2[[1]],Key@If[env===None, name, {name, env}] ]],
                Merge[
                  {
                    Replace[
                      ops[[#2[[1]], Key@If[env===None, name, {name, env}]]], 
                      Except[_Association]-><||>
                      ],
                    o
                    },
                  Last
                  ]
                ]
              ]
          },
        1
        ]&,
      NotebookRead/@cells
      ];
    mergeStyleSet@ops
    ]

Examples

Now we can do things like:

getStyleSheetChain[EvaluationNotebook[]]

enter image description here

Then we can pull the style set like:

styles = getStyleChain[getStyleSheetChain[EvaluationNotebook[]]];

And then for example pull the list of styles for a "CodeText" cell in my EvaluationNotebook[]:

styles["CodeText"]

<|CellMargins -> {{66, 10}, {3, 15}}, LineSpacing -> {1, 1, 1}, 
 MenuSortingValue -> 1540, FontColor -> GrayLevel[0.45]|>

Or pull the styles with a CellEventActions mapping:

Keys@Select[styles, KeyExistsQ[CellEventActions]]

{"AttachedDialogCell", "Input", "Code", "WolframAlphaShort", \
"WolframAlphaShortInput", "WolframAlphaLong", "NaturalLanguageInput", \
"DeployedNLInput"}
$\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.