5
$\begingroup$

Help!

I am writing a package with a function which takes lots and lots of different options which are Strings. When used, the front end autocompletion is suggesting them in Symbol form. If the resulting code is run, it is added to the General` context. Observe:

Define the Options of MyFunc, and its SyntaxInformation

Options[MyFunc] = {"MyOpt" -> True};
SyntaxInformation[MyFunc] = {"ArgumentsPattern" -> {_, OptionsPattern[]}};

Then, start typing MyFunc[3.2, My, and you will see MyOpt as a suggestion:

enter image description here

If you run the finished statement MyFunc[3.2, MyOpt->False], the program works as if it had been a String (totally unacceptable), and the option symbol MyOpt is added to the Global` context (also totally unacceptable):

enter image description here

This leads to a proliferation of these symbols in the user's front end, which is annoying. How can I prevent this?

$\endgroup$
6
$\begingroup$

You can use undocumented "OptionNames" property of SyntaxInformation to customize option names suggestions (and coloring of invalid option names).

MyFunc // ClearAll
MyFunc // Options = {"MyOpt" -> True};
MyFunc // SyntaxInformation = {
    "ArgumentsPattern" -> {_, OptionsPattern[]},
    "OptionNames" -> {"\"MyOpt\""}
};

After typing MyFunc[3.2, My I get (in version 11.0):

Auto-completion suggestions screen-shot

$\endgroup$
  • $\begingroup$ Much nicer solution that mine. :-) Any idea why FE`OC doesn't seem to be used here? Is there another mechanism you are aware of? $\endgroup$ – Mr.Wizard Jul 23 '17 at 13:23
  • $\begingroup$ @Mr.Wizard No idea, sorry. Your answer here is my first contact with FE`OC. $\endgroup$ – jkuczm Jul 23 '17 at 13:35
  • $\begingroup$ @jkuczm On my computer I'm finding that if I set SyntaxInformation for a function to take only options as in "ArgumentsPattern" -> { OptionsPattern[]}, then the front end fails to suggest a list of possible options. Is this happening on your computer too? $\endgroup$ – QuantumDot Jul 31 '17 at 21:46
  • $\begingroup$ @QuantumDot Yes, it starts suggestions from second argument of MyFunc, even if according to "ArgumentsPattern" it should start from first. Looks like a bug. $\endgroup$ – jkuczm Aug 1 '17 at 9:49
3
$\begingroup$

By convention option names are Symbols, and String equivalents are accepted.

For example all the formal Options of Plot are Symbols:

Head /@ First /@ Options[Plot] // Tally
{{Symbol, 60}}

Yet you can give options as Strings as well:

Plot[x^2, {x, 1, 10}, "PlotStyle" -> Red, "Frame" -> True,
  "Axes" -> False, "PlotLabel" -> "This is a plot"]

enter image description here

What you want therefore appears to go against the intentional design of Mathematica.

You may need to specifically interfere with that design to achieve your goal. I thought it would be possible to do this by modifying Front End function FE`OC but changing that doesn't seem to have an effect; I suspect a different function is now used to populate these menus, but I cannot find it.


With modification of FE`OC not working as hoped, and remembering Prompt a set of possible options it occurred to me that pre-escaping a String option name might work, and indeed it does! Well, sort of.

Options[MyFunc] = {"\"MyOpt\"" -> True};

SyntaxInformation[MyFunc] = {"ArgumentsPattern" -> {_, OptionsPattern[]}};

MyFunc[x_, OptionsPattern[]] := {x, OptionValue["MyOpt"]}

MyFunc[foo, MyO]  (* while typing in MyO *)

enter image description here

Selecting this does actually produce a String option name. However running it give an error:

MyFunc[foo, "MyOpt" -> bar]

OptionValue::nodef: Unknown option MyOpt for MyFunc. >>

{foo, bar}

So OptionValue doesn't like this, but it still extracts the option value correctly. It does not however handle the default case:

MyFunc[foo]

OptionValue::optnf: Option name MyOpt not found in defaults for MyFunc. >>

{foo, "MyOpt"}

I think therefore that you may need to avoid OptionValue and write your own filter.

You will also need to deal with adding or modifying the Options list, as

SetOptions[MyFunc, "MyOpt" -> False]

SetOptions::optnf: MyOpt is not a known option for MyFunc. >>

Before you pursue this further I think you should consider if you really have good reason to deviate from the existing design of Mathematica and all the headache that might entail.


Would modifying the list of Symbols returned by ? be of any use to use? See e.g.

$\endgroup$
  • $\begingroup$ Thank you for your very detailed answer! One thing that strikes me as a little inconsistent is "by convention all option names are Symbols, and String equivalents are accepted." This seems to run counter to what @Szabolcs said here: "...to avoid cluttering the name space". Do you rekon he is wrong? $\endgroup$ – QuantumDot Jul 23 '17 at 17:14
  • $\begingroup$ @QuantumDot No, I don't think he is wrong. Most of the old functions I am most familiar with are like Plot, using Symbol option names, but indeed (some) newer functions that I use less have String option names. I guess this is inconsistency in the design itself, and the auto-completion code was probably written by someone used to the old convention as I was. $\endgroup$ – Mr.Wizard Jul 24 '17 at 1:05

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.