How can I work out which functions work with SetOptions?
I don't know the direct answer to the specific question on SetOptions
, but if we look at the purpose of (re)setting options globally, I have some alternative suggestion. A need to set options globally means that you need some persistent configuration of options which you'd like to be applied many times, without extra effort on your side. This can be achieved by creating such option(s) configuration and then always passing options locally (explicitly). It is possible to create helper functions / macros, which would automate this process for you and make it look and feel (almost) as if you have set your options globally.
I have implemented a simplistic options configuration manager, and a lexically scoped construct withOptionConfiguration
, which can be wrapped around your code containing a function call of interest. One can also implement dynamically-scoped environments, for which the option-passing will happen also for all code called from the code within a construct. To my mind, this will save a lot of hassle even if / when you get the exhaustive answer to your direct question, since with the approach I suggest, you don't have at all to remember which functions work with SetOptions
and which don't.
As noted in the question, when you set an option to a function which appears not to work with SetOptions
the options do get set, e.g. from the question:
InputField[Dynamic[x], Sequence @@ Options[InputField]]
but for whatever reason the global setting does not get used locally by default.
Another interesting case is this:
SetOptions[Grid, Background -> RGBColor[1, 0, 0]]
which returns a list of Grid
options with the new Background
, yet when you do the same with GridBox
SetOptions[GridBox, Background -> RGBColor[1, 0, 0]]
SetOptions::nspt: "SetOptions of GridBox is not supported"
So testing the actual "box form" seems to highlight the problem. In this case GridBox
is not supported for SetOptions
even though Grid
did not return an error. So the following solution is a variation of what was provided to me by tech support. Check
can be used to return something in the case of a SetOptions
error:
Check[SetOptions[GridBox, "a" -> "b"], err, SetOptions::nspt]
SetOptions::nspt: "SetOptions of GridBox is not supported."
err
First get a list of names:
names = Names["System`*"]
test the names for the SetOptions
error
list = Quiet[Map[Check[SetOptions[ToExpression[#], "a" -> "b"]; Null, #,
SetOptions::nspt] &, names]];
delete the Null
elements
DeleteCases[list, Null]
{ActionMenuBox,AnimatorBox,CheckboxBox,ColorSetterBox,CounterBox,DynamicBox,
DynamicModuleBox,DynamicWrapperBox,GridBox,InputFieldBox,ItemBox,Line3DBox,LineBox,
LocatorBox,LocatorPaneBox,OpenerBox,OptionValueBox,OverlayBox,PaneBox,PanelBox,
PaneSelectorBox,Point3DBox,PointBox,PopupMenuBox,ProgressIndicatorBox,RadioButtonBox,
RectangleBox,RotationBox,SetterBox,Slider2DBox,SliderBox,TabViewBox,TemplateBox,
TogglerBox,TooltipBox,ValueBox}
So we have a list of 36 types of boxes that cannot be used with SetOptions
.
I think the reason for this is that many functions pass their options to other functions that they call during evaluation. See for example this answer to a related question on StackOverflow. So you can't set the option for the function you use, only the function that the option is passed to.
So for example, in one of my packages (you can guess which one, I have of course changed the initials of my employer to "XYZ") I have a function that starts with the definition:
XYZLineGraph[data:{{__?NumericQ} ..},
dates_List, opts:OptionsPattern[{XYZLineGraph,
DateListPlot, XYZDateTicks, XYZTickGrid, GraphNotesGrid}]] := (* more here *)
I cannot set the defaults for XYZLineGraph
that are actually defaults of DateListPlot
using SetOptions[XYZLineGraph]
.
An example:
test = FinancialData["AAPL", {2008}];
SetOptions[XYZLineGraph, BaseStyle -> Directive[Red]];
XYZLineGraph[test] (* not red *)
SetOptions[DateListPlot, BaseStyle -> Directive[Red]];
XYZLineGraph[test]
(* still not red, because I set the relevant defaults separately *)
DateListPlot[test] (* is red *)
As for identifying which functions can have SetOptions
work this way, I suspect the only way you could do this for built-in functions would be a laborious use of Trace
.