Function Repository Resource:

SaveReadableNotebook

Source Notebook

Save a notebook to a file that is formatted to maximize readability when viewing changes in version control systems

Contributed by: Richard Hennigan (Wolfram Research)

ResourceFunction["SaveReadableNotebook"][notebook,"file"]

saves notebook to "file" as a Notebook expression formatted for readability.

Details and Options

In ResourceFunction["SaveReadableNotebook"][notebook,], the value for notebook can be any of the following:
Notebook[]a notebook expression
NotebookObject[]a currently open notebook
"path"a pathname of a saved notebook
ResourceFunction["SaveReadableNotebook"] accepts the same options as ReadableForm with the the following additions:
"ExcludedCellOptions"{CellChangeTimes,ExpressionUUID}cell options that should be discarded from the saved notebook
"ExcludedNotebookOptions"{WindowSize,WindowMargins}notebook options that should be discarded

Examples

Basic Examples (3) 

Save a NotebookObject to a human-readable file:

In[1]:=
nb = CreateDocument[{ TextCell["Test notebook", "Title"], TextCell["This is a test", "Text"], ExpressionCell[Defer[1 + 1], "Input"], ExpressionCell[2, "Output"] }]
Out[1]=
In[2]:=
ResourceFunction["SaveReadableNotebook"][nb, FileNameJoin[{$TemporaryDirectory, "readable.nb"}]]
Out[2]=
In[3]:=
FilePrint[%]

Save a Notebook expression:

In[4]:=
ResourceFunction["SaveReadableNotebook"][ Notebook[{Cell["Hello world", "Text"]}], FileNameJoin[{$TemporaryDirectory, "readable.nb"}] ]
Out[4]=
In[5]:=
FilePrint[%]

Save a copy of a notebook file that already exists:

In[6]:=
ResourceFunction["SaveReadableNotebook"][ FindFile["ExampleData/document.nb"], FileNameJoin[{$TemporaryDirectory, "readable.nb"}] ]
Out[6]=
In[7]:=
FilePrint[%, 20]

Options (6) 

ExcludedCellOptions (3) 

By default, some cell options are automatically stripped:

In[8]:=
ResourceFunction["SaveReadableNotebook"][ Notebook[{Cell["Hello world", "Text", ExpressionUUID -> CreateUUID[]]}], FileNameJoin[{$TemporaryDirectory, "readable.nb"}] ] // FilePrint

Preserve all cell options:

In[9]:=
ResourceFunction["SaveReadableNotebook"][ Notebook[{Cell["Hello world", "Text", ExpressionUUID -> CreateUUID[]]}], FileNameJoin[{$TemporaryDirectory, "readable.nb"}], "ExcludedCellOptions" -> {} ] // FilePrint

Ignore specific options:

In[10]:=
ResourceFunction["SaveReadableNotebook"][ Notebook[{Cell["Hello world", "Text", FontColor -> Red, FontSize -> 14]}], FileNameJoin[{$TemporaryDirectory, "readable.nb"}], "ExcludedCellOptions" -> {FontColor} ] // FilePrint

ExcludedNotebookOptions (3) 

By default, some notebook options are automatically stripped:

In[11]:=
ResourceFunction["SaveReadableNotebook"][ Notebook[{Cell["Hello world", "Text"]}, WindowSize -> {1000, 1000}], FileNameJoin[{$TemporaryDirectory, "readable.nb"}] ] // FilePrint

Preserve all notebook options:

In[12]:=
ResourceFunction["SaveReadableNotebook"][ Notebook[{Cell["Hello world", "Text"]}, WindowSize -> {1000, 1000}], FileNameJoin[{$TemporaryDirectory, "readable.nb"}], "ExcludedNotebookOptions" -> {} ] // FilePrint

Ignore specific options:

In[13]:=
ResourceFunction["SaveReadableNotebook"][ Notebook[{Cell["Hello world", "Text"]}, Background -> Red], FileNameJoin[{$TemporaryDirectory, "readable.nb"}], "ExcludedNotebookOptions" -> {Background} ] // FilePrint

Applications (5) 

SaveReadableNotebook can be used to create notebook files that are well suited for version control systems that look at changes to files on a line-by-line basis.

Here’s a test notebook:

In[14]:=
nb = NotebookPut@Notebook[{ Cell["Test notebook", "Title"], Cell["This is a test.", "Text"], Cell[BoxData[RowBox[{"1", "+", "1"}]], "Input"], Cell[BoxData["2"], "Output"] }]; NotebookSave[nb, FileNameJoin[{$TemporaryDirectory, "original.nb"}]];

Now make changes to the notebook, then save to a new file:

In[15]:=
NotebookSave[nb, FileNameJoin[{$TemporaryDirectory, "changed.nb"}]];

It can be difficult to visualize what actually changed:

In[16]:=
fileDiff[file1_, file2_, max_ : Infinity] := Column@Take[ Flatten@Replace[ SequenceAlignment[Import[file1, "Lines"], Import[file2, "Lines"]], {{a___String}, {b___String}} :> Grid[{ {Item[StringRiffle[{a}, "\n"], Background -> LightRed]}, {Item[StringRiffle[{b}, "\n"], Background -> LightGreen]} }], {1} ], UpTo[max] ];
In[17]:=
fileDiff[ FileNameJoin[{$TemporaryDirectory, "original.nb"}], FileNameJoin[{$TemporaryDirectory, "changed.nb"}] ]
Out[17]=

Create a formatted version of each notebook and view changes for those files instead:

In[18]:=
ResourceFunction["SaveReadableNotebook"][ FileNameJoin[{$TemporaryDirectory, "original.nb"}], FileNameJoin[{$TemporaryDirectory, "original_readable.nb"}] ]; ResourceFunction["SaveReadableNotebook"][ FileNameJoin[{$TemporaryDirectory, "changed.nb"}], FileNameJoin[{$TemporaryDirectory, "changed_readable.nb"}] ]; fileDiff[ FileNameJoin[{$TemporaryDirectory, "original_readable.nb"}], FileNameJoin[{$TemporaryDirectory, "changed_readable.nb"}] ]
Out[20]=

The formatted notebook files still open normally:

In[21]:=
NotebookOpen[ FileNameJoin[{$TemporaryDirectory, "changed_readable.nb"}]]
Out[21]=

Requirements

Wolfram Language 11.3 (March 2018) or above

Version History

  • 1.1.1 – 17 June 2022
  • 1.1.0 – 06 May 2022
  • 1.0.0 – 03 December 2018

Related Resources

License Information