Move input cursor to after cell group
button = Button["Move",
SelectionMove[EvaluationCell[], After, GeneratedCell]];
Print["one"]
Print[button]
Print["two"]
Print["three"]
Print["four"]
Alternatively, using a number greater than 1 in the fourth argument of SelectionMove
gives the same behavior:
button = Button["Move",
SelectionMove[EvaluationCell[], After, CellGroup, 2]];
Print["one"]
Print[button]
Print["two"]
Print["three"]
Print["four"]
Instead, it is moved to after the cell containing the button, as if I had specified
Cell
instead ofCellGroup
inSelectionMove
.
On October, I reported this issue to the Wolfram support: [CASE:4323226]. They confirmed the bug and suggested a workaround. Here is the response:
It does appear that
SelectionMove
is not behaving properly. <...>In the meantime, here is one option for making the insertion point move to the next
CellGroup
. Please use theOption
GeneratedCell
for this. A code snippet is given below:"something that gives the first output and puts the EvaluationCell[] in a CellGroup" SelectionMove[EvaluationCell[], After, GeneratedCell, AutoScroll -> False]
But I immediately discovered another bug with this workaround: if evaluation cell has no GeneratedCell
immediately after it, the visual insertion point in the Notebook just disappears, and SelectionMove
doesn't return $Failed
as it should according to the Documentation. They confirmed this bug too ([CASE:4326002]), but hadn't suggested any workaround.
As a workaround I would suggest to check the type of the next cell explicitly, using NextCell[]
:
If[TrueQ@CurrentValue[NextCell[], GeneratedCell],
SelectionMove[EvaluationCell[], After, GeneratedCell, AutoScroll -> False],
SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False]]
But I'm not completely sure that the workaround suggested by the support is valid in the long-term: I believe that it may reflect another bug in SelectionMove
, and hence can change in the future. So I wouldn't use this workaround, and would use the well-documented and working functionality:
SelectionMove[EvaluationCell[], All, CellGroup, AutoScroll -> False];
If[Length[SelectedCells[]] > 1,
SelectionMove[EvaluationCell[], After, CellGroup, AutoScroll -> False],
SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False]];
The problem with this solution is that the user (with a very low probability) can click in the Notebook and change the selection created by the first row of the code. We can temporarily disable this using undocumented functions FrontEnd`NotebookSuspendScreenUpdates[]
and FrontEnd`NotebookResumeScreenUpdates[]
:
FrontEndExecute@FrontEnd`NotebookSuspendScreenUpdates[EvaluationNotebook[]];
SelectionMove[EvaluationCell[], All, CellGroup, AutoScroll -> False];
If[Length[SelectedCells[]] > 1,
SelectionMove[EvaluationCell[], After, CellGroup, AutoScroll -> False],
SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False]];
FrontEndExecute@FrontEnd`NotebookResumeScreenUpdates[EvaluationNotebook[]]
I believe that this solution is reliable despite using the undocumented functionality.
I tested these methods for a very sensitive use case:
- Delete pre-existing output under EvaluationCell[] from CellProlog
Unfortunately cell groups api is very limited so can't say it is robust but it should work assuming the cell group structure you've described is in place.
Button["Move",
FrontEndExecute[{
SelectionMove[EvaluationCell[], All, Cell];
SelectionMove[EvaluationNotebook[], All, CellGroup];
SelectionMove[EvaluationNotebook[], After, CellGroup]
}],
Evaluator -> None
]