Geertjan's Blog

  • March 22, 2007

Getting Further Into Groovy

Geertjan Wielenga
Product Manager
A lot of things are simple in Schliemann (which is the brand new NetBeans approach for the declarative creation of editor features, as described on the project page here) or, at least, a lot simpler than before. Other things are still pretty hard. The hardest thing I've yet encountered in Schliemann is code folding. But that was already hard before, so there's no change there. :-) It is hard because you need a grammar, and the grammar has to cover everything in your file, not just the pieces that require code folding. But I'll leave that for another day. The good news is that I've been very pleasantly surprised by, especially, hyperlinking and code completion. I haven't completed either of them for Groovy, but have come quite far.

First, the initial screenshot below is interesting. It shows Groovy syntax coloring and code completion, as well as a Navigator for jumping to relevant parts of the code. The way I implemented it for Groovy, the Navigator lists all the components and properties that it identifies in the current document, and clearly distinguishes between them, and then you can scroll through the list, select an entry, and click it. If the document is closed, it opens when you click the entry. Either way, the cursor lands at the entry in the opened document.

And this is literally everything I had to do to create that functionality:

NAVIGATOR:swingCompProps: {
icon: "/org/netbeans/modules/languages/resources/method.gif";
display_name: "<html><b><font color=000099>PROPERTY:</font></b> <font color='green'>$identifier$</font></html>";
NAVIGATOR:swingComps: {
icon: "/org/netbeans/modules/languages/resources/class.gif";
display_name: "<html><b><font color=000099>COMPONENT:</font></b> <font color='red'>$identifier$</font></html>";

Next, code completion. I like how code completion works in Schliemann. Again, though, (i.e., as I started discovering yesterday with NBS files) it seems that you need to predefine everything, this time in an XML file. Somehow I think I'd prefer having the code completion entries generated at runtime. But maybe I'm wrong. Anyway, code completion isn't completely complete, but below you can see it in action over the 'button' component. Finally, I implemented syntax coloring for most of the syntax, helped by Jim Clarke from the Groovy list and also from Sun, who sent me code for generating the Swing component properties (however, again I wonder whether these shouldn't be generated on the fly). So, right now, this is how my Groovy editor looks (the 'Design' view doesn't contain anything, just a placeholder for some kind of drag and drop interface that I am hoping to implement):

But that's not all. There's also hyperlinking. You can hold down the Ctrl key and then move the mouse over one of the Swing components, as shown here (the 'textField' is underlined in red below because I am holding down the Ctrl key while moving my mouse over it):

Then you click the link and the browser registered in the IDE opens, if it is closed, or receives focus, if it is already open. Then the applicable Javadoc page for the Swing component under the cursor is found and displayed in the browser. (And if you install Rich's JDIC browser from https://jdic.dev.java.net/, the Javadoc will open inside the IDE.) Hyperlinking has really massively improved under Schliemann. Here, one can also see (as with code completion) that one does use Java here and there. For these slightly more intricate features, you create a reference in the NBS file and then you implement the feature in Java. So, in my Groovy.nbs file I have this declaration:

HYPERLINK:swingComps: org.netbeans.modules.groovyschliemann.Groovy.hyperlink

This declaration says: "For the token named 'swingComps', provide hyperlinks by using the 'hyperlink(Context)' method in the org.netbeans.modules.groovyschliemann.Groovy class."

By adding that declaration to my NBS file, the current context is sent to the 'hyperlink(Context)' method, where a hyperlink is created to a specified destination. And this is my extremely simple implementation of the hyperlink, in this case for Groovy:

public static Runnable hyperlink(Context context) {
if (!(context instanceof org.netbeans.api.languages.SyntaxContext))
return null;
//Not sure what's going on here exactly,
//but this retrieves the name from the reference in the NBS file:
org.netbeans.api.languages.SyntaxContext scontext = (org.netbeans.api.languages.SyntaxContext) context;
org.netbeans.api.languages.ASTPath path = scontext.getASTPath();
org.netbeans.api.languages.ASTToken t = (org.netbeans.api.languages.ASTToken) path.getLeaf();
//Here we have a Swing component's name, retrieved from the above three lines:
final java.lang.String name = t.getIdentifier();
if(name.equals("textField")) {
newName = "JTextField";
} else {
newName = "JButton";
} // else { and so on... some way of mapping SwingBuilder to Swing classes... probably a map.
//Here, in a separate thread, we open the related Javadoc
//in the default browser:
return new Runnable() {
public void run() {
try {
showURL(new java.net.URL("http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/" +
newName + ".html"));
} catch (MalformedURLException ex) {

Now compare the above code to the code in the Hyperlink Navigation Tutorial (code similar to that found in this tutorial will also be in the forthcoming book). Notice how much simpler Schliemann makes hyperlinking! And all of the above code I learned from reading the JavaScript.nbs file in the NetBeans sources. Also the NBS.nbs file is really useful.

Finally, for today, as shown earlier, I can drag and drop the individual Groovy documents out of the IDE (just like any other document in 6.0) and work with them separately:

For documents that are separated from the IDE, as shown above, the Navigator continues to work. The Navigator shows the entries for whichever document currently has focus, which could be a document far outside of the IDE. The Navigator itself, just like any other window in 6.0, can be extracted from the IDE in this way. When you close the IDE and reopen it, the separated windows are still separated; in other words, the undocked state is persisted across restarts.

About Schliemann, my current main issues are about grammar (needs to be a visual way of designing grammar or there needs to be a way to generate it from 'antlr' files and 'JavaCC' files, and so on). Without grammar, no code folding. My other issue is that I have all these hard coded tokens which seems not very maintainable. It implies I need to change the NBS file whenever new classes/properties are added to the JDK. There's got to be a more dynamic way of working with Schliemann. Aside from these issues, I'm really impressed. Without any documentation, purely from reading the (very readable) NBS files that are already out there, one can extrapolate a lot of interesting information.

In other news. Do you write modules on top of NetBeans? Do you know about a document called "NetBeans API Changes since Last Release"? No?! That's not good! You better start reading it here. There is a LOT of information there and whenever someone makes changes/improvements to the NetBeans APIs, they are supposed to keep this document updated. You should check it regularly to make sure you're aware of the latest changes. I recommend you check it once a week, over a hot cup of morning coffee, together with a bagel and a brownie.

Join the discussion

Comments ( 12 )
  • Peter Thursday, March 22, 2007
    Can you provide sources to this module? I'd like to try it out myself and start tinkering with it.
    Peter Knego
  • Geertjan Thursday, March 22, 2007
    Cool. I will try and set up an open source project today and put everything in there. Tomorrow I'll describe the structure of the modules. (Because there's more than one, I'm trying to keep the modules small.) Remember, though, that all this functionality is completely new and fresh, and therefore quite fragile. However, if you work through the Hello Schliemann story, you'll see what the basic concepts consist of.
  • Peter Thursday, March 22, 2007
    Thanks Geertjan. I just started reading the pre-release of your new book, trying to grasp the innards of NetBeans. Interesting read I must say. However I don't see any mention of the Schliemann in it.

    Are there any plans to have a section/chapter on the subject in the final release of the book? I'm trying to understand how Schliemann works. As I understand it's a factory that produces Lexer, etc.. classes automatically based on .nbs file. It would be interesting to know what Schliemann produces and what are the limits to this production e.g. what functionality can be implemented with it.
  • Geertjan Thursday, March 22, 2007
    Afraid not, Peter. We only discuss stable APIs in the book and Schliemann is so raw that its bleeding. :-) It was just introduced into the development builds of NetBeans a week or so ago, so it will not even get a mention in the book, which is currently at the publisher waiting to get published. By the way, Schliemann is not a factory that produces Lexer. The questions you ask are all answered in the blog I referred you to (here) and in the links at the top of that blog entry. Please read it. It will then make more sense to you.
  • Caoyuan Deng Thursday, March 22, 2007
    Hi, Geertjian.
    I just done some works of an Erlang Editor module based on Schliemann, it looks like:
    I'd like to contribute it to NetBeans Community and polish it continually.
  • Prem Kurian Philip Thursday, March 22, 2007
    Thanks a lot for your blog and for the detailed entries that you make to the blog. Yours is one of the most informative/educative blogs I have seen. I really appreciate the effort you have taken to be as clear and precise as possible.
    Thanks again,
    Prem Kurian Philip
  • Sandip Thursday, March 22, 2007
    Caoyuan Deng,

    Can you share with us how you went about creating the grammar rules in NBS file for erlang? Did you have a grammar in JavaCC and ANTLR form and use some tool to transform it to NBS required format?

    I find that writing grammar is the hardest part of creating the NBS.

  • Geertjan Friday, March 23, 2007
    Sandip, I have asked Caoyuan Deng to do an interview with me about exactly these questions. I am hoping to really ask him the questions that have been popping up in my own mind about Schliemann recently. His result is really impressive -- see the link to his blog in his comment above -- so potentially there is a lot to learn from him. Finally, thanks Prem Kurian Philip, for your comment. What kind of development work do you do, would be in interested in hearing your experiences.
  • Caoyuan Deng Friday, March 23, 2007
    Hi Sandip,
    Actually I'm new to compiler principle, but I quickly found that Schliemann only support LL(k) form currently, so the normal JavaCC/ANTLR form may not be transform to NBS automatically. I had to modify a yacc like Erlang grammar definition(LALR) to fit the LL(1) rule.
    I'll share my experience on how I did the transform.
  • Jesse Glick Thursday, April 12, 2007
    By the way, I have added an Atom feed for NB API changes.
    doesn't have it yet, but I wouldn't rely on that anyway; it hasn't been built in a week! But
    gets built regularly and the feed seems to work from there, at least in Thunderbird. (I am not very experienced with feed formats so there may be problems on some clients. Patches to nbbuild/javadoctools/export2apichanges-atom.xsl would be gratefully accepted.)
  • goodscape Tuesday, May 1, 2007
  • Francisco Laborde Friday, January 16, 2009

    I am currently trying to create a new C-like language with code completion. So far I have tried using the COMPLETION keyword but whenever I use it with whitespace the completed word appears incomplete.

    I am also having trouble creating semantically-aware completion (for example, give declared int variables where an int variable is expected).

    Could you point me to a tutorial or to some documentation which could point me in the correct direction to implement code completion?


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.