The author of this question is interested in personally handling the code indentation and having the package editor, built-in in Mathematica 2012, preserve the manually chosen indentation level from line to line.

Instead, I found myself comfortable with the Automatic AutoIndent feature of normal notebook editor; it helps me understand and check the syntax while I'm coding.

If possible, I wish for the standard Mathematica 10 Package (.wl) editor to use this feature too.

I tried to apply the idea of the previous question and other ideas found elsewhere without success.

One problem is that the automatic indentation is lost when saving and reopening the .wl file, even if I apply again the proper style definition.

It is possible to do that?

  • $\begingroup$ I too would like to have this issue resolved when copying & pasting cells from a notebook into a package as well as when developing a package. Any developments for this? $\endgroup$
    – Edmund
    Jun 21, 2016 at 16:21

2 Answers 2


I recently found myself wanting a similar thing, that is, for the saved .wl to be formatted with the autoindentation and autospacing of the frontend's editor.

The frontend will apply autoindentation for Input style cells in the Package stylesheet, so I first change the cell style from the default Code to Input (+initialization cell).

I found I can then capture the frontend's formatting by toggling the cell style to CodeText and back to Input. This inserts explicit spaces for autoindentation and autospacing in the cell, and upon saving the .wl file will be formatted similar to what you see on screen in the package editor.

Programmatically, this can be done with

SaveFormattedNotebook[nb_NotebookObject] := (
    SelectionMove[#, All, Cell];
    FrontEndTokenExecute[nb, "Style", "CodeText"];
    FrontEndTokenExecute[nb, "Style", "Input"];
    ) &, Cells[nb, CellStyle -> {"Input"}]];

However, this'll leave the in-editor package with a bunch of redundant spaces, which should be removed, being careful not to delete spaces in comment blocks (* *) or strings ""

IsCommentRowBoxQ[RowBox[{box_, ___}]] := TrueQ[box == "(*"];
IsCommentRowBoxQ[___] := False

IsStringLiteralBoxQ[s_String] := 
 TrueQ[StringLength[s] > 2 && First@Characters[s] === "\""];
IsStringLiteralBoxQ[___] := False

CellApplyAutoIndent[cell_Cell] := 
 With[{indentingNewline = FromCharacterCode[FromDigits["F3A3", 16]]},
  Map[# /. "\n" -> indentingNewline &, cell, {-1}]]

CellRemoveExpressionWhitespace[c_?IsCommentRowBoxQ] := c;
CellRemoveExpressionWhitespace[s_?IsStringLiteralBoxQ] := s;
CellRemoveExpressionWhitespace[RowBox[boxes_]] :=
 RowBox[Map[CellRemoveExpressionWhitespace, boxes]];
CellRemoveExpressionWhitespace[s_String] :=
 StringDelete[s, " "];
  Cell[BoxData[boxes__], cellStyle_String, cellOptions___]] :=
 Cell[BoxData[Map[CellRemoveExpressionWhitespace, boxes]], cellStyle, 
CellRemoveExpressionWhitespace[x___] := x

FormatNotebook[nb_NotebookObject] :=
        NotebookRead[#]] &, Cells[nb, CellStyle -> {"Input"}]]

In addition to removing redundant whitespace, this also replaces \n line endings with \[IndentingNewLine]. This is necessary when opening a previously saved .wl file in the editor, since this will have \n line endings which means there is no autoformatting applied.


On my system (10.3.0, Windows) the indentation of a copied notebook expression is preserved in the package editor (also after closing and reopening the file) if the expression is copied from the notebook via the mouse context menu Copy As > Input Text.


Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.