I think I found an easy solution. Although my question was how to extract a simple 1d string, I show how to transform usages into nice and simple html. The rules for this can be adapted so that each box-structure is converted into whatever representation is wanted.
The basic trick is the following: A usage message consists of simple text and of special 2d string which are embraced in "\!\(\*"
and "\)"
. Now the way is to extract the contents of such a special string and to transform it into a Mathematica box expression. In this nested boxes we can replace reliable. This is the main difference to what @einbandi proposed who did this box replacement in the string which will always fail at some point.
Now we have to think about a set of rules to replace the box expressions. Since I wanted this for my IDEA plugin which can handle HTML, I will create a mixture of HTML and MathML. The boxes use pure HTML
boxRules = {
StyleBox[f_, "TI"] :> {"<em>", f, "</em>"},
StyleBox[f_, ___] :> {f},
RowBox[l_] :> {l},
SubscriptBox[a_, b_] :> {a, "<sub>", b, "</sub>"},
SuperscriptBox[a_, b_] :> {a, "<sup>", b, "</sup>"},
RadicalBox[x_, n_] :> {x, "<sup>1/", n, "</sup>"},
FractionBox[a_, b_] :> {"(", a, ")/(", b, ")"},
SqrtBox[a_] :> {"√(", a, ")"},
CheckboxBox[a_, ___] :> {"<u>", a, "</u>"},
OverscriptBox[a_, b_] :> {"Overscript[", a, b, "]"},
OpenerBox[a__] :> {"Opener[", a, "]"},
RadioButtonBox[a__] :> {"RadioButton[", a, "]"},
UnderscriptBox[a_, b_] :> {"Underscript[", a, b, "]"},
UnderoverscriptBox[a_, b_, c_] :> {"Underoverscript[", a, b, c,
"]"},
SubsuperscriptBox[a_, b_, c_] :> {a, "<sub><small>", b,
"</small></sub><sup><small>", c, "</small></sup>"}
};
With this rules we can replace inside a box expression until nothing changes anymore.
convertBoxExpressionToHTML[boxexpr_] :=
StringJoin[
ToString /@
Flatten[ReleaseHold[MakeExpression[boxexpr] //. boxRules]]]
This is basically everything you need to create a html-page of the usages of all known functions. Since I put some more stuff in it like
- creating of links to the official online documentation
- display of attributes
- display of options
I'll put the whole code at the end of this post and please note that it is not cleaned. The whole page looks then like this. Although there are some minor things (like nested 2d strings which are used about 5 times) I think for my plugin I can live with this:
extractUsage[str_] :=
With[{usg =
Function[expr, expr::usage, HoldAll] @@ MakeExpression[str]},
If[Head[usg] === String, usg, ""]]
createLinkName[s_] :=
If[StringMatchQ[ToString@FullForm[s], "\"\\[" ~~ __ ~~ "]\""],
{StringReplace[ToString@FullForm[s], {"\"" :> "", "\\" -> "\\\\"}],
StringReplace[
ToString@FullForm[s], {"\"" :> "",
"\\[" ~~ c__ ~~ "]" :> "character/" ~~ c}]},
{s, s}]
createOptionString[s_] :=
With[{opts =
Function[expr, Options[expr], HoldAll] @@ MakeExpression[s]},
If[opts === {},
"</p><b>Symbol has no options.</b>",
"</p><b>Options: </b>" <>
StringJoin@Riffle[ToString[First[#]] & /@ opts, ", "]
]
]
createHtmlUsage[s_String] := Module[{
usg = extractUsage[s],
attr = Attributes[s],
link, linkname},
{linkname, link} = createLinkName[s];
"<h3><a href=\"http://reference.wolfram.com/mathematica/ref/" <>
link <> ".html\">" <> linkname <> "</a></h3>" <> If[usg =!= "",
"<ul><li>" <>
StringReplace[
StringReplace[
usg, {Shortest["\!\(\*" ~~ content__ ~~ "\)"] :>
convertBoxExpressionToHTML[content],
"\n" :> "<li>"}
], {"\[Null]" :> "",
a_?(StringMatchQ[ToString@FullForm[#],
"\"\\[" ~~ __ ~~ "]\""] &) :>
StringReplace[
ToString[a, MathMLForm], {WhitespaceCharacter :> ""}]}
] <> "</ul>", ""] <> "<b>Attributes:</b> " <>
StringJoin[ToString /@ Riffle[attr, ", "]] <>
createOptionString[s] <> "\n"
]
names = Names["System`*"];
Export["tmp/usageMessages.html", StringJoin[createHtmlUsage /@ names], "Text"]
ToString
? $\endgroup$grep
the contents of those folders again. $\endgroup$