Why Keymapping rocks?

Smalltalkers always claim that Smalltalk has invented the mouse and the User Interface. Even if that can be discussed, I have to say it: I HATE THE MOUSE. The less I can use it, the best. The more I can stay with the keyboard, the best. Besides I am Smalltalk lover, I always try to admit when Smalltalk is not the best in certain aspect. And at least in Pharo, the need of the mouse is too much.

I have worked in industry with Eclipse for 3 years. And I am a geek who stays hours in front of the PC and when I was in Linux/Windows I was using all the time Total Commander or something similar. I used to know all possible shortcuts of all the software I was using in my machine. When I then started to program in Squeak it has like if I come back 20 years in time. I was not able to use the keyboard as I was doing it in the rest of my machine (and Eclipse included). It felt really frustrating. But ok…Smalltalk showed me so many cool stuff that I could live with the lack of proper shortcuts.


Today, I can say Pharo has improved a little in the direction of improving the user experience with the keyboard.  This is thanks to Guillermo Pollito who has been developing Keymapping for a while. And now Débora Fortini has joined. Keymapping is a really small tool that let you define keyboard shortcuts per morph. So you can take any subclass of Morph and define your OWN shortcuts to do what you want. Of course, it may happen that there are conflicts with shortcuts of other morphs or even with global shortcuts of your Operating System. Nevertheless, the framework is there and working.

So….why keymapping rocks?  Well, during Smalltalks I say to Guillermo “If you give me shortcuts to step into, step over, restart, proceed, and go up and down in the Debugger, I pay you several beers”. After 5 minutes, they were already working perfectly. What was needed?  First just create the class:

Object subclass: #KMDebuggerShortcuts
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Keymapping-Debugger'

And then put a class side method :

