# Move input cursor to after cell group

Bug introduced in 8 or earlier and persisting through 12.0

I am looking for a way to move the input cursor to after the current cell group. The following example illustrates the situation I am dealing with:

button = Button["Move", SelectionMove[EvaluationCell[], After, CellGroup]];

Print["one"]
Print[button]
Print["two"]


Evaluate the above then press the button.

What I need is the input cursor to be moved to the location immediately after the output cell group (i.e. after two). Instead, it is moved to after the cell containing the button, as if I had specified Cell instead of CellGroup in SelectionMove. (But if I use All as the 2nd argument of SelectionMove instead of After, then the cell group is selected correctly.)

I realize that there are some difficulties with specifying where to move the selection exactly because there are multiple levels of nested cell groups. In this case, all the printed cells are grouped into an "output group", which is then grouped together with the input cell. I am looking for a solution that works with the simple example I showed here, both when there are multiple outputs (several printed lines) and when there is only one.

Note: This is a follow-up of this question, and would be used to specify where the new cell would be inserted.

• maybe SelectionMove[EvaluationCell[], After, GeneratedCell]? – kglr Dec 30 '19 at 12:14
• @kglr While doesn't literally answer what I asked, it is pretty close to working for my actual use case. It would be valuable to have it as an answer. – Szabolcs Dec 30 '19 at 12:41
• Szabolcs, posted the comment as an answer. – kglr Dec 30 '19 at 12:59

Instead, it is moved to after the cell containing the button, as if I had specified Cell instead of CellGroup in SelectionMove.

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 the Option 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 FrontEndNotebookSuspendScreenUpdates[] and FrontEndNotebookResumeScreenUpdates[]:

FrontEndExecute@FrontEndNotebookSuspendScreenUpdates[EvaluationNotebook[]];
SelectionMove[EvaluationCell[], All, CellGroup, AutoScroll -> False];
If[Length[SelectedCells[]] > 1,
SelectionMove[EvaluationCell[], After, CellGroup, AutoScroll -> False],
SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False]];


I believe that this solution is reliable despite using the undocumented functionality.

I tested these methods for a very sensitive use case:

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"]


• The discovery with the fourth argument of SelectionMove is amaizing (+1)! I'm just not completely sure that this behavior is expected and doesn't reflect another bug. What do you think? – Alexey Popkov Dec 30 '19 at 14:18
• @Alexey, hard to tell whether this is expected behavior. I would have expected the number n should work to move the cursor n cellgroups. Also, replacing CellGroup with Cell moves the cursor after the button regardless of the fourth argument. – kglr Dec 30 '19 at 14:26

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
]