Tuesday, May 08, 2007

Keybinding in DrScheme Explained

Keybinding 101 in DrScheme

Ever since I can remember during my days with DrScheme, it has always annoyed me that I couldn't comment out a block of code with an easy to use keyboard shortcut. The default short cut for the comment-out command is either `ESC;c:semicolon' or `m:c:semicolon'. Now see here we go, I have to immediately explain this little language for expressing keystrokes, or you won't get a thing out of what I'm trying to convey. The truth is that I only last week finally put all the pieces together to assign a set of easily accessible keys combinations to both the comment-out and the uncomment commands, which in scheme simply prepends a semicolon at the very first character of a line, and removes it respectively. These are great tools when you are hacking up a program and you run into a bug, but your not quite sure what section of code is responsible for the bug. You just comment out pieces of your source in a logical progression until you've isolated the little pest.

Let me say first how appreciative I am of the help I received on this topic, both from various posts on this topic at plt-scheme@list.cs.brown.edu, and specifically a grand gentlemen who is perpetually involved with helping people who submit posts or bug reports to PLT. His name is Robby Findler, and you'll never find a more helpful man to deal with on matters relating to PLT. And he is kind of heart, not known to me to punish you for posting a bug report that turns out to be your own typographical mistake. I can vouch for this personally. Actually, I could say the same things about nearly the entire PLT crew, but it was Robby who specifically helped me out with todays topic.

The first thing you should realize about assigning a new key binding to actuate a certain command is that there are several ways to go about it. But to make the task much simpler for typical kinds of keymapping, which is what the process is called in DrScheme, the PLT bunch have provided a way directly off the `Edit' menu, under the menu item `Keybindings' a sub-menu-item entitled `Add User-defined Keybindings...'. Sounds simple enough, and indeed a file open dialog box appears straight away ready to accept your User-defined Keybinding file. The catch is, it doesn't take you to a directory filled with example keybinding files that you could use as a template in making your own file. The truth is the description of the structure of this file is only been recently better documented in the manuals, and in my opinion, the documentation still leaves the uninitiated pretty much clueless on what sort of file they should be handing to DrScheme as a valid keybindings file. I intend to show you how that file should be written, and document where you can read more about the topic.

First off you'll want to read section 3.3.7 Defining Custom Shortcuts, in the PLT:DrScheme Programming Environment Manual. I've reproduce it here with permission, for your convenience, since it's such a short piece.


3.3.7 Defining Custom Shortcuts

The Add User-defined Keybindings... menu item in the Keybindings sub-menu of Edit selects a file containing Scheme definitions of keybindings. The file must contain a single module that uses a special keybindings language, (lib "keybinding-lang.ss" "framework"). For example, a file named mykeys.ss for keybindings might contain the following code:


(module mykeys (lib "keybinding-lang.ss" "framework") ...)

The keybindings language includes all of MzScheme, (lib "mred.ss" "mred"), (lib "class.ss"), and one addition, a keybinding form:


(keybinding keybinding-string-expr keybinding-proc-expr)

The keybinding-string-expr must produce a suitable first argument for map-function in keymap%, and the keybinding-proc-expr must produce a suitable second argument for add-function in keymap%.


Also the require statement


(require (lib "tool-lib.ss" "drscheme"))

adds all of the names defined in the tools manual to your keybindings module, in order to help define drscheme-specific keybindings.



Putting it all together it means our keybinding file should come out looking something like this, for a single instance of key remapping:


(module mykeys (lib "keybinding-lang.ss" "framework") (require (lib "tool-lib.ss" "drscheme")) (keybinding keybinding-string-expr keybinding-proc-expr))

Now all we have to do is come up with two expressions, the keybinding-string-expr and the keybinding-proc-expr. They've even provided hot links to the functions whose arguments these two expression become to help us out. These hot links are live in this post as well, so feel free to check out the documentation available for both functions.

In the case of the first keybinding-string-expr the documentation has become quite thorough. It describes how you build the string that defines the keystroke sequence that you wish to use to activate your function. I'll review this with you in just a moment. In the case of the second keybinding-proc-expr it is not clear at all what you should be using for a valid function name, nor where one would find them. As it was explained to me by Robby Findler, the scope of the available functions includes simply everything PLT has to offer, including functions that can be found in PlaneT, and even my own libraries. That's good to know, but I remain fuzzy on the precise protocol for calling functions from different sources. What I intend to do in this post is make available to you a method of determining the vast majority of editor functions available in standard DrScheme. If you have a desire to make a hot key for your favorite PlaneT package function I would refer you to the good people on the PLT mailing list, who should be able to come up with an answer for a specific question on mapping a specific function.

Now to get back to how you go about defining the keystrokes for your new keybinding-string-expr. The first thing to know is the terminating character, of a possibly chorded key combination, can have more than one keybinding. The rules for precedence over which keybinding actually gets invoked are pretty simple, but very specific. Generally speaking, the more modifier keys used in a key combination, the higher its precedence. In the event that two key combinations enumerate the same number of modifiers, the string that prohibits the use of the most modifier keys while typing the other required keys in the sequence, has the higher precedence. I'll have more to say about this later when we get to some specific examples.

The actual string that makes up the keybinding-string-expr is formated as a semicolon delimited sequence of state strings. Each of these state strings indicates the presence of a either a modifier key being pressed or not pressed, or a the state of a mouse button, a double or triple click, function keys, numeric keypad keys or a regular character key. Certain characters are special. The colon indicates that the previous character in the string is to be interpreted as a modifier key. And the semicolon delimits sequences of states, such that you can represent first one key being pressed and then subsequently another key being pressed. Since they are special, and since states like the status of a mouse button do not have standard character representations, PLT has come up with a long list of special names that you can use to represent these states. For a complete list see the documentation for the map-function. I'll just give you enough to get you started. The colon key is represented as the string "colon" and the semicolon character is represented by the string "semicolon", not surprisingly. Another special character is tilde `~' key. When it is prefixed to a modifier key, it reverses the meaning, such that it only matches states in which the modifier key is not pressed. Since the modifier keys are so commonly used, I've reproduced their representative strings below for you convenience.

The modifier identifiers are:
  • ``s:'' -- All platforms: Shift
  • ``c:'' -- All platforms: Control
  • ``a:'' -- Mac OS X: Option
  • ``m:'' -- Windows: Alt; X: Meta
  • ``d:'' -- Mac OS X: Command
  • ``?:'' -- All platforms: allow match to character produced by opposite use of Shift and/or AltGr/Option, when available; see get-other-shift-key-code in key-event%

By the way, that last modifier matching string "?:", produces two other precedence classes of state strings, both of which rank below everything else. The higher of the two precedence classes takes effect when you simply use the "?:" match sequence on either the Shift or the AltGr(Windows)/Option(Mac) keys, and the lowest takes effect when you use it on both. But remember, you'll likely be trying to achieve the highest precedence you can so that you'll be certain to override any other keybinding that may be in effect for your chosen hot key, so it's not likely that you'll be worrying about these types of match sequences very often.

I think about now is a good time to review some examples taken shamelessly from the manual.