buildDebuggerShortcutsOn: aBuilder
(aBuilder shortcut: #stackDown)
category: #DebuggerShortcuts
default: $d command shift, Character arrowDown
do: [ :target | target down ].
(aBuilder shortcut: #stackUp)
category: #DebuggerShortcuts
default: $d command shift, Character arrowUp
do: [ :target | target up ].
(aBuilder shortcut: #proceedDebugger)
category: #DebuggerShortcuts
default: $d command shift, $p
do: [ :target | target  proceed ].
(aBuilder shortcut: #restartDebugger)
category: #DebuggerShortcuts
default: $d command shift, $r
do: [ :target | target  restart ].
(aBuilder shortcut: #stepIntoDebugger)
category: #DebuggerShortcuts
default: $d command shift, $i
do: [ :target | target  send ].
(aBuilder shortcut: #stepOverDebugger)
category: #DebuggerShortcuts
default: $d command shift, $o
do: [ :target | target  doStep ].
(aBuilder shortcut: #stepIntoBlockDebugger)
category: #DebuggerShortcuts
default: $d command shift, $t
do: [ :target | target  stepIntoBlock ].
(aBuilder shortcut: #SeeFullStackDebugger)
category: #DebuggerShortcuts
default: $d command shift, $f
do: [ :target | target  fullStack ].
(aBuilder shortcut: #runHereDebugger)
category: #DebuggerShortcuts
default: $d command shift, $h
do: [ :target | target  runToSelection ].

All shortcuts are defined in the same way: you create a method which receives a builder. The method #shortcut receives a shortcut name and creates an instance of KMKeymapBuilder. Then, sending the message #category:default:do: to the created KMKeymapBuilder, you can define all shortcuts. The first parameter is a category. The second is the combination of keys for the shortcut and the last parameter is the block to evaluate when such shortcut is pressed. Notice that the block receives at least the target object. In this case the target is the debugger.

Now, the last part is to tell the Debugger that it should attach those shortcuts. To do that, we had to overwrite (for example) the method Debugger >> #openFullMorphicLabel:

openFullMorphicLabel: aLabelString
"Open a full morphic debugger with the given label"

| window |
window := UIManager default openDebugger: self fullMorphicLabel: aLabelString.
window attachKeymapCategory: #DebuggerShortcuts targetting: self.

Notice in this method the line number 6. So…after 5 minutes that took Guille to code that, I had the shortcuts I ever wanted.

Available shortcuts

What is important of Keymapping is the infrastructure since it give us the tool to create our own shortcuts. Or even better, integrate in Pharo new shortcuts. Just to give you an idea, KMMonticelloShortcuts has shortcuts for committing, open repository, view changes, etc. KMGlobalShortcuts has shortcuts for saving the image, to open the world menu, to open a workspace, to open a transcript, to open Monticello, to open a class browser, etc… So…come on!!  what are you waiting to give it a try?

How to install it?  As easy as always:

Gofer new
squeaksource: 'ShortWays';
package: 'ConfigurationOfKeymapping';

(ConfigurationOfKeymapping project version: #bleedingEdge) load

Notice that Keymapping has an integration with the Settings framework. So if you open the Setting Browser and go to the category “Keymapping” you will see some of the shortcuts and of course you will be able to modify them. Note that not all shortcuts are yet integrated to the Settings framework since Keymapping is still in development 🙂

What I would like in the future

  • The VM so far cannot handle some key events of certain keys like functions. Moreover, it seems (but I am not sure) that different VMs (the Windows VM, Linux, Mac OSX) do not handle all the key events the same way. It would be nice if they can be uniform.
  • In Pharo, when you do right-click or whatever menu that show you options like “do-it”, “print it”, etc., they all show the shortcut for them. However, if you do change them with KeyMappings, then such menu is not updated. It would be nice if the menu is auto-generated depending on the current configured shortcut.
  • It would be nice to have a way of tracking conflicts between shortcuts.

8 thoughts on “Why Keymapping rocks?

  1. Both conflict detection and menu updating were part of my original version of Keymappings. It looks like this package has received a lot of inspired work from the community so I’m sure that those two items will eventually see it in to the modern version.

    The differences between VM’s has plagued Keymappings from the beginning. As I remember, there are two conflicting forces here: 1) the desire to have the VM smooth out platform differences and 2) the lack of a platform neutral keystroke model. For example, how should “left shift + a” be delivered to the image? A or left-shift+A? Should qualifier key events be delivered? etc Now add to this all the oddities associated with various keyboards, OS’s etc and you have a real mess. I would like to see the VM deliver platform dependent but as primitive as possible keystrokes to the image and giving us the power to make platform dependent decisions regarding qualifier keys etc. We could build our own “Squeak/Pharo key” abstractions and then map them on to the platform. Something like the meta keys in X-windows. Your keymappings would refer to qualifiers abstractly as “logical key qualifiers” and you could determine your preference for which qualifier key actually represents the logical qualifier. I made several attempts at this and failed. Frankly this was probably because I was focused on X-windows which has its own mapping layer. I think it could be sorted out and would be happy to help. I think that there should be some general discussion about other application needs regarding keyboard events, though, so we don’t proceed to walk all over every one.

    1. Hi David. Wow, I didn’t know that you wrote the original version of Keymappings. Thanks for all the background. Yes, as long as I could see it looks like they have been pushing Keymappings a bit more.

      I completly agree with 2) and I think that’s the most complicated part. I hope that in the future we can have a VM that delivers event that way. But such part of the system goes beyond my knowledge right now 🙁

      I will forward your answer to Guillermo Polito. Thank you very much.

  2. Keymapping on iOS/iPad with a bluetooth keyboard is what I’ll be working on over here. Now that I have the VM working, this will be very useful. (As the current thing uses touches to achieve results and the onscreen keyboard eats a lot of space, making the UI close to unusable (the virtual keyboard hiding the world menu for example).

    1. I am glad you could compile the VM. If there was something extra you should do, maybe you can write a blog post about it? so that other can do it as well 😉
      Regarding Keymapping don’t hesistate to ask the pharo mailing list since Guille is always around

Leave a Reply