8
$\begingroup$

I need to set StyleDefinitions for a notebook in such manner so I can provide references to multiple stylesheets:

SetOptions[
 EvaluationNotebook[],
  StyleDefinitions->Notebook[{
   Cell[StyleData[StyleDefinitions->"Stylesheet1.nb"]],
   Cell[StyleData[StyleDefinitions->"Stylesheet2.nb"]]
}]
]

This code won't work. Only the first one will be taken into account.

Requirements:

  1. I can't use explicit StyleDefinitions. So importing + merging those styles won't help me because there are going to be many notebooks depending on them and I don't want to update all of them when I change any stylesheet.

  2. I can't use common setup that stylesheets are joined step by step. E.g. EvaluationNotebook[] style points to "Stylesheet1" which contains reference to "Stylesheet2" etc.

    It won't work because I want sometimes to replace "Stylesheet2" with "Stylesheet2b" etc. Would have to have "Stylesheet1" and "Stylesheet1a" to keep the whole chain. At the end I'd have to have multiple "top level" stylesheets for all those possible combinations.

Toys:

{style1, style2} = Notebook[{Cell[StyleData["Input"], #]}] & /@ {
    CellFrame -> True,
    CellFrameColor -> RGBColor[1, 0, 0]};

{path1, path2, path3} = FileNameJoin[{$TemporaryDirectory, #}] & /@ 
    {"Style1.nb",  "Style2.nb", "Style3.nb"};

MapThread[ Export,  {  {path1, path2},  {style1, style2}   }   ]

Additional stylesheet created as described in 2.:

Export[
 path3,
 Insert[
   style1,
   Cell[StyleData[StyleDefinitions -> path2]],
   {1, 1}]
 ]

And I would like

CreateDocument[{Cell[BoxData[RowBox[{"1", "+", "1"}]], "Input"]},
 StyleDefinitions -> Notebook[{
       Cell[StyleData[StyleDefinitions->path1]],
       Cell[StyleData[StyleDefinitions->path2]]
    }]
 ]

gets red frame too, just like:

CreateDocument[{Cell[BoxData[RowBox[{"1", "+", "1"}]], "Input"]},
 StyleDefinitions -> path3
 ]
$\endgroup$
  • 1
    $\begingroup$ @m_goldberg Couldn't it be done the same way it is with linked stylesheets now, only the link structure is specified in a single list for StyleDefinitions? $\endgroup$ – Mr.Wizard Jun 26 '15 at 0:08
  • 3
    $\begingroup$ The multiple inheritance problem is not to be dismissed. Styles can be "re-rooted" (effectively told to ignore inheritance) by using StyleData[name, StyleDefinitions->None]. So, let's assume you have multiple stylesheets which inherit from Core.nb. Each one of them defines a new "Input" style. Some re-root "Input" and others don't. What to do? Also, the multiple inheritance problem introduces serious performance issues...(continued) $\endgroup$ – John Fultz Jun 26 '15 at 17:59
  • 3
    $\begingroup$ If I have two versions of "Title" inherited from different stylesheets and they define FontColor differently, it is no longer acceptable for me to just take the first one. I must figure out where the information came from for each style. If both stylesheets inherit from Default.nb, but only the second stylesheet overrides Default.nb's version of FontColor, then I must choose the second. If only the first overrides, then I must choose the first. This necessity to not just track option settings, but the precise provenance of each and every option setting is expensive...(continued) $\endgroup$ – John Fultz Jun 26 '15 at 18:02
  • 3
    $\begingroup$ ...and these particular computations, although we cache them as much as possible, are one of the most expensive computations in the system. Not to mention the amount of effort to implement which, as has been pointed out in this thread, has a very low payoff because very few people would ever use this feature. $\endgroup$ – John Fultz Jun 26 '15 at 18:05
  • 3
    $\begingroup$ That having been said, your statement that multiple stylesheets "don't work" is not strictly true. They don't work for your purposes. But they do work. You can use multiple StyleData[StyleDefinition->...] cells to mix in new styles. So if, in your example, "StyleSheet2.nb" has styles which don't exist in "StyleSheet1.nb", then they will be amalgamated together in your new stylesheet. So it does do something, just not what you were hoping for. Sorry for the multiple commenting, but I don't feel like I'm actually answering your question. Unless you'd accept "no" as an answer. :) $\endgroup$ – John Fultz Jun 26 '15 at 18:09
4
$\begingroup$

A copy of John Fultz's comments posted June 26, 2015 preserved for enduring reference:

The multiple inheritance problem is not to be dismissed. Styles can be "re-rooted" (effectively told to ignore inheritance) by using StyleData[name, StyleDefinitions->None]. So, let's assume you have multiple stylesheets which inherit from Core.nb. Each one of them defines a new "Input" style. Some re-root "Input" and others don't. What to do? Also, the multiple inheritance problem introduces serious performance issues.

If I have two versions of "Title" inherited from different stylesheets and they define FontColor differently, it is no longer acceptable for me to just take the first one. I must figure out where the information came from for each style. If both stylesheets inherit from Default.nb, but only the second stylesheet overrides Default.nb's version of FontColor, then I must choose the second. If only the first overrides, then I must choose the first. This necessity to not just track option settings, but the precise provenance of each and every option setting is expensive and these particular computations, although we cache them as much as possible, are one of the most expensive computations in the system. Not to mention the amount of effort to implement which, as has been pointed out in this thread, has a very low payoff because very few people would ever use this feature.

That having been said, your statement that multiple stylesheets "don't work" is not strictly true. They don't work for your purposes. But they do work. You can use multiple StyleData[StyleDefinition->...] cells to mix in new styles. So if, in your example, "StyleSheet2.nb" has styles which don't exist in "StyleSheet1.nb", then they will be amalgamated together in your new stylesheet. So it does do something, just not what you were hoping for. Sorry for the multiple commenting, but I don't feel like I'm actually answering your question. Unless you'd accept "no" as an answer. :)

$\endgroup$
  • 1
    $\begingroup$ Just a comment to the last section. That's not true for built-in styles like Input/Output, maybe because we are already inheriting from $FrontEnd (are we? what does it mean? closely related), $\endgroup$ – Kuba Jul 2 '15 at 13:59
  • $\begingroup$ @Kuba, my last paragraph indicates that multiple stylesheets lets you mix in "new styles". What I mean by this is stylenames which have not been previously defined. Input/Output are defined in Core.nb, which is ultimately inherited by nearly every stylesheet in the system. Not many styles you've heard of get defined in Core.nb because we don't want to insert hard-coded stylenames into effectively every stylesheet. So, you won't find Section or Title or Code, for example. But Input and Output are so universal to the way the system works, it seemed better just to put them in Core.nb. $\endgroup$ – John Fultz Aug 14 '15 at 21:17
  • $\begingroup$ @JohnFultz yes, now I see I get your comment wrong. I will try to think about this whole system and my doubts again as soon as I can. Thanks for your input here and in the linked topic. $\endgroup$ – Kuba Aug 14 '15 at 22:10

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.