Examples:

  • "space" -- matches whenever the space bar is pressed, regardless of the state of modifiers keys.
  • "~c:space" -- matches whenever the space bar is pressed and the Control key is not pressed.
  • "a" -- matches whenever ``a'' is typed, regardless of the state of modifiers keys (other than Shift).
  • ":a" -- matches only when ``a'' is typed with no modifier keys pressed.
  • "~c:a" -- matches whenever ``a'' is typed and neither the Shift key nor the Control key is pressed.
  • ":esc;:c:c" -- matches an Escape key press (no modifiers) followed by a Control-C press (no modifiers other than Control).
  • "?:d:+" -- matches when Command is pressed with the key that produces ``+'', even if producing ``+'' normally requires pressing Shift.

There are two examples here that I think are worthy of mention beyond what is explained in the manual. The first is the ":a" sequence. You'll notice it has a leading colon, but no preceding character for the colon to interpret as a modifier key. This has a very desirable effect, in that is it matches only if no modifier keys are pressed. You'll remember that the precedence goes up with the number of modifiers that cannot be pressed for a state string to match, all else being equal. Well this is the best way to insure that your hot key to whatever key you've chosen; lets make it a bit more realistic and map it to a function key like this ":f11", will have the highest precedence possible for an un-chorded press of F11. The state string ":f11" matches only if no modifier keys are pressed and the f11 function key is pressed by itself, and since it is preceded by a colon, it trumps any other keybinding to f11 without a modifier key, except for any other keybindings that are identical, in which case, unfortunately, the winner is selected arbitrarily. The other example worthy of further mention is the ":esc;:c:c" sequence. Note it to starts off with a colon as well, so the Esc key must be pressed by itself. Then there is that semicolon. This translates to, and now you release the previous state string, and press the sequence corresponding to the following state string. In this case the following sequence again starts off with a colon (you can tell somebody was after the highest possible precedence they could get), so the following `c:' represents the control key, which must be typed in the absence of any other modifiers due to the previous colon. Finally, we get to the actual character key, which is the letter `c'. To match this sequence you have to type the Esc key by itself, release it, and then type control-c, with no other modifier keys pressed. Not the most convenient shortcut, but it shows off the versatility of what you can do with the proper encoding.

I encourage you to read the entire section on the map-function. It is very well written, and it supplies you with the names for any possible key and/or mouse combination you could possibly want. With all that we've learned now, you can finally decode those annoying hot keys for commenting out code that I was complaining about at the outset of this post. They are `ESC;c:semicolon' and `m:c:semicolon' respectively. Well that first one sure looks familiar. It requires that you press the Esc key, with any set of modifiers you'd like to throw in, then release the Esc key, and finally press control-semicolon. Not what I'd call exactly convenient. Then it gets worse with the next sequence. At the time I first started using DrScheme I didn't own a *nix box, or a Mac. And the first of the two required modifier keys in this sequence is the meta key, which has no equivalent on an XP box. So even had I wanted to learn these unwieldy chorded keystrokes, I wasn't going to be able to use that hot key sequence at all. I know now that I could have used the Alt key for the meta key, but at the time I was clueless. Now I own a Mac Pro and DrScheme gives you the option of using your option key as the meta key. However, the option key is my gateway into quick access to a variety of special characters, that I would other wise have to pull up the special-character tool to insert into a document. No, what I wanted was a very quick key combination, so that I'd actually get some use out of these shortcuts.

The official document within the Help Desk where you can find the default global keybindings for an editor is keymap:setup-global in frameworks functions. However, this doesn't nearly cover all the keybindings you'll see when you look at your Active Keybindings. To get the entire list, minus the menu shortcuts, you have to employ the use of several functions, each of which adds its own particular set of bindings to the keymap. As far as I know, this information is not provided in any one location within a particular manual. So, here you get the product of my research into reconstructing the better part of the Active Keybindings in a default DrScheme system.

