7
$\begingroup$

Bug introduced in 8 or earlier and persisting through 13.1.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.)

enter image description here

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.

$\endgroup$
3
  • 1
    $\begingroup$ maybe SelectionMove[EvaluationCell[], After, GeneratedCell]? $\endgroup$
    – kglr
    Commented Dec 30, 2019 at 12:14
  • $\begingroup$ @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. $\endgroup$
    – Szabolcs
    Commented Dec 30, 2019 at 12:41
  • $\begingroup$ Szabolcs, posted the comment as an answer. $\endgroup$
    – kglr
    Commented Dec 30, 2019 at 12:59

3 Answers 3

5
$\begingroup$

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 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:

$\endgroup$
5
$\begingroup$
button = Button["Move", 
   SelectionMove[EvaluationCell[], After, GeneratedCell]];

Print["one"]
Print[button]
Print["two"]
Print["three"]
Print["four"]

enter image description here

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

enter image description here

$\endgroup$
2
  • $\begingroup$ 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? $\endgroup$ Commented Dec 30, 2019 at 14:18
  • 1
    $\begingroup$ @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. $\endgroup$
    – kglr
    Commented Dec 30, 2019 at 14:26
3
$\begingroup$

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
]
$\endgroup$

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.