Tag Archives: Keymappings

Nautilus: the reborn of the SystemBrowser?

I have always had a problem regarding Pharo: how to help/collaborate with its developement while still be as much productive as possible? The thing is that to help you usually need to work with the bleeding edge. To help, an easy way is to just use it and report/fix the problems you find while doing so. But I cannot use an image where I am not productive. So…how do I manage this? Since Pharo 1.0 to 1.3 (or so) I tried to always keep updated the Metacello configurations of the development tools I needed and sometimes even try to update myself the code of such tools. Second step was to at least, automate all my image building so that I could spend less time on in.

The tools I always need are: a nice browser with refactoring integration, OCompletion and Shout. So far, I have always been used OmniBrowser (a.k.a OB), and sometimes O2. The main problem with them is that their main developers are usually one version behind the Pharo bleeding edge. Say we are now in the development of Pharo 1.4, OB developers will likely update OB to work with Pharo 1.4 only when it is released, but not before. Therefore, it doesn’t solve my problem of trying to help Pharo yet have an environment where I am productive.

Luckily, Benjamin Van Ryseghem is solving my problem 🙂  He has been working a lot in a new browser called Nautilus. I really recommend you to give it a try. Just spend 5 minutes on it. There is a Pharo By Example chapter about Nautilus on the way which you can download from here.

Installing Nautilus

You can get a working image with it from Jenkins. Otherwise you can take the latest Pharo 1.4 image and try to execute the following:

Gofer it
url: 'http://ss3.gemstone.com/ss/Nautilus';
package: 'ConfigurationOfNautilus';
load.

(Smalltalk at: #ConfigurationOfNautilus) perform: #loadRelease

That will load Nautilus together with the refactoring engine and OCompletion (the default code completion in Pharo images). If you just want Nautilus and RB, then you can use #loadRefactorings and if you just want Nautilus alone, just use #loadDefault.

My point of view about Nautilus

I have been using it since a couple of days already and I would like to share the nice things I found.

Infrastructure

  • The first thing is that it works in bleeding edge of Pharo 1.4. I hope that in the future Nautilus continue to be update at the same time than Pharo, so that I can always use Nautilus in the bleeding  edge of Pharo.
  • Not only it works in Pharo 1.4, but also it is based on the new tools of it, such as Ring (a model infrastructure for Pharo), RPackage (a replacement for PackageInfo and friends) and KeyMappings.
  • It has integration with Refactoring Engine, KeyMappings, OCompletion, Shout and SUnit.

Usability

  • Nice “Hierarchy” view. Maybe the first time it looks strange because it swaps the panes of the packages and the classes. But there are several reasons for that.
  • Since I use Metacello to load/update projects, the 90% of my usage of Monticello Browser is to commit or view changes. Once you have modified a class, the icon of the package turns red in Nautilus. From within the icon, you can click and it directly opens a Monticello Browser so that you can commit 🙂  But…if you are lazy like me, there is even an option in the menu “Commit in ” -> select the repo.. and that’s all! You don’t even need to go to Monticello Browser to commit 🙂  And of course, there is also an option for “Changes With”.
  • Environments aware browsing: you can select a class or a package, right click -> “browse restricted”. That will open a new Nautilus browser where the scope is limited to the class/package you have selected. So now for example if you search for senders or do a refactor, I will only do it in that scope. This is similar to OB’s refactoring scopes.
  • The refactorings are grouped and adapted for each pane (package, classes, protocols and methods).
  • Integration with SUnit: you can run tests from the browser. You can select one test method in particular, a class or a whole package. It also has rounded icons to see whether they have failed or not (the icon can be black when the test was not run,  green or red).
  • When you browse a package, you also see (in gray) the classes that have extension methods of that package!
  • There is no confusion about with refactor and without refactor. For example, previously with OB, you have the default “rename” which was not a refactor…just rename it. Then to real rename it (and update references) you needed to go to the refactoring. I found this confusing, mostly for newcomers. Nautilus clarifies that.
  • Finally, resizable panes (columns)!
  • Clear button names. For example, instead of “?” now comments are in the button “Comments”.

Educating people

  • Long methods have a yellow background and very long ones red 🙂  That tells you something!
  • There is a special icons for not commented classes and you are even able to click in the icon to edit the class comment

Extensivility

  • It is easy to add your own menu entries and shortcuts.
  • Plugins architecture: like Firefox, Eclipse, etc., you can write your own plugins for Nautilus! For example, I like Igor plugin 🙂  it shows for each method the timestamp of the current version of the method.

 “New” stuff

  • Nice concept of Groups. You can create groups, where you give them a name and then you can add classes, methods or protocols to them. Then you can browse those groups and see only those items you have added. There are also some automatic/smart groups such as “Most Viewed Classes” and “Last Modified Classes”.
  • Multiselection list!!! Yes, finally 🙂  The browser has the infrastructure for a multiplelist, so you can multiselect classes, protocols, methods, etc. Not all “actions” of the normal menu applies to multiselection. Some others would require some changes in the core of Pharo. Nonetheless, what matters is that at least the browser now supports that. As an example, you can select several methods, and remove all of them altogether.

My conclusion

I have to admit that so far I am loving Nautilus. One of the things I really like is that Ben is not only developing Nautilus but also he is improving Pharo in the way. You can check, for example, the Spec project. I also like the fact of using the latest infrastructure of Pharo such as Ring, RPackage, KeyMappings, etc. Finally, I have to remark the incredible good actitutude of Ben, its author. If you have feedback, wishes, ideas, bugs or whatever, do not hesitate to let him know. In my case I have reported him like 15  ideas and they were all implemented in the same or next day 😉  You can just drop an email in the Pharo mailing lists or directly create an issue in the Pharo bug tracker (there is a specific type for Nautilis). Thanks also for ESUG, Stef or all other who have pushed this project.

To sum up, I have migrated all my images to work with Pharo 1.4  and Nautilus.

Here you have a screenshot:


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.

Keymapping

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
<keymap>
(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.
^window

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';
load.

(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.