(let ([keymap (new keymap:aug-keymap%)]
[drscheme:keymap
      (drscheme:rep:get-drs-bindings-keymap)])
(scheme:setup-keymap keymap)
(keymap:setup-global keymap)
(keymap:setup-search keymap)
(keymap:setup-file keymap)
(keymap:set-chained-keymaps keymap
        (list drscheme:keymap))
(let* ([table (send keymap get-map-function-table)]
      [bindings (hash-table-map table list)]
      [sym-first-list
       (sort
        bindings
        (lambda (x y) (string<=? (cadr x) (cadr y))))])
; At this point sym-first-list is a list of pairs,
; where the car is the state string and the cadr
; is the function name (in most cases.)

There are in fact commands available for all the menu functions, but to get the correct function name to call to actuate them takes some direct help from someone in the PLT group to help you, or a lot of searching through source code. As far as I know, there is no place in the manuals that gives any more information than what I've provided you. And as you can see, it's scattered about in different function calls that simply take a lot of time to research. Now many of these functions are displayed in the Active Keybindings dialog box, however, there is no way to copy them off the dialog box, so that you can make your own list and design a strategy for your custom keymapping. Hopefully, the tables below will fill this gap, and you'll be able to get to the majority of the generic editor functions provided by a basic DrScheme editor frame in Scheme mode. One very hospitable thing the PLT crew have done with the global keybindings is make it quite simple for you to override them. If you go down the list, there is only one state string that begins with a colon, and that is for the mouse-popup-menu, bound to ":rightbuttonseq". That means, if you would rather use a keybinding for something else, or swap a couple around, you can easily do this by simply placing a colon at the beginning of your own custom keybinding, which will automatically give it higher precedence, as we discussed above.

Keymap - Welcome to DrScheme, version 369.100-svn5may2007 [3m].
"\u001f"undoback-to-prev-embedded
-editor
"m:c:left"
")"balance-parensback-to-prev-embedded
-editor
"ESC;c:left"
":rightbuttonseq"mouse-popup-menuback-to-prev-embedded
-editor
"a:c:left"
"ESC;""insert-""-pairbackward-character"c:b"
"ESC;("insert-()-pairbackward-character"left"
"ESC;0"command-repeat-0backward-kill-word"m:del"
"ESC;1"command-repeat-1backward-kill-word"ESC;del"
"ESC;2"command-repeat-2backward-select"s:c:b"
"ESC;3"command-repeat-3backward-select"s:left"
"ESC;4"command-repeat-4backward-select
-word
"m:s:b"
"ESC;5"command-repeat-5backward-select
-word
"ESC;s:b"
"ESC;6"command-repeat-6backward-select
-word
"a:s:left"
"ESC;7"command-repeat-7backward-select
-word
"c:s:left"
"ESC;8"command-repeat-8backward-sexp"ESC;left"
"ESC;9"command-repeat-9backward-sexp"m:c:b"
"ESC;<"beginning-of-filebackward-sexp"ESC;c:b"
"ESC;>"end-of-filebackward-word"m:b"
"ESC;["insert-[]-pairbackward-word"ESC;b"
"ESC;a:return"do-returnbackward-word"a:left"
"ESC;b"backward-wordbackward-word"c:left"
"ESC;c"capitalize-wordbalance-parens")"
"ESC;c:="uncommentbalance-parens"]"
"ESC;c:a:return"do-returnbalance-parens"}"
"ESC;c:b"backward-sexpbeginning-of-file"m:<"
"ESC;c:down"down-into-embedded
-editor
beginning-of-file"ESC;<"
"ESC;c:f"forward-sexpbeginning-of-file"d:up"
"ESC;c:g"ring-bellbeginning-of-file"c:home"
"ESC;c:k"remove-sexpbeginning-of-line"c:a"
"ESC;c:left"back-to-prev-embedded
-editor
beginning-of-line"d:left"
"ESC;c:p"flash-backward-sexpbeginning-of-line"m:left"
"ESC;c:return"do-returnbeginning-of-line"home"
"ESC;c:right"forward-to-next
-embedded-editor
capitalize-word"m:c"
"ESC;c:s:a:return"do-returncapitalize-word"ESC;c"
"ESC;c:semicolon"comment-outcenter-view-on-line"c:l"
"ESC;c:space"select-forward-sexpcheck syntax"c:c;c:c"
"ESC;c:t"transpose-sexpcheck syntax"f6"
"ESC;c:u"up-sexpcollapse-newline"c:x;c:o"
"ESC;c:up"up-out-of-embedded
-editor
collapse-space"m:space"
"ESC;d"kill-wordcollapse-space"ESC;space"
"ESC;del"backward-kill-wordcommand-repeat-0"c:u"
"ESC;down"down-sexpcommand-repeat-0"m:0"
"ESC;f"forward-wordcommand-repeat-0"ESC;0"
"ESC;g"goto-linecommand-repeat-1"m:1"
"ESC;l"downcase-wordcommand-repeat-1"ESC;1"
"ESC;left"backward-sexpcommand-repeat-2"m:2"
"ESC;o"toggle-overwritecommand-repeat-2"ESC;2"
"ESC;p"goto-positioncommand-repeat-3"m:3"
"ESC;return"do-returncommand-repeat-3"ESC;3"
"ESC;right"forward-sexpcommand-repeat-4"m:4"
"ESC;s:a:return"do-returncommand-repeat-4"ESC;4"
"ESC;s:b"backward-select
-word
command-repeat-5"m:5"
"ESC;s:c:b"select-backward
-sexp
command-repeat-5"ESC;5"
"ESC;s:c:down"select-down-sexpcommand-repeat-6"m:6"
"ESC;s:c:f"select-forward-sexpcommand-repeat-6"ESC;6"
"ESC;s:c:n"flash-forward-sexpcommand-repeat-7"m:7"
"ESC;s:c:return"do-returncommand-repeat-7"ESC;7"
"ESC;s:c:u"select-up-sexpcommand-repeat-8"m:8"
"ESC;s:down"select-down-sexpcommand-repeat-8"ESC;8"
"ESC;s:f"forward-select-wordcommand-repeat-9"m:9"
"ESC;s:l"insert-lambda-templatecommand-repeat-9"ESC;9"
"ESC;s:left"select-backward
-sexp
comment-out"m:c:semicolon"
"ESC;s:return"do-returncomment-out"ESC;c:semicolon"
"ESC;s:right"select-forward-sexpcopy-clipboard"m:w"
"ESC;s:up"select-up-sexpcopy-clipboard"ESC;w"
"ESC;s:v"select-page-upcopy-clipboard"a:c"
"ESC;space"collapse-spacecopy-clipboard"d:c"
"ESC;t"transpose-wordscopy-clipboard"c:insert"
"ESC;u"upcase-wordcut-clipboard"c:w"
"ESC;up"up-sexpcut-clipboard"a:x"
"ESC;v"previous-pagecut-clipboard"d:x"
"ESC;w"copy-clipboardcut-clipboard"s:delete"
"ESC;y"paste-nextdelete-key"del"
"ESC;{"insert-{}-pairdelete-next-character"c:d"
"ESC;|"insert-||-pairdelete-previous
-character
"c:h"
"TAB"tabify-at-caretdelete-to-end-of
-line
"c:k"
"["rewrite-square-parendo-return"s:return"
"]"balance-parensdo-return"s:c:return"
"a:c"copy-clipboarddo-return"a:return"
"a:c:down"down-into-embedded
-editor
do-return"s:a:return"
"a:c:left"back-to-prev-embedded
-editor
do-return"c:a:return"
"a:c:right"forward-to-next
-embedded-editor
do-return"c:s:a:return"
"a:c:up"up-out-of-embedded
-editor
do-return"c:return"
"a:down"next-pagedo-return"d:return"
"a:left"backward-worddo-return"m:return"
"a:return"do-returndo-return"ESC;return"
"a:right"forward-worddo-return"m:s:return"
"a:s:down"select-page-downdo-return"ESC;s:return"
"a:s:left"backward-select
-word
do-return"m:s:c:return"
"a:s:right"forward-select-worddo-return"ESC;s:c:return"
"a:s:up"select-up-sexpdo-return"m:a:return"
"a:up"previous-pagedo-return"ESC;a:return"
"a:v"paste-clipboarddo-return"m:s:a:return"
"a:x"cut-clipboarddo-return"ESC;s:a:return"
"a:z"undodo-return"m:c:a:return"
"c:)"non-clever-close
-round-paren
do-return"ESC;c:a:return"
"c:+"redodo-return"m:c:s:a:return"
"c:/"undodo-return"ESC;c:s:a:return"
"c:["non-clever-open
-square-bracket
do-return"m:c:return"
"c:]"non-clever-close
-square-bracket
do-return"ESC;c:return"
"c:_"undodo-return"return"
"c:a"beginning-of-linedown-into-embedded
-editor
"m:c:down"
"c:a:return"do-returndown-into-embedded
-editor
"ESC;c:down"
"c:b"backward-characterdown-into-embedded
-editor
"a:c:down"
"c:c;c:b"remove-parens-forwarddown-sexp"m:down"
"c:c;c:c"check syntaxdown-sexp"ESC;down"
"c:c;c:g"ring-belldowncase-word"m:l"
"c:c;c:l"introduce-let-ansdowncase-word"ESC;l"
"c:c;c:o"move-sexp-outend-of-file"m:>"
"c:c;c:r"make-read-onlyend-of-file"ESC;>"
"c:d"delete-next-characterend-of-file"d:down"
"c:down"next-pageend-of-file"c:end"
"c:e"end-of-lineend-of-line"c:e"
"c:end"end-of-fileend-of-line"d:right"
"c:f"forward-characterend-of-line"m:right"
"c:f6"toggle-focus-between
-definitions-and
-interactions
end-of-line"end"
"c:g"hide-searchexecute"f5"
"c:h"delete-previous
-character
find-string-again"d:g"
"c:home"beginning-of-fileflash-backward-sexp"m:c:p"
"c:i"toggle-search-focusflash-backward-sexp"ESC;c:p"
"c:insert"copy-clipboardflash-forward-sexp"m:s:c:n"
"c:k"delete-to-end-of
-line
flash-forward-sexp"ESC;s:c:n"
"c:l"center-view-on-lineforward-character"c:f"
"c:left"backward-wordforward-character"right"
"c:n"next-lineforward-select"s:c:f"
"c:o"open-lineforward-select"s:right"
"c:p"previous-lineforward-select-word"m:s:f"
"c:pagedown"next-tabforward-select-word"ESC;s:f"
"c:pageup"prev-tabforward-select-word"a:s:right"
"c:r"move-to-search-or
-reverse-search
forward-select-word"c:s:right"
"c:return"do-returnforward-sexp"ESC;right"
"c:right"forward-wordforward-sexp"m:c:f"
"c:s"move-to-search-or
-search
forward-sexp"ESC;c:f"
"c:s:a:return"do-returnforward-to-next
-embedded-editor
"m:c:right"
"c:s:left"backward-select
-word
forward-to-next
-embedded-editor
"ESC;c:right"
"c:s:right"forward-select-wordforward-to-next
-embedded-editor
"a:c:right"
"c:s:tab"prev-tabforward-word"m:f"
"c:space"toggle-anchorforward-word"ESC;f"
"c:t"transpose-charsforward-word"a:right"
"c:tab"next-tabforward-word"c:right"
"c:u"command-repeat-0goto-line"m:g"
"c:up"previous-pagegoto-line"ESC;g"
"c:v"next-pagegoto-position"m:p"
"c:w"cut-clipboardgoto-position"ESC;p"
"c:x;("keyboard-macro-start
-record
hide-search"c:g"
"c:x;)"keyboard-macro-end
-record
insert-""-pair"m:""
"c:x;b"jump to binding occurrenceinsert-""-pair"ESC;""
"c:x;c:f"load-fileinsert-()-pair"m:("
"c:x;c:g"ring-bellinsert-()-pair"ESC;("
"c:x;c:o"collapse-newlineinsert-[]-pair"m:["
"c:x;c:s"save-fileinsert-[]-pair"ESC;["
"c:x;c:w"save-file-asinsert-lambda-template"m:s:l"
"c:x;d"jump to definition (in other file)insert-lambda-template"ESC;s:l"
"c:x;e"keyboard-macro-run
-saved
insert-{}-pair"m:{"
"c:x;n"jump to next bound occurrenceinsert-{}-pair"ESC;{"
"c:x;o"toggle-focus-between
-definitions-and
-interactions
insert-||-pair"m:|"
"c:x;u"undoinsert-||-pair"ESC;|"
"c:y"paste-clipboardintroduce-let-ans"c:c;c:l"
"c:}"non-clever-close
-curley-bracket
jump to binding occurrence"c:x;b"
"d:c"copy-clipboardjump to definition (in other file)"c:x;d"
"d:down"end-of-filejump to next bound occurrence"c:x;n"
"d:g"find-string-againkeyboard-macro-end
-record
"c:x;)"
"d:left"beginning-of-linekeyboard-macro-run
-saved
"c:x;e"
"d:return"do-returnkeyboard-macro-start
-record
"c:x;("
"d:right"end-of-linekill-word"m:d"
"d:s"save-filekill-word"ESC;d"
"d:s:left"prev-tabload-file"c:x;c:f"
"d:s:right"next-tabmake-read-only"c:c;c:r"
"d:up"beginning-of-filemouse-popup-menu":rightbuttonseq"
"d:v"paste-clipboardmove-sexp-out"c:c;c:o"
"d:x"cut-clipboardmove-to-search-or
-reverse-search
"c:r"
"d:z"undomove-to-search-or
-search
"c:s"
"del"delete-keynext-line"c:n"
"down"next-linenext-line"down"
"end"end-of-linenext-page"c:v"
"f1"search-help-desknext-page"a:down"
"f5"executenext-page"pagedown"
"f6"check syntaxnext-page"c:down"
"home"beginning-of-linenext-tab"c:tab"
"insert"toggle-overwritenext-tab"d:s:right"
"left"backward-characternext-tab"c:pagedown"
"leftbuttondouble"select-click-wordnon-clever-close
-curley-bracket
"c:}"
"leftbuttontriple"select-click-linenon-clever-close
-round-paren
"c:)"
"m:""insert-""-pairnon-clever-close
-square-bracket
"c:]"
"m:("insert-()-pairnon-clever-open
-square-bracket
"c:["
"m:0"command-repeat-0open-line"c:o"
"m:1"command-repeat-1paste-click-region"middlebutton"
"m:2"command-repeat-2paste-clipboard"c:y"
"m:3"command-repeat-3paste-clipboard"a:v"
"m:4"command-repeat-4paste-clipboard"d:v"
"m:5"command-repeat-5paste-clipboard"s:insert"
"m:6"command-repeat-6paste-next"m:y"
"m:7"command-repeat-7paste-next"ESC;y"
"m:8"command-repeat-8prev-tab"c:s:tab"
"m:9"command-repeat-9prev-tab"d:s:left"
"m:<"beginning-of-fileprev-tab"c:pageup"
"m:>"end-of-fileprevious-line"c:p"
"m:["insert-[]-pairprevious-line"up"
"m:a:return"do-returnprevious-page"m:v"
"m:b"backward-wordprevious-page"ESC;v"
"m:c"capitalize-wordprevious-page"a:up"
"m:c:="uncommentprevious-page"pageup"
"m:c:a:return"do-returnprevious-page"c:up"
"m:c:b"backward-sexpredo"c:+"
"m:c:down"down-into-embedded
-editor
remove-parens-forward"c:c;c:b"
"m:c:f"forward-sexpremove-sexp"m:c:k"
"m:c:g"ring-bellremove-sexp"ESC;c:k"
"m:c:k"remove-sexprewrite-square-paren"["
"m:c:left"back-to-prev-embedded
-editor
ring-bell"m:c:g"
"m:c:p"flash-backward-sexpring-bell"ESC;c:g"
"m:c:return"do-returnring-bell"c:x;c:g"
"m:c:right"forward-to-next
-embedded-editor
ring-bell"c:c;c:g"
"m:c:s:a:return"do-returnsave-file"c:x;c:s"
"m:c:semicolon"comment-outsave-file"d:s"
"m:c:space"select-forward-sexpsave-file-as"c:x;c:w"
"m:c:t"transpose-sexpsearch-help-desk"f1"
"m:c:u"up-sexpselect-backward
-sexp
"m:s:c:b"
"m:c:up"up-out-of-embedded
-editor
select-backward
-sexp
"ESC;s:left"
"m:d"kill-wordselect-backward
-sexp
"ESC;s:c:b"
"m:del"backward-kill-wordselect-click-line"leftbuttontriple"
"m:down"down-sexpselect-click-word"leftbuttondouble"
"m:f"forward-wordselect-down"s:c:n"
"m:g"goto-lineselect-down"s:down"
"m:l"downcase-wordselect-down-sexp"m:s:down"
"m:left"beginning-of-lineselect-down-sexp"ESC;s:down"
"m:o"toggle-overwriteselect-down-sexp"m:s:c:down"
"m:p"goto-positionselect-down-sexp"ESC;s:c:down"
"m:return"do-returnselect-forward-sexp"ESC;s:right"
"m:right"end-of-lineselect-forward-sexp"m:s:c:f"
"m:s:a:return"do-returnselect-forward-sexp"ESC;s:c:f"
"m:s:b"backward-select
-word
select-forward-sexp"m:c:space"
"m:s:c:b"select-backward
-sexp
select-forward-sexp"ESC;c:space"
"m:s:c:down"select-down-sexpselect-page-down"s:c:v"
"m:s:c:f"select-forward-sexpselect-page-down"a:s:down"
"m:s:c:n"flash-forward-sexpselect-page-down"s:pagedown"
"m:s:c:return"do-returnselect-page-down"s:c:down"
"m:s:c:u"select-up-sexpselect-page-up"m:s:v"
"m:s:down"select-down-sexpselect-page-up"ESC;s:v"
"m:s:f"forward-select-wordselect-page-up"s:a:up"
"m:s:l"insert-lambda-templateselect-page-up"s:pageup"
"m:s:left"select-to-beginning
-of-line
select-page-up"s:c:up"
"m:s:return"do-returnselect-to-beginning
-of-file
"s:c:home"
"m:s:right"select-to-end-of
-line
select-to-beginning
-of-file
"s:d:up"
"m:s:up"select-up-sexpselect-to-beginning
-of-line
"m:s:left"
"m:s:v"select-page-upselect-to-beginning
-of-line
"s:home"
"m:space"collapse-spaceselect-to-beginning
-of-line
"s:c:a"
"m:t"transpose-wordsselect-to-end-of
-file
"s:c:end"
"m:u"upcase-wordselect-to-end-of
-file
"s:d:down"
"m:up"up-sexpselect-to-end-of
-line
"m:s:right"
"m:v"previous-pageselect-to-end-of
-line
"s:end"
"m:w"copy-clipboardselect-to-end-of
-line
"s:c:e"
"m:y"paste-nextselect-up"s:c:p"
"m:{"insert-{}-pairselect-up"s:up"
"m:|"insert-||-pairselect-up-sexp"m:s:up"
"middlebutton"paste-click-regionselect-up-sexp"ESC;s:up"
"pagedown"next-pageselect-up-sexp"a:s:up"
"pageup"previous-pageselect-up-sexp"m:s:c:u"
"return"do-returnselect-up-sexp"ESC;s:c:u"
"right"forward-charactertabify-at-caret"TAB"
"s:a:return"do-returntoggle-anchor"c:space"
"s:a:up"select-page-uptoggle-focus-between
-definitions-and
-interactions
"c:x;o"
"s:c:a"select-to-beginning
-of-line
toggle-focus-between
-definitions-and
-interactions
"c:f6"
"s:c:b"backward-selecttoggle-overwrite"m:o"
"s:c:down"select-page-downtoggle-overwrite"ESC;o"
"s:c:e"select-to-end-of
-line
toggle-overwrite"insert"
"s:c:end"select-to-end-of
-file
toggle-search-focus"c:i"
"s:c:f"forward-selecttranspose-chars"c:t"
"s:c:home"select-to-beginning
-of-file
transpose-sexp"m:c:t"
"s:c:n"select-downtranspose-sexp"ESC;c:t"
"s:c:p"select-uptranspose-words"m:t"
"s:c:return"do-returntranspose-words"ESC;t"
"s:c:up"select-page-upuncomment"m:c:="
"s:c:v"select-page-downuncomment"ESC;c:="
"s:d:down"select-to-end-of
-file
undo"c:_"
"s:d:up"select-to-beginning
-of-file
undo"c:/"
"s:delete"cut-clipboardundo"\u001f"
"s:down"select-downundo"a:z"
"s:end"select-to-end-of
-line
undo"d:z"
"s:home"select-to-beginning
-of-line
undo"c:x;u"
"s:insert"paste-clipboardup-out-of-embedded
-editor
"m:c:up"
"s:left"backward-selectup-out-of-embedded
-editor
"ESC;c:up"
"s:pagedown"select-page-downup-out-of-embedded
-editor
"a:c:up"
"s:pageup"select-page-upup-sexp"m:up"
"s:return"do-returnup-sexp"ESC;up"
"s:right"forward-selectup-sexp"m:c:u"
"s:up"select-upup-sexp"ESC;c:u"
"up"previous-lineupcase-word"m:u"
"}"balance-parensupcase-word"ESC;u"

The following tables are meant to help you in making decisions about what shortcuts you might want to create. I've arranged them first by platform specificity and followed up with tables of easy sequences to type and then the akward sequences, either because they take your hand off the home row, or they involve more than one modifier key and finally those that involve a sequence of keystrokes. You'll find that some sequences will inevitably be in more than one table, as they qualify under several catagories. If your like me you'll find it ineresting what choices were made to accomadate such a diverse audience as are the consumers of PLT software.


Unicode Character - Control - Unit Separator: its control effect is to make following text underlined.
"\u001f"undo

Platform Neutrual Keyboard Commands: avaialable on all platforms.
"ESC;c:="uncomment
"ESC;c:b"backward-sexp
"ESC;c:down"down-into-embedded-editor
"ESC;c:f"forward-sexp
"ESC;c:g"ring-bell
"ESC;c:k"remove-sexp
"ESC;c:left"back-to-prev-embedded-editor
"ESC;c:p"flash-backward-sexp
"ESC;c:return"do-return
"ESC;c:right"forward-to-next-embedded-editor
"ESC;c:semicolon"comment-out
"ESC;c:space"select-forward-sexp
"ESC;c:t"transpose-sexp
"ESC;c:u"up-sexp
"ESC;c:up"up-out-of-embedded-editor
"c:)"non-clever-close-round-paren
"c:+"redo
"c:/"undo
"c:["non-clever-open-square-bracket
"c:]"non-clever-close-square-bracket
"c:_"undo
"c:a"beginning-of-line
"c:b"backward-character
"c:d"delete-next-character
"c:down"next-page
"c:e"end-of-line
"c:end"end-of-file
"c:f"forward-character
"c:f6"toggle-focus-between-definitions-and-interactions
"c:g"hide-search
"c:h"delete-previous-character
"c:home"beginning-of-file
"c:i"toggle-search-focus
"c:insert"copy-clipboard
"c:k"delete-to-end-of-line
"c:l"center-view-on-line
"c:left"backward-word
"c:n"next-line
"c:o"open-line
"c:p"previous-line
"c:pagedown"next-tab
"c:pageup"prev-tab
"c:r"move-to-search-or-reverse-search
"c:return"do-return
"c:right"forward-word
"c:s"move-to-search-or-search
"c:space"toggle-anchor
"c:t"transpose-chars
"c:tab"next-tab
"c:u"command-repeat-0
"c:up"previous-page
"c:v"next-page
"c:w"cut-clipboard
"c:x;("keyboard-macro-start-record
"c:x;)"keyboard-macro-end-record
"c:x;b"jump to binding occurrence
"c:x;d"jump to definition (in other file)
"c:x;e"keyboard-macro-run-saved
"c:x;n"jump to next bound occurrence
"c:x;o"toggle-focus-between-definitions-and-interactions
"c:x;u"undo
"c:y"paste-clipboard
"c:}"non-clever-close-curley-bracket

Platform Neutral Mouse Shortcuts available on any platform with a mouse, but note `paste-click-region' requires a three-button mouse.
":rightbuttonseq"mouse-popup-menu
"leftbuttondouble"select-click-word
"leftbuttontriple"select-click-line
"middlebutton"paste-click-region

Mac Specific Shortcuts: using the `option' key modifier - from my experience on a Mac Pro running OS X Server v10.4.9, thankfully the a:c, a:v, a:x and a:z shortcuts aren't active, and the option key's function to provide an extended character set to your keyboard takes precedence. It is interesting to note the sequences involving both the meta and option key; as far as I know these are impossible combinations on any keyboard of which I'm familiar. Also, there seems to be an effort to capture all possible bindings of the return key, perhaps to prevent anyone from binding any modifier enhanced sequence to the return key.
"ESC;a:return"do-return
"ESC;c:a:return"do-return
"ESC;c:s:a:return"do-return
"ESC;s:a:return"do-return
"a:c"copy-clipboard
"a:c:down"down-into-embedded-editor
"a:c:left"back-to-prev-embedded-editor
"a:c:right"forward-to-next-embedded-editor
"a:c:up"up-out-of-embedded-editor
"a:down"next-page
"a:left"backward-word
"a:return"do-return
"a:right"forward-word
"a:s:down"select-page-down
"a:s:left"backward-select-word
"a:s:right"forward-select-word
"a:s:up"select-up-sexp
"a:up"previous-page
"a:v"paste-clipboard
"a:x"cut-clipboard
"a:z"undo
"c:a:return"do-return
"c:s:a:return"do-return
"m:a:return"do-return
"m:c:a:return"do-return
"m:c:s:a:return"do-return
"m:s:a:return"do-return
"s:a:return"do-return
"s:a:up"select-page-up

Mac Specific Shortcuts: using the `command' modifier
"d:c"copy-clipboard
"d:down"end-of-file
"d:g"find-string-again
"d:left"beginning-of-line
"d:return"do-return
"d:right"end-of-line
"d:s"save-file
"d:s:left"prev-tab
"d:s:right"next-tab
"d:up"beginning-of-file
"d:v"paste-clipboard
"d:x"cut-clipboard
"d:z"undo
"s:d:down"select-to-end-of-file
"s:d:up"select-to-beginning-of-file

*nix and Windows Specific Shortcuts: using the `meta' key modifier on *nix or `Alt' key modifier on Windows - also available on OS X by giving up the function of your option key.
"m:""insert-""-pair
"m:("insert-()-pair
"m:0"command-repeat-0
"m:1"command-repeat-1
"m:2"command-repeat-2
"m:3"command-repeat-3
"m:4"command-repeat-4
"m:5"command-repeat-5
"m:6"command-repeat-6
"m:7"command-repeat-7
"m:8"command-repeat-8
"m:9"command-repeat-9
"m:<"beginning-of-file
"m:>"end-of-file
"m:["insert-[]-pair
"m:a:return"do-return
"m:b"backward-word
"m:c"capitalize-word
"m:c:="uncomment
"m:c:a:return"do-return
"m:c:b"backward-sexp
"m:c:down"down-into-embedded-editor
"m:c:f"forward-sexp
"m:c:g"ring-bell
"m:c:k"remove-sexp
"m:c:left"back-to-prev-embedded-editor
"m:c:p"flash-backward-sexp
"m:c:return"do-return
"m:c:right"forward-to-next-embedded-editor
"m:c:s:a:return"do-return
"m:c:semicolon"comment-out
"m:c:space"select-forward-sexp
"m:c:t"transpose-sexp
"m:c:u"up-sexp
"m:c:up"up-out-of-embedded-editor
"m:d"kill-word
"m:del"backward-kill-word
"m:down"down-sexp
"m:f"forward-word
"m:g"goto-line
"m:l"downcase-word
"m:left"beginning-of-line
"m:o"toggle-overwrite
"m:p"goto-position
"m:return"do-return
"m:right"end-of-line
"m:s:a:return"do-return
"m:s:b"backward-select-word
"m:s:c:b"select-backward-sexp
"m:s:c:down"select-down-sexp
"m:s:c:f"select-forward-sexp
"m:s:c:n"flash-forward-sexp
"m:s:c:return"do-return
"m:s:c:u"select-up-sexp
"m:s:down"select-down-sexp
"m:s:f"forward-select-word
"m:s:l"insert-lambda-template
"m:s:left"select-to-beginning-of-line
"m:s:return"do-return
"m:s:right"select-to-end-of-line
"m:s:up"select-up-sexp
"m:s:v"select-page-up
"m:space"collapse-space
"m:t"transpose-words
"m:u"upcase-word
"m:up"up-sexp
"m:v"previous-page
"m:w"copy-clipboard
"m:y"paste-next
"m:{"insert-{}-pair
"m:|"insert-||-pair

Easy to Type Shortcuts
")"balance-parens
"TAB"tabify-at-caret
"["rewrite-square-paren
"]"balance-parens
"a:c"copy-clipboard
"a:v"paste-clipboard
"a:x"cut-clipboard
"a:z"undo
"c:)"non-clever-close-round-paren
"c:+"redo
"c:/"undo
"c:["non-clever-open-square-bracket
"c:]"non-clever-close-square-bracket
"c:_"undo
"c:a"beginning-of-line
"c:b"backward-character
"c:d"delete-next-character
"c:e"end-of-line
"c:f"forward-character
"c:f6"toggle-focus-between-definitions-and-interactions
"c:g"hide-search
"c:h"delete-previous-character
"c:i"toggle-search-focus
"c:k"delete-to-end-of-line
"c:l"center-view-on-line
"c:n"next-line
"c:o"open-line
"c:p"previous-line
"c:r"move-to-search-or-reverse-search
"c:return"do-return
"c:s"move-to-search-or-search
"c:space"toggle-anchor
"c:t"transpose-chars
"c:tab"next-tab
"c:u"command-repeat-0
"c:v"next-page
"c:w"cut-clipboard
"c:y"paste-clipboard
"d:c"copy-clipboard
"d:g"find-string-again
"d:return"do-return
"d:s"save-file
"d:v"paste-clipboard
"d:x"cut-clipboard
"d:z"undo
"f1"search-help-desk
"f5"execute
"f6"check syntax
"m:""insert-""-pair
"m:("insert-()-pair
"m:0"command-repeat-0
"m:1"command-repeat-1
"m:2"command-repeat-2
"m:3"command-repeat-3
"m:4"command-repeat-4
"m:5"command-repeat-5
"m:6"command-repeat-6
"m:7"command-repeat-7
"m:8"command-repeat-8
"m:9"command-repeat-9
"m:<"beginning-of-file
"m:>"end-of-file
"m:["insert-[]-pair
"m:b"backward-word
"m:c"capitalize-word
"m:d"kill-word
"m:f"forward-word
"m:g"goto-line
"m:l"downcase-word
"m:o"toggle-overwrite
"m:p"goto-position
"m:space"collapse-space
"m:t"transpose-words
"m:u"upcase-word
"m:v"previous-page
"m:w"copy-clipboard
"m:y"paste-next
"m:{"insert-{}-pair
"m:|"insert-||-pair
"return"do-return
"}"balance-parens

Shortcuts That Take a Hand Off Home Row
":rightbuttonseq"mouse-popup-menu
"ESC;c:down"down-into-embedded-editor
"ESC;c:left"back-to-prev-embedded-editor
"ESC;c:right"forward-to-next-embedded-editor
"ESC;c:up"up-out-of-embedded-editor
"ESC;del"backward-kill-word
"ESC;down"down-sexp
"ESC;left"backward-sexp
"ESC;right"forward-sexp
"ESC;s:c:down"select-down-sexp
"ESC;s:down"select-down-sexp
"ESC;s:left"select-backward-sexp
"ESC;s:right"select-forward-sexp
"ESC;s:up"select-up-sexp
"ESC;up"up-sexp
"a:c:down"down-into-embedded-editor
"a:c:left"back-to-prev-embedded-editor
"a:c:right"forward-to-next-embedded-editor
"a:c:up"up-out-of-embedded-editor
"a:down"next-page
"a:left"backward-word
"a:right"forward-word
"a:s:down"select-page-down
"a:s:left"backward-select-word
"a:s:right"forward-select-word
"a:s:up"select-up-sexp
"a:up"previous-page
"c:down"next-page
"c:end"end-of-file
"c:home"beginning-of-file
"c:insert"copy-clipboard
"c:left"backward-word
"c:pagedown"next-tab
"c:pageup"prev-tab
"c:right"forward-word
"c:s:left"backward-select-word
"c:s:right"forward-select-word
"c:up"previous-page
"d:down"end-of-file
"d:left"beginning-of-line
"d:right"end-of-line
"d:s:left"prev-tab
"d:s:right"next-tab
"d:up"beginning-of-file
"del"delete-key
"down"next-line
"end"end-of-line
"home"beginning-of-line
"insert"toggle-overwrite
"left"backward-character
"leftbuttondouble"select-click-word
"leftbuttontriple"select-click-line
"m:c:down"down-into-embedded-editor
"m:c:left"back-to-prev-embedded-editor
"m:c:right"forward-to-next-embedded-editor
"m:c:up"up-out-of-embedded-editor
"m:del"backward-kill-word
"m:down"down-sexp
"m:left"beginning-of-line
"m:right"end-of-line
"m:s:c:down"select-down-sexp
"m:s:down"select-down-sexp
"m:s:left"select-to-beginning-of-line
"m:s:right"select-to-end-of-line
"m:s:up"select-up-sexp
"m:up"up-sexp
"middlebutton"paste-click-region
"pagedown"next-page
"pageup"previous-page
"right"forward-character
"s:a:up"select-page-up
"s:c:down"select-page-down
"s:c:end"select-to-end-of-file
"s:c:home"select-to-beginning-of-file
"s:c:up"select-page-up
"s:d:down"select-to-end-of-file
"s:d:up"select-to-beginning-of-file
"s:delete"cut-clipboard
"s:down"select-down
"s:end"select-to-end-of-line
"s:home"select-to-beginning-of-line
"s:insert"paste-clipboard
"s:left"backward-select
"s:pagedown"select-page-down
"s:pageup"select-page-up
"s:right"forward-select
"s:up"select-up
"up"previous-line

Single Chorded Shortcuts With More Than One Modifier
"a:c:down"down-into-embedded-editor
"a:c:left"back-to-prev-embedded-editor
"a:c:right"forward-to-next-embedded-editor
"a:c:up"up-out-of-embedded-editor
"a:s:down"select-page-down
"a:s:left"backward-select-word
"a:s:right"forward-select-word
"a:s:up"select-up-sexp
"c:a:return"do-return
"c:s:a:return"do-return
"c:s:left"backward-select-word
"c:s:right"forward-select-word
"c:s:tab"prev-tab
"d:s:left"prev-tab
"d:s:right"next-tab
"m:a:return"do-return
"m:c:="uncomment
"m:c:a:return"do-return
"m:c:b"backward-sexp
"m:c:down"down-into-embedded-editor
"m:c:f"forward-sexp
"m:c:g"ring-bell
"m:c:k"remove-sexp
"m:c:left"back-to-prev-embedded-editor
"m:c:p"flash-backward-sexp
"m:c:return"do-return
"m:c:right"forward-to-next-embedded-editor
"m:c:s:a:return"do-return
"m:c:semicolon"comment-out
"m:c:space"select-forward-sexp
"m:c:t"transpose-sexp
"m:c:u"up-sexp
"m:c:up"up-out-of-embedded-editor
"m:s:a:return"do-return
"m:s:b"backward-select-word
"m:s:c:b"select-backward-sexp
"m:s:c:down"select-down-sexp
"m:s:c:f"select-forward-sexp
"m:s:c:n"flash-forward-sexp
"m:s:c:return"do-return
"m:s:c:u"select-up-sexp
"m:s:down"select-down-sexp
"m:s:f"forward-select-word
"m:s:l"insert-lambda-template
"m:s:left"select-to-beginning-of-line
"m:s:return"do-return
"m:s:right"select-to-end-of-line
"m:s:up"select-up-sexp
"m:s:v"select-page-up
"s:a:return"do-return
"s:a:up"select-page-up
"s:c:a"select-to-beginning-of-line
"s:c:b"backward-select
"s:c:down"select-page-down
"s:c:e"select-to-end-of-line
"s:c:end"select-to-end-of-file
"s:c:f"forward-select
"s:c:home"select-to-beginning-of-file
"s:c:n"select-down
"s:c:p"select-up
"s:c:return"do-return
"s:c:up"select-page-up
"s:c:v"select-page-down
"s:d:down"select-to-end-of-file
"s:d:up"select-to-beginning-of-file

Shortcuts That Require a Sequence of Keys
"ESC;""insert-""-pair
"ESC;("insert-()-pair
"ESC;0"command-repeat-0
"ESC;1"command-repeat-1
"ESC;2"command-repeat-2
"ESC;3"command-repeat-3
"ESC;4"command-repeat-4
"ESC;5"command-repeat-5
"ESC;6"command-repeat-6
"ESC;7"command-repeat-7
"ESC;8"command-repeat-8
"ESC;9"command-repeat-9
"ESC;<"beginning-of-file
"ESC;>"end-of-file
"ESC;["insert-[]-pair
"ESC;a:return"do-return
"ESC;b"backward-word
"ESC;c"capitalize-word
"ESC;c:="uncomment
"ESC;c:a:return"do-return
"ESC;c:b"backward-sexp
"ESC;c:down"down-into-embedded-editor
"ESC;c:f"forward-sexp
"ESC;c:g"ring-bell
"ESC;c:k"remove-sexp
"ESC;c:left"back-to-prev-embedded-editor
"ESC;c:p"flash-backward-sexp
"ESC;c:return"do-return
"ESC;c:right"forward-to-next-embedded-editor
"ESC;c:s:a:return"do-return
"ESC;c:semicolon"comment-out
"ESC;c:space"select-forward-sexp
"ESC;c:t"transpose-sexp
"ESC;c:u"up-sexp
"ESC;c:up"up-out-of-embedded-editor
"ESC;d"kill-word
"ESC;del"backward-kill-word
"ESC;down"down-sexp
"ESC;f"forward-word
"ESC;g"goto-line
"ESC;l"downcase-word
"ESC;left"backward-sexp
"ESC;o"toggle-overwrite
"ESC;p"goto-position
"ESC;return"do-return
"ESC;right"forward-sexp
"ESC;s:a:return"do-return
"ESC;s:b"backward-select-word
"ESC;s:c:b"select-backward-sexp
"ESC;s:c:down"select-down-sexp
"ESC;s:c:f"select-forward-sexp
"ESC;s:c:n"flash-forward-sexp
"ESC;s:c:return"do-return
"ESC;s:c:u"select-up-sexp
"ESC;s:down"select-down-sexp
"ESC;s:f"forward-select-word
"ESC;s:l"insert-lambda-template
"ESC;s:left"select-backward-sexp
"ESC;s:return"do-return
"ESC;s:right"select-forward-sexp
"ESC;s:up"select-up-sexp
"ESC;s:v"select-page-up
"ESC;space"collapse-space
"ESC;t"transpose-words
"ESC;u"upcase-word
"ESC;up"up-sexp
"ESC;v"previous-page
"ESC;w"copy-clipboard
"ESC;y"paste-next
"ESC;{"insert-{}-pair
"ESC;|"insert-||-pair
"c:c;c:b"remove-parens-forward
"c:c;c:c"check syntax
"c:c;c:g"ring-bell
"c:c;c:l"introduce-let-ans
"c:c;c:o"move-sexp-out
"c:c;c:r"make-read-only
"c:x;("keyboard-macro-start-record
"c:x;)"keyboard-macro-end-record
"c:x;b"jump to binding occurrence
"c:x;c:f"load-file
"c:x;c:g"ring-bell
"c:x;c:o"collapse-newline
"c:x;c:s"save-file
"c:x;c:w"save-file-as
"c:x;d"jump to definition (in other file)
"c:x;e"keyboard-macro-run-saved
"c:x;n"jump to next bound occurrence
"c:x;o"toggle-focus-between-definitions-and-interactions
"c:x;u"undo

You should be aware that these tables were built from the output as produced on a Mac Pro; it is entirely possible that they would give somewhat different output depending on the platform you have DrScheme installed on. Use these tables as a guide, and when you want to make a binding change, double check your own Active Keybinding dialog to make certain that the keys your are binding to are either free or the ones you had decided to override. Finally, the Active Keybinding dialog will show many bindings to menu shortcuts, but the name that is used to describe it is clearly not a valid Scheme identifier, rather it is a description of the menu item's function. If you really want to bind to one of these functions, you'll need the assistance of someone from the PLT team. I had hoped to be able to programatically provide a list of these functions for you, but the code that manipulates these bindings is inside a private function within the code that defines one of the frameworks most basic interface, and there was no clear way for me to access it without hacking into DrScheme.

Now to wrap it all up, I've put an abridged version of my own keybinding module below. However, the two different forms in which you will likely be calling your target functions. The first form is when you simply write your own lambda function of two arguments, an editor<%> object and an event<%> object. You'll likely have little use for the event<%> object, as you know what triggered the call to your function, however, if you had need of the exact time that the event had taken place, you can query the event to get that information. The editor<%> object, on the other hand, is your only link to DrScheme. You can call any public method on the editor you so desire. I've given some simple examples of inserting a string-snip<%> object. But, truely, your imagination is the only limit on what you can do with your custom keybinding and a live editor at your command.

The second form is the method you need to use to execute any of the named functions from the editor's keymap. You send the editor's keymap the call-function method with the name of the function as a string argument. These are the functions listed in the tables. I encourage you to read the documentation regarding the editor<%> class. You're bound to come up with some inovative ways of doing things you never dreamed of before.

As always, it's been a pleasure bringing you this article. I hope you have learned something new. Either way, please leave a comment about your impression of the topic, how it was covered, how it could be improved or anything else you have on your mind.

(module schemekeys-keymap
(lib "keybinding-lang.ss" "framework")

; Adds DrScheme Specific functions to the
; available functions we can bind to.
(require (lib "tool-lib.ss" "drscheme"))

(define (sendsnip e s)
(let ([snip (make-object string-snip% s)])
  (send snip set-flags '(hard-newline))
  (send e insert snip (string-length s) 0)))

(keybinding ":d:semicolon"
(lambda (editor event)
  (preferences:show-dialog)))
(keybinding ":c:1"
(lambda (editor event)
  (sendsnip editor
            "(module <name>
            \"../schemekeys/schemekeys.ss\"")))
(keybinding ":c:5"
(lambda (editor event)
  (sendsnip editor
            "(fold (λ (x rest)
             (if (<pred>? x)
             (cons x rest) rest))
             () <list>)")))
(keybinding ":f2"
(lambda (editor event)
  (send
    (send editor get-keymap)
    call-function
    "toggle-focus-between-definitions-and-interactions"
    editor event #t)))
(keybinding ":c:8"
(lambda (editor event)
  (send
    (send editor get-keymap)
    call-function
    "keyboard-macro-start-record"
    editor event #t)))
(keybinding ":c:9"
(lambda (editor event)
  (send
    (send editor get-keymap)
    call-function
    "keyboard-macro-end-record"
    editor event #t)))
(keybinding ":c:0"
(lambda (editor event)
  (send
    (send editor get-keymap)
    call-function
    "keyboard-macro-run-saved"
    editor event #t)))
(keybinding ":d:]"
(lambda (editor event)
  (send
    (send editor get-keymap)
    call-function
    "comment-out"
    editor event #t)))
(keybinding ":d:["
(lambda (editor event)
  (send
    (send editor get-keymap)
    call-function
    "uncomment"
    editor event #t)))

Enjoy!

--kyle

7 comments:

Jens Axel Søgaard said...

Very nice explanation. I am sure your article will inspire some experimentation.

Btw - you mention that XP has no Meta-key. I thought Alt was interprested as the Meta key (it does in Emacs - I think).

Kyle Smith said...

Yeah, your absolutely right about Alt serving as the meta key under DrScheme (and other programs as you point out.) I revised the post to include the statement that at the time I began working with DrScheme, I was clueless as to being able to use the Alt key. It's funny I didn't catch that, because I make that very point in the heading of my tables that use the meta key.

Thanks for the comment Jens.

--kyle

Jesse Ruderman said...

Do you know an easy way to enter λ (lambda) on Mac? Is there an alt or alt+shift combination for it?

Kyle Smith said...

Hi Jesse,

In DrScheme the shortcut is command-\. If you want to type it into other applications in Mac OS X, you'll need to use an alternate keyboard layout, which can be found under internationalization in the systems preferences dialog. I found an excellent tutorial on how this all works form Penn State.

Hope this helps.

--kyle

Griff said...

Your article is priceless!

Joy said...

I find most of it is useless for me because I don't need that much information...can't you just post a file that defines the hotkey and give instructions for how to use it?

Kyle Smith said...

Joy,
This article is quite out of date, and the information you solicite is very accessible from within the application. If you find the titles of the commands don't fully explain their function, their are many helpfull people in the PLT Scheme family that would be happy to assist you, or point you in the direction of the appropriate documentation. You will find many usefull links to various resources within the PLT group on the sidebar of this blog.

--kyle