How to prevent Mathematica from inserting random line breaks in usage messages?

I am writing a Mathematica package, and documenting its functions with ::usage messages. However, when I type ?FunctionName to view the usage message of a function, Mathematica inserts seemingly random line breaks into the message.

Here is an example (I replaced the letters in the message with x's, because the actual text of the message doesn't matter):

test::usage =
"xxxxxxxxxxxxxxxxxxxxxx[xxxxxxxx, xxxxxxxxx, xxxxx] xxx x xxxxxxxxxxxxxxx xxxx xxx xxx xxxxxxxxxxx xxxxx xxxxxxxxxxxx x xxxx xxxxxx xxxxxxx xx xxx xxxxxxxxx xxxxxxx xxxxxxxxxxx xxx xxx xxxxxx xxxxxxx.";
?test


The output in Mathematica is as follows:

For some reason, Mathematica chooses to add a line break in the middle of the sentence, which was not there before, instead of using the entire line width. As a result, the output looks ugly - especially since the first line is significantly shorter than the second line.

Is there any way to avoid this?

• Well, there's certainly a way: replace all the spaces with \[NonBreakingSpace]. But this is bad and I hope there's a better answer. Feb 6 '21 at 19:39
• @PatrickStevens: Thanks, this works, but seems a bit extreme... People have been writing Mathematica packages for decades, am I really the first person to encounter this issue? :O
– Wolf
Feb 6 '21 at 20:47
• @Bill: Thanks, I tired this but it doesn't seem to change anything.
– Wolf
Feb 6 '21 at 20:48
• You can always put your own line breaks (\n) in the string where you want them as well. It's obviously not always what you want, but it's easy to do at least. Feb 10 '21 at 22:01

I faced the same problem when writing my own package (OGRe: An Object-Oriented General Relativity Package). My initial solution, which I first posted here, was to convert spaces to \[NonBreakingSpace], which stopped Mathematica from breaking the lines in weird places - but also forced it to break in the middle of words...

Then I found another solution, using a dirty trick where I converted English letters to characters from the Mathematical Alphanumeric Symbols Unicode block, which are inherently bold and/or italic. But that wasn't a good solution either.

However, Carl Woll, in the comments to my answer, suggested a perfect solution combining his answer and my old answer. My new code for a module that generates a nicely-formatted usage message is as follows:

CreateUsageMessage[f_, args_List, msg_String] := (
Evaluate[f::usage] = ToString[TextCell[Row[{
ToString[f],
"[",
Splice[(Style[#, Bold] &)/@ Riffle[args, ", "]],
"] ",
Splice[StringSplit[msg, ""] /. (ToString[#] -> Style[args[[#]], Bold] & /@ Range[1, Length[args]])]
}]],
StandardForm
];
);
Attributes[UsageMessage] = HoldAll;


I prefer bold for the arguments, but if you want italic, simply replace Bold with Italic.

Here is an example of using this module:

CreateUsageMessage[TList, {ID, indices, coordinatesID}, "lists the unique, non-zero components of the tensor object 1 with the index configuration 2 and in the coordinate system 3.
2 should be a list of the form {\[PlusMinus]1, \[PlusMinus]1, ...}, where +1 corresponds to an upper index and -1 corresponds to a lower index.
If the index configuration and/or coordinate system are omitted, the default ones will be used."];


This will produce the following usage message:

Problem solved! Thanks Carl!

• You can just use something like Row[{Style["f", Bold], "[", Style["arg", Italic], "] is xxx"}] to get bold and italic letters. Apr 14 '21 at 15:50
• I tried that, and got an error saying that the usage message must be a string. This is exactly why I had to use this dirty trick in the first place. Apr 14 '21 at 21:34
• I'm talking about the argument of TextCell, which is inside of ToString. Apr 15 '21 at 0:09
• Ah, I see what you mean now. Thanks, that works perfectly! Please see my new edit :) Apr 15 '21 at 14:11

I usually discourage the use of StandardForm strings, but this is a case where it makes sense, since usage messages have to be strings. The key is to format the string as a text cell using TextCell, since these strings line-break as text. Using a simple string instead formats as an expression. So:

test::usage = ToString[
TextCell["xxxxxxxxxxxxxxxxxxxxxx[xxxxxxxx, xxxxxxxxx, xxxxx] xxx x xxxxxxxxxxxxxxx xxxx xxx xxx xxxxxxxxxxx xxxxx xxxxxxxxxxxx x xxxx xxxxxx xxxxxxx xx xxx xxxxxxxxx xxxxxxx xxxxxxxxxxx xxx xxx xxxxxx xxxxxxx."],
StandardForm
];


Then:

?test


• +1. It seems to work as well with TraditionalForm as StandardForm, but perhaps there's a drawback this example does not show? Feb 10 '21 at 22:54
• This did the trick, thanks. But why do you usually discourage the use of StandardForm strings? And are there any issues that may arise from using StandardForm` in my usage messages?
– Wolf
Feb 11 '21 at 2:45