Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'd like to create a keyboard shortcut that will allow me to select all of the cells from the current cell until the end of the notebook, similar to how ShiftCtrlEnd functions when editing text in most Windows applications.

By editing KeyEventTranslations.tr, I've already created a shortcut using ShiftCtrlA that allows me to select the current cell (rather then pressing Ctrl. repeatedly). I'd like to then use another shortcut that would allow me to avoid having to hold down Shift and press over and over until I reach the bottom.

Any ideas?

share|improve this question
    
I seem to recall that a simpler question, selecting multiple cells, had no forthcoming answer. I hope this proves possible but I'm doubtful. EDIT: docs for SelectionMove confirm: "SelectionMove can only select multiple cells as part of a CellGroup unit specification." –  Mr.Wizard Oct 30 '12 at 21:40
    
Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Read the FAQs! 3) When you see good Q&A, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. ALSO, remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign` –  chris Oct 31 '12 at 10:15

3 Answers 3

up vote 5 down vote accepted

Building on Albert's answer I added code such that Ctrl Shift End will select all cells downwards. Just execute this code in a notebook and restart Mathematica:

   mymenuitems="
         (* Select all cells downwards *)
         Item[KeyEvent[\"End\", Modifiers -> {Control, Shift}], 
         KernelExecute[
          Module[{ enb = EvaluationNotebook[],
                   tag = StringJoin[\"tmp\", ToString[Round[AbsoluteTime[]/$TimeUnit]]],editable 
                   },
                editable = ReplaceAll[Editable, Options[enb, Editable]];
                SetOptions[enb, Editable -> False];
                SelectionMove[enb, Next, Cell, AutoScroll -> False];
                MathLink`CallFrontEnd[FrontEnd`SelectionAddCellTags[enb, {tag}]];
                SelectionMove[enb, After, Notebook, AutoScroll -> False];
                SelectionMove[enb, Previous, Cell, AutoScroll -> False];
                While[FreeQ[ReplaceAll[CellTags,Options[NotebookSelection[]]], tag],
                      MathLink`CallFrontEnd[FrontEnd`SelectionAddCellTags[enb, {tag}]];
                      SelectionMove[enb, Previous, Cell, AutoScroll -> False]
                ];
                NotebookFind[enb, tag, All, CellTags, AutoScroll -> False];
                MathLink`CallFrontEnd[FrontEnd`SelectionRemoveCellTags[enb, {tag}]];
                SetOptions[enb, Editable -> editable]
            ]
            ], MenuEvaluator -> Automatic ]
            ";
    Quiet@CreateDirectory@FileNameJoin[{$UserBaseDirectory,"SystemFiles","FrontEnd","TextResources",$OperatingSystem}];
    mykeyeventtrans=FileNameJoin[{$UserBaseDirectory,"SystemFiles","FrontEnd","TextResources",$OperatingSystem,"KeyEventTranslations.tr"}];
    If[FileExistsQ[mykeyeventtrans],DeleteFile@mykeyeventtrans];
    CopyFile[FileNameJoin[{$InstallationDirectory,"SystemFiles","FrontEnd","TextResources",$OperatingSystem,"KeyEventTranslations.tr"}],mykeyeventtrans];
keytext=Import[mykeyeventtrans,"Text"];
mykeytext=StringReplace[keytext,"EventTranslations[{":>StringJoin["EventTranslations[{\n(* User defined *)\n",mymenuitems,",\n"]];
Export[mykeyeventtrans,mykeytext,"Text"];

I only tested this on Windows. No idea if it works on MacOSX and Linux.

share|improve this answer

I also don't know a straightforward way to do what you want, so Mr.Wizard could well be right. But there are workarounds as e.g. the following which is "abusing" CellTags. It is however somewhat hacky and not very fast and reliable and I'm not sure whether it is good enough for your every day use:

Module[{
  enb = EvaluationNotebook[],
  tag = StringJoin[
    RandomChoice[
     Join[CharacterRange["A", "Z"], CharacterRange["a", "z"], 
      CharacterRange["0", "9"]],
     30]
    ],
    editable
  },
 editable = Editable /. Options[enb,Editable];
 SetOptions[enb, Editable -> False];
 SelectionMove[enb, Next, Cell, AutoScroll -> False];
 MathLink`CallFrontEnd[FrontEnd`SelectionAddCellTags[enb, {tag}]];
 SelectionMove[enb, After, Notebook, AutoScroll -> False];
 SelectionMove[enb, Previous, Cell, AutoScroll -> False];
 While[FreeQ[CellTags /. Options[NotebookSelection[]], tag],
  MathLink`CallFrontEnd[FrontEnd`SelectionAddCellTags[enb, {tag}]];
  SelectionMove[enb, Previous, Cell, AutoScroll -> False];
  ];
 NotebookFind[enb, tag, All, CellTags, AutoScroll -> False];
 MathLink`CallFrontEnd[FrontEnd`SelectionRemoveCellTags[enb, {tag}]];
 SetOptions[EvaluationNotebook[], Editable -> editable]
 ]

It should be relatively clear what this does, nevertheless I think some remarks might be helpful:

  • I'm using a random tag to mark the cells to be selected (a common strategy to create global unique identifiers GUIDs), you could probably think of something smarter and e.g. check whether the tag you want to use is already present in the notebook to be on the really save side. I think it would, for almost all use cases, also be good enough to work with a constant unique identifier, though...
  • to temporarily add tags without destroying already existing ones, I'm using the undocumented frontend functionality SelectionAddCellTags and SelectionRemoveCellTags which I know from the excellent talk "The joy of Tagging" given by David Reiss at a Wolfram User Conference some years ago. You should be able to find the corresponding notebook in the web which is a good read if you try to do any kind of advanced notebook manipulating...
  • except for the random tag generation it should be possible to do this completely in the frontend which might be a good idea if you want it to be executed from a keyboard shortcut or button.
  • as suggested by Rolf Mertig I did set the notebook to not be editable while the code is running so that it should be relatively safe against user input.
  • there might well be other features, especially undocumented ones, which might let you do the same thing more reliable and faster, so don't accept this answer too early...
share|improve this answer
1  
it is easy to secure against user input. Just add SetOptions[EvaluationNotebook[], Editable -> False]; at the beginning of the Module and SetOptions[EvaluationNotebook[], Editable -> True] at the end –  Rolf Mertig Oct 31 '12 at 10:32
    
@RolfMertig: good point, I have incorporated it ... –  Albert Retey Oct 31 '12 at 11:19
    
I changed the tag to ToString @ Round @ AbsoluteTime[] . Or is there any good argument not to do so? –  Rolf Mertig Oct 31 '12 at 15:06
    
Why is SetOptions[EvaluationNotebook[], Editable -> False] the last thing to be evaluated? –  acl Oct 31 '12 at 15:47
    
@acl: because I didn't test it :-). Of course it should have been set to True. Actually it would be even better to set it to the value it had before we changed it, which I have now inserted... –  Albert Retey Oct 31 '12 at 16:15

In case this is helpful to anyone stumbling upon this thread this as I did, here is simpler code to select all cells from the end of a notebook to the current evaluation cell.

endAtID = First @ EvaluationCell[];
SelectionMove[EvaluationNotebook[], After, Notebook];
SelectionMove[EvaluationNotebook[], Previous, Cell];
While[
    SelectedCells[][[1, 1]] =!= endAtID,
    FrontEndTokenExecute[EvaluationNotebook[], "SelectPreviousLine"];
] 

This can be modified to start from the cell containing the current insertion point, here is a button which will do this.

Button["press to select all cells from insertion point to end of notebook",
    SelectionMove[InputNotebook[], All, Cell];
    If[
        SelectedCells[InputNotebook[]] === {}, 
        SelectionMove[InputNotebook[], Next, Cell]
    ];
    endAtID = First @ SelectedCells[InputNotebook[]][[1]];
    SelectionMove[InputNotebook[], After, Notebook];
    SelectionMove[InputNotebook[], Previous, Cell];
    While[
        SelectedCells[InputNotebook[]][[1, 1]] =!= endAtID, 
        FrontEndTokenExecute[InputNotebook[], "SelectPreviousLine"];
    ]
]

The code inside the button above should work fine when triggered from a keyboard shortcut or palette button or wherever you want. To make it delete the selected cells, simply add

NotebookDelete[InputNotebook[]] 

to the end of the code inside the button.

AMENDMENTS: To make the selection go from the insertion point to the end of the notebook, you can modify the code as such

Button["press to select all cells from insertion point to end of notebook",
    SelectionMove[InputNotebook[], After, Notebook];
    SelectionMove[InputNotebook[], Previous, Cell];
    endAtID = First@SelectedCells[InputNotebook[]][[1]];
    SelectionMove[EvaluationCell[], All, Cell];
    While[
        SelectedCells[InputNotebook[]][[-1, 1]] =!= endAtID, 
        FrontEndTokenExecute[InputNotebook[], "SelectNextLine"];
    ]
]

I like Albert Riley's suggestion in the comments to use FixedPoint so much I thought we should add it here

SelectionMove[InputNotebook[], All, Cell];
FixedPoint[
    (
        FrontEndTokenExecute[InputNotebook[], "SelectNextLine"];
        SelectedCells[InputNotebook[]]
    ) &,
    {}
]
share|improve this answer
    
very good find, turns out there is also a FrontEndToken "SelectNextLine" which would allow to select the rest of the notebook from top to bottom instead from bottom to top. Both seem to be quite useful, would you mind to share where you did find them? –  Albert Retey Aug 27 at 15:38
    
Both would work indeed, you could move the selection to the end of the notebook and then select the previous cell and use a similar While loop. I found this front end token at the very end of the documentation for SelectionMove inside the "possible issues" subsection. –  Kyle Keane Aug 27 at 15:46
    
Thanks for the information about the source, not exacty where one would actively search, but at least it's there:-). But isn't what you describe in the comment what already is in your answer and the "SelectNextLine" would allow to select the current cell and then extend to the end of the notebook? Something like: SelectionMove[InputNotebook[], All, Cell]; FixedPoint[(FrontEndTokenExecute[InputNotebook[], "SelectNextLine"]; SelectedCells[InputNotebook[]]) &,{}] –  Albert Retey Aug 27 at 21:59
    
Yes my comment is the same concept, but it did need some refactoring. I added the code to the answer along with highlighting your intelligent use of FixedPoint –  Kyle Keane Aug 27 at 23:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.