Formatting usage messages
Asked Answered
M

4

8

If you take a look at the Combinatorica package in Mathematica8 in (mathematicapath)/AddOns/LegacyPackages/DiscreteMath/Combinatorica.m you will find the definitions of functions. What I'm interested to know is how Mathematica knows how to format the usage messages. Something tells me that I'm not looking at the right file. In any case, lets try the following:

Cofactor::usage = "Cofactor[m, {i, j}] calculates the (i, j)th cofactor of matrix m."

This line is the 682 line in the file mentioned above. Now if we run it in a mathematica notebook and we use ?Cofactor we will see the exact same message. But if we get the package then the message is formatted. Here is a screenshot:

enter image description here

Notice how the m, i and j inside the function changed and a double arrow was added to the message. I think the arrow was added to the message because there exists documentation for it. Can someone explain this behavior?


EDIT: This is a screenshot of my notebook file that autosaves to an m file.

enter image description here

As you can see, the L and M are in italic times new roman. Now I will load the package and see the usage.

enter image description here

So far so good. Now lets look at the Documentation center. I will look for the function LineDistance.

enter image description here

As you can see, it shows a weird message. In this case we only want to display the message without any styles. I still can't figure out how the Combinatorica package does this. I followed this to make the index so that the doc center can display the summary. The summary is essentially the usage display. Let me know if I need to be more specific.

Malek answered 4/7, 2011 at 11:20 Comment(0)
O
2

OK, here's the explanation.

Digging in the Combinatorica source reveals this:

