Here's a (rather hacky but robust-ish) way to reduce patterns down to the number of arguments they occupy:
reduceSpans[spans_] :=
# /. Except[_Symbol | _Span | _Integer | ∞] -> 1 & /@ spans //.
{
(m_ ;; n_ ;; l_) :> (m + n) ;; l,
(Hold | List)[a___, PatternSequence[m_Integer, n_Integer],
b___] :> {a, m + n, b},
(Hold | List)[a___, PatternSequence[m_Integer, n_ ;; k_],
b___] :> {a, (m + n) ;; k, b},
(Hold | List)[a___, PatternSequence[m_ ;; k_, n_Integer],
b___] :> {a, m ;; (k + n), b},
(Hold | List)[a___, PatternSequence[m_ ;; k_, n_ ;; j_],
b___] :> {a, (m + n) ;; (k + j), b}
}
reducePatterns[p_, opsRep_: (0 ;; ∞)] :=
p /. {
_Symbol?(Function[s,
MatchQ[Unevaluated[s],
Except[Pattern | Optional | Blank | BlankSequence |
BlankNullSequence | PatternSequence | OptionsPattern]
], HoldFirst]) -> List
} //. {
Verbatim[Blank][___] -> 1,
Verbatim[BlankSequence][___] -> (1 ;; ∞),
Verbatim[BlankNullSequence][___] -> (0 ;; ∞),
_OptionsPattern :> opsRep,
Verbatim[HoldPattern][
Verbatim[Pattern][a_, b_]
] | Verbatim[Pattern][a_, b_] :> b,
Verbatim[PatternTest][a_, b_] :> a,
Verbatim[Optional][a_, b_] :> (0 ;; a),
Verbatim[Optional][a_] :> (0 ;; 1)
} // reduceSpans;
This basically reduces the pattern down to simple pattern elements then adds the component numbers for those.
Then we can apply this to SyntaxInfo
(with a little bit of hacking):
paramsBySInfo[sinfo_List, opsLen_: 0] :=
With[{loc = Replace["LocalVariables" /. sinfo, _String -> {}],
arp = "ArgumentsPattern" /. sinfo},
ParameterSequence @@
Fold[
Replace[#2,
{
{i_Integer, ___} :>
If[
Length@# < i,
Replace[#, {
{Span[n_, m_], r___} :>
{Span[Max@{i, n}, Max@{i, m}], r}
}],
#
],
_ :> #
}] &,
reducePatterns[arp, opsLen],
loc
]
];
And for good measure apply it to DownValues
too:
paramsByDVs[dvs_List, opsLen_: 0] :=
With[{choices =
Replace[First@#, Verbatim[HoldPattern][_[a___]] :> Hold[a]] & /@
dvs},
ParameterSequence @@@ (reducePatterns[#, opsLen] &) /@ choices
];
Then write a wrapper that tries SyntaxInformation
first, then DownValues
:
paramNum[f_Symbol] :=
Replace[
SyntaxInformation@f, {
{} :>
Replace[
DownValues[f], {
{} -> 0,
e_ :> paramsByDVs[e, Length@Options@f]
}
],
e_ :> paramsBySInfo[e, Length@Options@f]
}
];
This gives pretty close to what you want I think:
In[375]:= paramNum /@ {Plot, paramNum, Integrate, MemberQ, Plot3D}
Out[375]= {
ParameterSequence[2 ;; ∞],
{ParameterSequence[1]},
ParameterSequence[2 ;; ∞],
ParameterSequence[1 ;; 3],
ParameterSequence[2 ;; ∞]
}
Note that I supplied the number of options to my reduction functions, as that's the max number OptionsPattern[]
should be able to take.
?Plot
produces a number of relevant pieces of information aboutPlot[]
. One such piece of information is the different 'ways' you can callPlot[]
. Perhaps you should look for a way to access the cells that are output from?fun
or??func
and then operate on their contents. Note that the formal number of different options for a function such asPlot[]
is provided byOptions[func]
and in Plot's case there are 62 different options available. $\endgroup$WolframLanguageData["Plot", EntityProperty["WolframLanguageSymbol", "PlaintextUsage"]]
,so I post another post $\endgroup$SyntaxInformation[]
? $\endgroup$LocalVariables
. $\endgroup$