Introduction
I often have the problem that in an expression, I want to change an option. If we are sure the option is not present, we could simply use Append[expression, opt -> val]
. But sometimes such an expression is very long and it can be a bit of a pain to see if this option is already present.
Example
We have
Notebook[{Cell["hello", "Text"]}]
we want
Notebook[{Cell["hello", "Text"]}, Background -> LightGreen]
Mathematica has some built in functions for setting options. They are SetOptions
, Option
in combination with Set
(which I think does the same thing as SetOptions
) and CurrentValue
in combination with Set
. None of these seem to do what I want.
Silly things I tried
The fact that we can use Options
with Set
may sound promising, but although we can ask the value of an option in an expression, we cannot set it.
Example
kkkk:=f[2,q->c,z->x,zz->xx];
Options[kkkk]
Options[kkkk, q]
{q -> c, z -> x, zz -> xx} {q -> c}
But
Options[kkkk] = {q -> d, z -> x, zz -> xx}
gives an error and
Options[Unevaluated@kkkk] = {q -> d, z -> x, zz -> xx}
does something strange.
Nice function
So I have made my own function
setExpressionOptions[
head_[
a__,
b : Longest[ OptionsPattern[], 1],
Longest[(symb_ -> _) ..., 2],
d : OptionsPattern[]
],
symb_ -> val_
] := head[a, b, symb -> val, d]
Examples of use
setExpressionOptions[f[2, q -> b, z -> x, zz -> xx], q -> c]
f[2, q -> c, z -> x, zz -> xx]
setExpressionOptions[f[2, z -> x, zz -> xx], q -> c]
f[2, z -> x, zz -> xx, q -> c]
The function also works with Unevaluated
setExpressionOptions[Unevaluated[Plot[x, {x, 0, 1}]], PlotStyle -> Red]
(*a plot with a red line*)
Note that we really need Unevaluated
here, otherwise the expression with head Plot
evaluates to an expression with head Graphics
, which does not work with PlotStyle
.
Possible extension
We can define the function setOptions
like this
setOptions[
x_ /; MemberQ[{NotebookObject, CellObject, FrontEndObject, InputStream,
OutputStream, Symbol, String}, Head[Unevaluated@x]], y___
] := SetOptions[x, y]
setOptions[z___] := setExpressionOptions[z]
Examples of use
setOptions[EvaluationNotebook[], Background -> LightGreen]
(*makes the background LightGreen*)
setOptions[f[1], q -> r]
f[1, q -> r]
Question
I like the functions quite a lot, but they could be better. It would be nice if we could set any number of options at once using setExpressionOptions
.
Example of desired evaluation
setExpressionOptionsBetter[
Notebook[{Cell["hello", "Text"]}, Background -> LightGreen],
Background -> Cyan,
DynamicUpdating -> True
]
Notebook[{Cell["hello", "Text"]}, Background -> Cyan, DynamicUpdating -> True]
Note that SetOptions
works the same way; beyond position one there are any number of Rule
s. That also makes integrating this case in setOptions
easier.
Also I am sure I left out a lot of heads in the test in setOptions
. The Q&A How can I work out which functions work with SetOptions? sounded promising for making the list more complete, but I guess it is not helpful.
Main question*: Can we add the additional functionality?
sub Question 1: Did I overlook anything and can this be done easier?
sub Question 2: Can this use of
Longest
lead to bad performance? (probably no)