(* get formatted Combinatorica messages, except for special cases *)
If[FileType[ToFileName[{System`Private`$MessagesDir,$Language},"Usage.m"]]===File,
Select[FindList[ToFileName[{System`Private`$MessagesDir,$Language},"Usage.m"],"Combinatorica`"],
StringMatchQ[#,StartOfString~~"Combinatorica`*"]&&
!StringMatchQ[#,"Combinatorica`"~~("EdgeColor"|"Path"|"Thin"|"Thick"|"Star"|"RandomInteger")~~__]&]//ToExpression;
]

It is loading messages from ToFileName[{System`Private`$MessagesDir,$Language},"Usage.m"], which on my machine is SystemFiles\Kernel\TextResources\English\Usage.m. This is why all usage messages are created conditionally in Combinatorica.m (only if they don't exist yet). If you look in Usage.m you'll see it has all the ugly boxes stuff that @ragfield mentioned.

I guess the simplest way to have formatted messages is to edit them in the front end in a notebook, and create an auto-save package. This way you can use all the front end's formatting tools, and won't need to deal with boxes.

Orthography answered 4/7, 2011 at 13:28 Comment(6)
That's what I'm doing. I'm formatting the messages in a notebook and auto-saving them to a package. Everything seems fine, but what bothers me is that if you search for it in the Documentation Center then you also see all of boxes. I wonder if I'll have to have a separate Usage.m file with the formatted version. If this is the case, where would it be placed?Malek
@Malek I didn't understand what you meant here: "if you search for it in the Documentation Center then you also see all of boxes". If you never edit your .m file directly, there's no reason to have a separate file for messages. If you do, then you can reserve the auto-save package for messages only, place the resulting .m file in the same directory where your package is (or a subdir of that), and read it in from your main package file.Orthography
let me edit my post and add a screenshot so that you can see what I mean.Malek
screenshots have been uploaded.Malek
@Malek I see. So this is a different question now, about how to integrate with the new doc viewer properly. Unfortunately I have no experience with that...Orthography
Alright, I'll write up a new question with more details, maybe you can come up with an idea if you check my steps.Malek
A
2

I will answer on how the link in the Message is generated. Tracing Message printing shows a call to undocumented Documentation`CreateMessageLink function which returns the URL to the corresponding Documentation page if this page exists:

Trace[Information[Sin], Documentation`CreateMessageLink]

In[32]:= Documentation`CreateMessageLink["System", "Sin", "argx", "English"]

Out[32]= "paclet:ref/message/General/argx"

In some cases we can also see calls to Internal`MessageButtonHandler which further calls Documentation`CreateMessageLink:

Trace[Message[Sin::argx, 1, 1], 
 Internal`MessageButtonHandler | Documentation`CreateMessageLink, 
 TraceInternal -> True]
Abixah answered 5/7, 2011 at 3:58 Comment(0)
T
1

The way to embed style information in a String expression is to use linear syntax. For a box expression such as:

StyleBox["foo", FontSlant->Italic]

You can embed this inside of a String by adding \* to the front of it and escaping any special characters such as quotes:

"blah \*StyleBox[\"foo\", FontSlant->Italic] blah"

This should work for any box expression, no matter how complicated:

"blah \*RowBox[{SubsuperscriptBox[\"\[Integral]\",\"0\",\"1\"],RowBox[{FractionBox[\"1\",RowBox[{\"x\",\"+\",\"1\"}]],RowBox[{\"\[DifferentialD]\",\"x\"}]}]}] blah"
Tavares answered 4/7, 2011 at 12:20 Comment(1)
I was aware of this. The problem is that if I document my functions and I format my usage messages then when I search for them the summary I obtain contains all of the \*StyleBox[.... That's when I noticed that in the package Combinatorica they do not format anything and so their summary comes out without any format. However, when you use the ?NameofFunction then you have the nice format. How is this done?Malek
A
0

I am currently working on rewriting your ApplicationMaker for newer Mathematica-Versions with added functionalities and came to the exact same question here.

My answer is simple: Mathematica dont allowes you to use formated summaries for your symbols (or even build in symbols), so we have to unformate the usage-strings for the summaries. The usagestring itself can still have formatting, but one needs to have a function that removes all the formatingboxes from a string.

i have a solution that uses the UndocumentedTestFEParserPacket as described by John Fultz! in this question.

This funny named Tool parses a String Input into the real unchanged Mathematica BoxForm.

This is my example code:

str0 = Sum::usage

str1=StringJoin[ToString[StringReplace[#, "\\\"" -> "\""]]& /@
(Riffle[MathLink`CallFrontEnd[
FrontEnd`UndocumentedTestFEParserPacket[str0, True]]〚1〛
//. RowBox[{seq___}] :> seq /. BoxData -> List, " "]
/. SubscriptBox[a_, b_] :> a<>"_"<>b
/. Except[List, _Symbol][args__] :> Sequence@@Riffle[{args}, " "])];

str2 = Fold[StringReplace, str1, 
{((WhitespaceCharacter...)~~br:("["|"("|"=") ~~ (WhitespaceCharacter ...)) :> br,
((WhitespaceCharacter ...) ~~ br:("]"|"}"|","|".")) :> br, 
(br:("{") ~~ (WhitespaceCharacter ...)) :> br, 
". " ~~ Except[EndOfString] -> ". \n"}]

and this is how the Output looks like (first Output formatted fancy str0, second simple flat str2)

first Output formatted fancy str0, second simple flat str2

Code Explanation:

str0 is the formatted usagestring with all the StyleBoxes and other formatting boxes.

str1:

UndocumentedTestFEParserPacket[str0, True] gives Boxes and strips off all StyleBoxes, thats because the second argument is True. First Replacement removes all RowBoxes. The outer BoxForm changed to a List of strings. Whitespaces are inserted between these strings the by Riffle. SubscriptBox gets a special treatment. The last line replaces every remaining FormatBox such as UnderoverscriptBox and it does that by adding Whitespaces between the arguments, and returning the arguments as a flat Sequence.

ToString[StringReplace[#, "\\\"" -> "\""]]& /@

was added to include more cases such as StringReplace::usage. This cases include string representations "" with Styles inside of a the usage-string, when "args" has to be given as strings.

str2:

In this block of code i only remove unwanted WhitespaceCharacter from the string str1 and i add linebreaks "/n" after the ".", because they got lost during the Parsing. There are 3 different cases where WhitespaceCharacter can be removed. 1 removing left-and right sided WithespaceCharacter from a character like "[". 2. and 3. removing WithespaceCharacter from left(2) or right(3) side.

Summary

Istead of summary-> mySymbol::usage, use summary -> unformatString[mySymbol::usage] with unformatString being an appropriate function that performes the unformating like descriped above.

Alternatively you can define another usage message manually like

f::usage = "fancy string with formating";
f::usage2 = "flat string without formating";

than use summary -> mySymbol::usage2

Alchemize answered 22/3, 2015 at 19:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.