7
$\begingroup$

I would like to be able to set a limit on the maximum number of characters on every line in notebook (for example, 80). Does Mathematica provide this functionality?

$\endgroup$
0

1 Answer 1

6
$\begingroup$

There is PageWidth:

PageWidth is an option for output streams and for cells which specifies how wide each line of text should be allowed to be.

Possible settings for cells are:

  • WindowWidth the width of the window on the screen
  • PaperWidth the width of the page as it would be printed
  • n explicit width given in printer's points

We can set this option at the Notebook level (with lower priority than at the level of individual cell):

The Wolfram Language allows you to take any cell option and set it at the notebook level, thereby specifying a global default for that option throughout the notebook.

We have to take into account that PageWidth includes the following values:

  1. CellMargins

  2. CellFrameMargins with the space occupied by CellFrame (if CellFrame is turned on)

  3. The space occupied by CellLabel (if is turned on and shown on the left, what is controlled by ShowCellLabel and CellLabelPositioning); CellLabelMargins seems to be ignored by now.

  4. CellFrameLabelMargins with the space occupied by CellFrameLabels themselves (if the latter are turned on)

[Update: 5. "Widths" suboption of CellBracketOptions. I didn't try to figured out how it interferes with the above options.]

From the above list only calculation of the space occupied by CellLabel and CellFrameLabels isn't straightforward since it isn't known beforehand how much space do they need. Fortunately, by default there are no CellFrameLabels, and CellLabel also doesn't take any additional space because

With the default setting CellLabelPositioning -> Automatic, the label for a cell is placed to the left of the cell if it is short enough to fit in the left margin. Otherwise, the label is placed above the cell.

Hence with the default settings it is sufficient to take into account only CellMargins, CellFrame and CellFrameMargins. Here is how one can find their portion inside of PageWidth:

margins = Total[Replace[
   Switch[CurrentValue[{CellFrame, 1}],
    True | {True, True}, {CurrentValue[{CellMargins, 1}], CurrentValue[{CellFrameMargins, 1}]},
    _?NumericQ | {_?NumericQ, _?NumericQ}, {CurrentValue[{CellMargins, 1}], CurrentValue[{CellFrameMargins, 1}]*Sign[Abs[CurrentValue[{CellFrame, 1}]]], CurrentValue[{CellFrame, 1}]},
    _, {CurrentValue[{CellMargins, 1}]}], {x_?NumericQ :> 2 x, l_List :> Total[l]}, {1}]]
76

(the above implementation doesn't handle correctly mixed specifications for CellFrame; complete implementation can be found in this answer.)

Knowing margins, we can restrict cell contents to be 400 pts wide:

SetOptions[EvaluationNotebook[], PageWidth -> 400 + margins]

And here is a way to make this option Dynamic (the implementation is very basic: it assumes that CellFrame may be only either True or False):

SetOptions[EvaluationNotebook[], PageWidth -> Dynamic[400 +
  Total[Replace[
    If[TrueQ@CurrentValue[EvaluationNotebook[], {StyleDefinitions, "Input", CellFrame}],
     {CurrentValue[EvaluationNotebook[], {StyleDefinitions, "Input", CellFrameMargins}],
      CurrentValue[EvaluationNotebook[], {StyleDefinitions, "Input", CellMargins}]},
     {CurrentValue[EvaluationNotebook[], {StyleDefinitions, "Input", CellMargins}]}], 
     {x_?NumberQ :> 2 x, l_List :> Total[First[l]]}, {1}]]]]

PageWidth allows to specify the maximum width in printer's points (what for the purposes of on-screen display we may read as pixels). If you use a mono-spaced font like Courier, it shouldn't be too difficult to establish the correspondence between the number of characters and the width of the line.

Here is a quick check up for all printable ASCII and Greek characters:

With[{chrs = 
   Join[CharacterRange[" ", "~"], 
    CharacterRange["\[CapitalAlpha]", "\[Omega]"]]},
 Table[Rasterize[StringJoin@Take[chrs, n], "RasterSize"][[1]]/n // N,
  {n, 1, Length[chrs]}]]

{7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.02273,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.01818,7.,7.,7.,7.,7.,7.,7.,7.,7.01563,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.01282,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.,7.00709,7.,7.,7.,7.,7.00685,7.,7.,7.,7.,7.,7.}

We see that for Courier (my default font) with default FontSize -> 12 the width of a character is equal to 7 pixels. Small inconsistency comes from the fact that Rasterize[string, "RasterSize"] isn't precise for strings.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.