You can make use of the notebook options NotebookEventActions
and NotebookDynamicExpression
to do this. The idea is to store the ExpressionUUID
of the selected cell into the notebook tagging rules option when the notebook is closed. If the cursor is between cells, then use either the next cell if it exists, or the previous cell otherwise. Then, when the notebook is opened, move the cursor to the cell with the stored ExpressionUUID
. One downside is that since this depends on NotebookDynamicExpression
, you will get the Enable Dynamics
popup.
At any rate, here is a NotebookEventActions
option that stores the ExpressionUUID
:
NotebookEventActions -> {
"WindowClose" :> With[{nb = EvaluationNotebook[]},
CurrentValue[nb, {TaggingRules, "LastCell"}] = CurrentValue[
Replace[SelectedCells[nb],
{} :> (
SelectionMove[nb, Next, Cell];
Replace[
SelectedCells[nb],
{} :> (
SelectionMove[nb, Previous, Cell];
SelectedCells[nb]
)
]
)
],
ExpressionUUID
]
]
}
And, here is a NotebookDynamicExpression
option that moves the cursor to the stored ExpressionUUID
:
NotebookDynamicExpression :> With[
{uu = CurrentValue[EvaluationNotebook[], {TaggingRules, "LastCell"}]},
Pause[.1];
SelectionMove[
First @ Cells[ExpressionUUID -> uu],
All,
CellContents
]
]
I included a Pause[.1]
wait. Without this pause, I think the SelectionMove
request happens before the front end is ready.
You will also note that I always select the contents of the desired cell. With more work, it is possible to record the position of the cursor in more detail, and also to restore the cursor to its original state, even if that original state were between cells, in the middle of a cell etc.
For visualization purposes, I create a notebook below with the needed options, and with some preexisting cells. I executed the following code, and saved the resulting notebook as temp.nb
:
CreateDocument[
{
ExpressionCell[Defer@Defer[Dynamic][CurrentValue[Cells[],ExpressionUUID]],"Input"],
ExpressionCell[Dynamic[CurrentValue[Cells[],ExpressionUUID]],"Output"],
ExpressionCell[Defer[1+1],"Input"],
ExpressionCell[1+1,"Output"],
ExpressionCell[Defer[AbsoluteCurrentValue[WindowTitle]],"Input"],
ExpressionCell[Dynamic@AbsoluteCurrentValue[WindowTitle],"Output"]
},
WindowMargins->{{0,Automatic},{Automatic,0}},
WindowSize->{500,500},
NotebookEventActions -> {
"WindowClose" :> With[{nb = EvaluationNotebook[]},
CurrentValue[nb, {TaggingRules, "LastCell"}] = CurrentValue[
Replace[SelectedCells[nb],
{} :> (
SelectionMove[nb, Next, Cell];
Replace[
SelectedCells[nb],
{} :> (
SelectionMove[nb, Previous, Cell];
SelectedCells[nb]
)
]
)
],
ExpressionUUID
]
]
},
NotebookDynamicExpression :> With[
{uu = CurrentValue[EvaluationNotebook[], {TaggingRules, "LastCell"}]},
Pause[.1];
SelectionMove[
First @ Cells[ExpressionUUID -> uu],
All,
CellContents
]
]
];
An animation of saving and opening the above notebook after moving the cursor follows:
