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 want to use this to add a keyboard shortcut to an undo function I wrote. The basic problem is the following:

I have a command, let's say x=1, and I want to run the command with a keyboard shortcut. Is there a way to do it?

Editing the KeyEventTranslation.tr file is what I tried.

Adding

Item[KeyEvent["z",Modifiers->{Command}],Evaluate[x=1]],

does not work.

Item[
 KeyEvent["z", Modifiers -> {Command}], 
  FrontEndExecute[{FrontEnd`NotebookWrite[FrontEnd`InputNotebook[],"x=1"]}]]

adds the text x=1 where the cursor is, but it still needs to be evaluated and I need to be at the right place with the cursor.

Are there other ways?

This might be related, but I couldn't get anything out of it so far.

share|improve this question
add comment

1 Answer

up vote 16 down vote accepted

Here are four approaches to setting up keyboard shortcuts. The last is the best!

AddMenuCommands

First examples using notebook manipulation, (as you tried):

This example adds a command to the Insert menu, with a key combination Control+U (normally the underline command). This addition just lasts for the session, but could be added to an init file.

FrontEndExecute[
 FrontEnd`AddMenuCommands["DuplicatePreviousOutput",
  {Delimiter, MenuItem["Evaluate x = 1",
    FrontEnd`KernelExecute[
     nb = SelectedNotebook[];
     SelectionMove[nb, After, Cell]; 
     NotebookWrite[nb, Cell[BoxData[RowBox[{"x", "=", "1"}]], "Input"]];
     SelectionMove[nb, Previous, Cell];
     SelectionEvaluate[nb]],
    MenuKey["u", Modifiers -> {"Control"}],
    System`MenuEvaluator -> Automatic]}]]

Note, you can find the box format like so:

ToBoxes[Hold[x = 1]]

Out = RowBox[{"Hold", "[", RowBox[{"x", "=", "1"}], "]"}]

This could also be done invisibly like this:

FrontEndExecute[
 FrontEnd`AddMenuCommands["DuplicatePreviousOutput",
  {Delimiter, MenuItem["Evaluate x = 1",
    FrontEnd`KernelExecute[
     nb = CreateDocument[Null, Visible -> False, WindowSelected -> True];
     NotebookWrite[nb, Cell[BoxData[RowBox[{"x", "=", "1"}]], "Input"]];
     SelectionMove[nb, Previous, Cell];
     SelectionEvaluate[nb];
     NotebookClose[nb]],
    MenuKey["u", Modifiers -> {"Control"}],
    System`MenuEvaluator -> Automatic]}]]

A quicker version just uses ToExpression, (not Evaluate, as you first tried):

FrontEndExecute[
 FrontEnd`AddMenuCommands["DuplicatePreviousOutput",
  {Delimiter, MenuItem["Evaluate x = 1",
    FrontEnd`KernelExecute[ToExpression["x=1;"]],
    MenuKey["u", Modifiers -> {"Control"}],
    System`MenuEvaluator -> Automatic]}]]

KeyEventTranslations

The notebook manipulation can be implemented in KeyEventTranslations.tr like so:

Item[KeyEvent["u", Modifiers -> {Control}], FrontEndExecute[
  FrontEnd`SelectionMove[FrontEnd`InputNotebook[], After, Cell];
  FrontEnd`NotebookWrite[FrontEnd`InputNotebook[], 
    Cell[BoxData[RowBox[{"x", "=", "1"}]], "Input"]];
  FrontEnd`SelectionMove[FrontEnd`InputNotebook[], Previous, Cell];
  FrontEnd`SelectionEvaluate[FrontEnd`InputNotebook[]]]]

NotebookEventActions

Another approach for adding a keyboard shortcut is this:

function[] := x = 1

SetOptions[SelectedNotebook[],
 NotebookEventActions -> {"DownArrowKeyDown" :> function[]}]

Setting notebook event actions to command or control key combinations does not appear to be possible. A shifted key assignment can be made, e.g. Shift+O (just capital "o"):

NotebookEventActions -> {{"KeyDown", "O"} :> ...

You can replace SelectedNotebook[] with $FrontEnd (note 'Details') - that adds the assignment to your front end init file. (To undo, you would need to edit the init file to remove the event assignment.)

MenuSetup

Finally -- and this is probably the most obvious -- place x = 1; in a file called assign.m and call it from a menu item specified in MenuSetup.tr with:

Item["Evaluate x = 1",
 KernelExecute[Get["assign.m", Path -> "C:\\Users\\chrisd\\Documents"]]]],
 MenuKey["u", Modifiers->{"Control"}], MenuEvaluator->Automatic]

Alternatively, use ToExpression:

Item["Evaluate x = 1", KernelExecute[ToExpression["x=1;"]],
 MenuKey["u", Modifiers -> {"Control"}], MenuEvaluator -> Automatic]
share|improve this answer
    
Very nice. That definitely works. Perfect would be to not add any text to the notebook. I like that there is no need to edit any system files. –  jenson Dec 12 '12 at 12:40
    
@jenson_bo - I added a second AddMenuCommands variation which doesn't leave any text in the input notebook. –  Chris Degnen Dec 12 '12 at 13:43
    
Great answer, I tried the invisible option, it works, but since I am using the notebooks name in the assigned function creating a new document seems to be a problem. I will try the last option later. Thanks. Once the keyboard shortcuts work in a nice way, I think my layman's undo/version control is presentable - but of course can be improved even more. –  jenson Dec 12 '12 at 14:30
1  
@jenson_bo - In the first version, you could delete the created cell like so: NotebookWrite[nb, Cell[BoxData[RowBox[{RowBox[{"x", "=", "1"}], ";"}]], "Input"]]; SelectionMove[nb, Previous, Cell]; SelectionEvaluate[nb]; SelectionMove[nb, Previous, Cell]; NotebookDelete[nb] –  Chris Degnen Dec 12 '12 at 14:48
    
@ Chris Degnen - SelectionMove[nb, Previous, Cell]; NotebookDelete[nb] That does the trick I think. :) –  jenson Dec 12 '12 at 14:55
add comment

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.