<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3283609923804350642</id><updated>2012-02-16T11:07:22.594-08:00</updated><title type='text'>Tor Norbye's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default?start-index=101&amp;max-results=100'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>341</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6736062349551433697</id><published>2010-11-18T17:05:00.000-08:00</published><updated>2010-11-22T11:45:12.608-08:00</updated><title type='text'>Building the Android IDE Tools</title><content type='html'>Do you want to try bleeding edge builds of the Android IDE tooling? No problem. We do all the tool development directly in a &lt;a href="http://android.git.kernel.org/?p=platform/sdk.git;a=summary"&gt;public git repository&lt;/a&gt;. Just build it, run it, and you can see all daily progress in our &lt;a href="https://review.source.android.com//#q,status:closed+project:platform/sdk,n,z"&gt;review tool&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Andy Rubin recently &lt;a href="http://twitter.com/#!/Arubin/status/27808662429"&gt;tweeted how to build Android&lt;/a&gt;&amp;nbsp;- and as you can see, it's easy and the instructions fit within the 140 twitter character limit.&amp;nbsp;However, if you want to work on the IDE tooling itself, there are many other tips and tricks to know about. The purpose of this blog entry is to document how you can set up an environment to build the Android SDK, including the IDE support, and have everything configured such that you can run and debug the Android support directly from within the IDE.&lt;br /&gt;&lt;br /&gt;My hope is that some of you, once you have the Android tooling up and running, will decide to look under the covers, tinker with the bits, and hopefully find and fix bugs, or even contribute features! I'll talk more about contributions in a later blog post; today the focus is on building and running the bits even if you have no intention of contributing. Even bug reports from you on newly developed features would be useful.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Setup&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First, you'll need to install the prerequisites for your platform. This means you'll have git, a C compiler, etc. There are quite a few steps here, and it's all platform dependent, so I'll just point you to the official build instructions where we have detailed instructions: &amp;nbsp;&lt;a href="http://source.android.com/source/download.html"&gt;http://source.android.com/source/download.html&lt;/a&gt;&amp;nbsp;. &amp;nbsp;If you're on a Mac, pay particular attention to the instructions on creating a case sensitive filesystem image. When I started I glossed over that part and hurried down to the git checkout command, only to discover later that I had to start over.&lt;br /&gt;&lt;br /&gt;One other Mac specific tip, which isn't in the main Android page yet, is that Apple's recent JDK update "broke" the Android build on Snow Leopard since the build uses JNI. The location of the JNI header file changed or disappeared with the JDK update, so you now need to go to Apple and get the developer SDK, JavaDeveloper.pkg from&amp;nbsp;&lt;a href="http://connect.apple.com/"&gt;http://connect.apple.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NOTE NOTE NOTE:&lt;/b&gt;&amp;nbsp;&lt;a href="http://twitter.com/#!/droidxav"&gt;Xavier&lt;/a&gt; tells me that building on Windows is more difficult because the SDK itself doesn't build on Windows, so you may have to download a system image and then build the tools components themselves manually. Hopefully I'll be able to provide more details on this soon.&lt;br /&gt;&lt;br /&gt;Once you have everything configured, check out the source code using the first half of Andy Rubin's tweet:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ mkdir android&lt;br /&gt;$ cd android&lt;br /&gt;$ repo init -u git://android.git.kernel.org/platform/manifest.git&lt;br /&gt;$ repo sync&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;During the repo init command, it will ask you for your name and e-mail address; these will be used later if you decide to check in changesets and upload them for review.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Build&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now you are ready to build. While you could just type "make", this is where our SDK build instructions diverge a bit.&lt;br /&gt;&lt;br /&gt;In a bash shell, run these commands&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ . build/envsetup.sh&lt;br /&gt;$ lunch sdk-eng&lt;br /&gt;$ make sdk&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ ./sdk/eclipse/scripts/create_all_symlinks.sh&lt;/span&gt;&lt;br /&gt;That will run for quite a while and build everything. It will also create a lot of symlinks to help you edit and compile files within Eclipse.&lt;br /&gt;&lt;br /&gt;Next, configure Eclipse. We support Eclipse 3.4 and up, but we're currently using Eclipse 3.5.2 for development. Make sure you get a version with RCP support, such as the "Eclipse for RCP and RAP Developers" distribution. I'm using eclipse-rcp-galileo-SR2-macosx-cocoa. (You &lt;b&gt;can&lt;/b&gt;&amp;nbsp;use Eclipse 3.6.1 - I just tried it. However, the test project won't compile. You won't need that project to run the Eclipse support. If you're going to be making changes you'll want to have it, but for now, if you're just wanting to try the new support and don't want to install an older Eclipse, go right ahead, and skip the "tests" project in the projects-to-import list below.)&lt;br /&gt;&lt;br /&gt;To configure Eclipse,&amp;nbsp;right click in the Workspace and choose "Import...", then select "Existing Projects into Workspace". &amp;nbsp;You want to import precisely these projects:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sdk/eclipse/plugins/com.android.ide.eclipse.adt&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sdk/eclipse/plugins/com.android.ide.eclipse.tests&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sdk/eclipse/plugins/com.android.ide.eclipse.ddms&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sdk/ddms &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;(import all 3 projects -&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ddmlib,&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ddms-plugin,&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ddmuilib&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sdk/ide_common&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sdk/androidprefs&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sdk/sdkstats&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sdk/layoutlib_api&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Things won't compile yet, until we finish the configuration.&lt;br /&gt;&lt;br /&gt;Go to the Preferences panel, search for Classpath Variables, and define ANDROID_SRC pointing to the top of your source tree (e.g. the "android" dir in the tweet instructions).&lt;br /&gt;&lt;br /&gt;Then right click on the ddmuilib project and open its properties. Go to&amp;nbsp;Java &amp;gt; Build Path, and open the User Libraries tab. You should see ANDROID_JFREECHART and ANDROID_SWT as libraries there. These will need to be configured. For ANDROID_JFREECHART, select the library and click on Add Jars, then point to&amp;nbsp;prebuilt/common/jfreechart and add all 3 jars. For ANDROID_SWT, add the 3 jars&amp;nbsp;under prebuilt/common/eclipse, as well as the architecture specific version - for my Mac it's prebuilt/darwin-x86/swt/swt.jar but this will depend on your OS and architecture. (When I used Eclipse 3.6 I couldn't just add the jars from this dialog, I had to go and open the User Libraries panel and there I could define libraries named ANDROID_JFREECHART and ANDROID_SWT.)&lt;br /&gt;&lt;br /&gt;Voila -- now all the errors in the Problems view should disappear! (There are still quite a few warnings.)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Run and Debug&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The next step is to add a run configuration so you can run and debug the ADT. Hit the Run button. When it asks you what to run it as, choose "Eclipse Application".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Important&lt;/b&gt;: Open the Configurations panel and edit the new configuration. In particular, go to the "Plug-ins" panel, and uncheck the third or so item, &amp;nbsp;"com.android.ide.eclipse.tests". If you enable it you can run into some very subtle bugs where jars from the test module's classpath are accidentally conflicting with different versions of jars in the tools plugin. I wasted nearly a day on that issue...&lt;br /&gt;&lt;br /&gt;If you're on Mac and you get "java.lang.UnsatisfiedLinkError: Cannot load 32-bit SWT libraries on 64-bit JVM", you need to add "-d32" as an argument to the VM.&lt;br /&gt;&lt;br /&gt;You should now be able to run the ADT - it will invoke a second instance of Eclipse, where all the Android tooling is baked in. The first thing you need to do is point the tool to a version of the SDK. Open the Preferences panel, and in the Android panel go to the text field where you can point to an SDK root. If you have downloaded versions of Android in the past, you can point to the root containing all of the different platforms here. However, you don't have to -- when you ran "make sdk" earlier you built a trunk version of the Android SDK (from here on referred to as "AOSP", which I think stands for Android Open Source Project). &amp;nbsp;Therefore, you can point to your build output here -- and as you continue pulling down new changes and rebuilding the SDK, your Eclipse target will also use the latest and greatest.&lt;br /&gt;&lt;br /&gt;To point to it, use &amp;lt;your tree&amp;gt;/out/host/darwin-x86/sdk/android-sdk_eng.tnorbye_mac-x86/&lt;br /&gt;&lt;br /&gt;That exact path will &lt;b&gt;not&lt;/b&gt;&amp;nbsp;work for you, since it has various architecture and user names in it. So open the file chooser and drill down, first to out, then host, then your os and architecture, then sdk, and then some directory which contains "android-sdk_eng", your username and your platform. &amp;nbsp;Hit OK.&lt;br /&gt;&lt;br /&gt;After a brief pause you should now see a platform listed in the listbox in the Android panel, and it will identify itself as version "AOSP". If you instead point to officially released versions of Android, you'll see versions like "5", "6" and "7". The reason we don't use a number for the trunk version is to prevent you from accidentally building an app compiled against this trunk version, and then releasing it on the market.&lt;br /&gt;&lt;br /&gt;Now that you have your Android versions configured, you can create a new Android project. Do New &amp;gt; Android Project, and in the New project dialog, you need to go and choose the AOSP platform in the platform listbox. &amp;nbsp;Fill out the dialog. The only trick is that it asks you for a "Min SDK Version", and here you should again type "AOSP". &amp;nbsp;You can now go and try for example the Layout Editor, by opening res &amp;gt; layout &amp;gt; main.xml.&lt;br /&gt;&lt;br /&gt;We're working actively on the layout editor, but as you can see we could use help in lots of areas, from feature development, to icon work, to bug fixing, to bug reporting! (Again, I'll talk more about contributions in a follow-up post.)&lt;br /&gt;&lt;br /&gt;To stay up to date, just go to the command line, type "repo sync", wait for a while, and then redo the make steps (source build/envsetup.sh, lunch sdk-eng, make sdk, create_symlinks), and reopen Eclipse and rebuild all. If you get a build error, you can wipe out the entire out folder to build from scratch, but I rarely have to do that.&lt;br /&gt;&lt;br /&gt;You can add additional Android platforms, such that you can choose which platform to use for WYSIWYG rendering (just like you can already switch theme, orientation, etc):&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_PkzBdpmSG-Y/TOWqhkExeCI/AAAAAAAAdgY/c2wd9rMIhn8/target-selector.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_PkzBdpmSG-Y/TOWqhkExeCI/AAAAAAAAdgY/c2wd9rMIhn8/target-selector.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is a new feature added just in the last couple of days. It lets you target older platforms but visually work with newer platforms, and quickly switch between them to see how your layout looks on different platforms. &amp;nbsp;Of course, to use this you need to point your root Android tree to an install containing multiple platforms.&amp;nbsp;If you &lt;b&gt;do&lt;/b&gt; add additional platforms, make sure you copy older platforms (android-6, android-7, etc) into the platforms/ folder of the newly built SDK, rather than the other way around. This is necessary because the directory structure changed recently.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Edit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now that you can build and run, let's take a look at the source code. The main Eclipse project to look at is the "adt" project, which is the Eclipse plugin.&lt;br /&gt;&lt;br /&gt;First, you can configure your editor to use our custom dictionary to help the spell checker recognize words that are in our comments but are not in the default Eclipse English dictionary. &amp;nbsp;Search for Spelling in the options dialog, and add&amp;nbsp;sdk/eclipse/dictionary.txt as the "User Defined Dictionary" path.&lt;br /&gt;&lt;br /&gt;Second, if you will be doing any editing of the source code, make sure you configure your editor to use our formatting preferences and our import order. Open the Java Code Style dialog, and for the formatter, import&amp;nbsp;development/ide/eclipse/android-formatting.xml&amp;nbsp;. For Organize Import, import development/ide/eclipse/android.importorder . The code style for the Android source code base is document in&amp;nbsp;&lt;a href="http://source.android.com/source/code-style.html"&gt;http://source.android.com/source/code-style.html&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;***&lt;br /&gt;&lt;br /&gt;That's it! You should now be able to get the source code, build, edit, run and debug the Android IDE tools!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6736062349551433697?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6736062349551433697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/11/building-android-ide-tools.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6736062349551433697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6736062349551433697'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/11/building-android-ide-tools.html' title='Building the Android IDE Tools'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_PkzBdpmSG-Y/TOWqhkExeCI/AAAAAAAAdgY/c2wd9rMIhn8/s72-c/target-selector.png' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-260200141859763720</id><published>2010-10-15T11:11:00.000-07:00</published><updated>2010-10-15T11:14:24.983-07:00</updated><title type='text'>Android</title><content type='html'>I'm now working on Android!&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TLiYGTUrK5I/AAAAAAAABhE/yYjEZVMLfa4/android.png" align="right" /&gt;&lt;br /&gt;&lt;br /&gt;In particular, I'm working on tooling for Android. That means I get to work fully in open source again which I enjoyed in the NetBeans days. We use the public Android git repository and I submit&amp;nbsp;&lt;a href="https://review.source.android.com//#q,owner:tnorbye,n,z"&gt;my fixes&lt;/a&gt;&amp;nbsp;into the Gerrit code review tool which is a really nice workflow tool for git; I highly recommend it.&lt;br /&gt;&lt;br /&gt;As you may or may not know, the Android tooling is Eclipse based, so I'm learning both to use Eclipse as well as writing plugins for it. There are some things I'm missing from NetBeans, but there are also some new features I'm welcoming. I just need to rewire my motor reflexes for it all to feel natural!&lt;br /&gt;&lt;br /&gt;In the past when I've posted NetBeans tips, many of you have helpfully listed the corresponding Eclipse (and IntelliJ) shortcuts. While I have found replacements for many of the features I'm used to, I'm still stumped with the following, so if any of you could enlighten me - either with existing keybindings or optional plugins, I would appreciate it:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Most important: How can I, via the keyboard, navigate through my matches in the Find Usages search? This was my favorite keystroke in NetBeans (and I had meant to do a code tip about it) - if you press Cmd-period, you can navigate through find usages searches, build errors, diff view differences, etc. In Eclipse there is also Cmd-period, but it only works if the Search window has focus - and it doesn't work in the Diff view. (In fact, Cmd-period doesn't work in the Search window on the Mac; I don't know why, because it's listed as the shortcut, and Cmd-period does work in the editor view to navigate parsing errors. Luckily I've found the workaround of Cmd+Shift+period which navigates backwards, so I'm using that one, but I still have to give the Search window focus.)&lt;/li&gt;&lt;li&gt;When I select a symbol in the editor, all the occurrences (of the same variable, class, method, etc) are highlighted. In NetBeans I could navigate through these via a shortcut. Is there a way to do that in Eclipse? (Somebody told me that I could select the text and then use Cmd-k to navigate, but that's text-search based and will jump to unrelated symbols that happen to be the same string, e.g. the same parameter name in a different function).&lt;/li&gt;&lt;li&gt;How can I, via the keyboard, see the light bulb text? Sometimes I get a light bulb in the editor margin trying to tell me something. I have not found a way to see what it's saying other than hovering over it with the mouse. In NetBeans, Alt+Enter would show the light bulb text above the current line as well as the quickfix suggestions below the current line. In Eclipse I know I can press Cmd-1 to see the suggestions, but it doesn't show what the warning is and sometimes it isn't obvious from the suggestions what the problem is. &amp;nbsp;(For example, for an unused variable the suggestion is "Remove x").&lt;/li&gt;&lt;li&gt;I'm really missing the NetBeans version control view (the one which lists the "status"; all your changed, added, and removed files and made it trivial to walk through and diff them). Maybe this is just because I'm working with git and there isn't a plugin which offers that view yet?&lt;/li&gt;&lt;li&gt;This is minor, but when I initiate instant-renaming, it doesn't select the text, which NetBeans did, and I prefer that (so I can hit rename and type the new name). Is there a way to configure it to do that?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;These are the answers I've asked some Eclipse users about and still haven't learned the answers to. One question I &lt;i&gt;did&lt;/i&gt;&amp;nbsp;ask, and eventually found the answer to is how to navigate files similar to NetBeans' Ctrl-Tab feature. The reason I'm bringing it up is that only one person finally showed me the right feature but most people didn't know about it - so if you're an Eclipse user, maybe you'll find this useful: "Next Editor". It's bound to something I can't remember in Eclipse, but I rebound the action called "Next Editor" to Ctrl-Tab (since Cmd-Tab is the equivalent application-switch shortcut on the Mac). You can press it to jump between two files - but the key thing is that when you're jumping between more than two files you can keep holding the Ctrl key after typing Tab to see a dialog of your recently edited files in most-recently-edited order. &amp;nbsp;I find this more intuitive than the jump-between-editing-locations since sometimes I jump to a file, look for something (without editing) and then I want to go back.&lt;br /&gt;&lt;br /&gt;Anyway, I'm having a great time. I love working on tools, and perhaps even more, Android!&lt;br /&gt;&lt;br /&gt;(By the way, if there are any SWT mavens out there, I would love an answer to &lt;a href="http://stackoverflow.com/questions/3908290/mousedown-events-are-not-delivered-until-mouseup-when-a-drag-source-is-present"&gt;this question&lt;/a&gt; which I posed on StackOverflow. If you know the answer but don't have or want to have a Stackoverflow account, feel free to post it here and I'll link back to it.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-260200141859763720?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/260200141859763720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/10/android.html#comment-form' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/260200141859763720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/260200141859763720'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/10/android.html' title='Android'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TLiYGTUrK5I/AAAAAAAABhE/yYjEZVMLfa4/s72-c/android.png' height='72' width='72'/><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-9099990951938094882</id><published>2010-09-27T06:05:00.000-07:00</published><updated>2010-09-27T06:05:42.395-07:00</updated><title type='text'>Next Chapter</title><content type='html'>Today I'm starting in a new job at Google! I'm not sure what I'll work on yet, but I certainly have some strong preferences!&lt;br /&gt;&lt;br /&gt;Google seems to be open to employee blogging, so hopefully I can continue writing about work related topics. And I realize I've forgotten to finish my IDE tips "series" - I have a few more tips that I planned to cover so I'll try to get around to that soon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-9099990951938094882?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/9099990951938094882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/09/next-chapter.html#comment-form' title='28 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/9099990951938094882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/9099990951938094882'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/09/next-chapter.html' title='Next Chapter'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>28</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-624671715528708015</id><published>2010-09-24T10:01:00.000-07:00</published><updated>2010-09-24T10:41:03.274-07:00</updated><title type='text'>System.exit(0)</title><content type='html'>It's time for a new adventure!&lt;br /&gt;&lt;br /&gt;&lt;img align="left" src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJy4ObY-qtI/AAAAAAAABgg/P_692h3FHSs/badge.jpg" style="margin-bottom: 5px; margin-right: 5px;" /&gt;&amp;nbsp;I joined Sun in 1996 and I've been here ever since -- including the Oracle acquisition six months ago.  It's been a wonderful time. I've met many of the world's most talented engineers, I've had the chance to work on some interesting projects and I've learned a lot! I looked at my badge that I'm about to turn in (picture on left) and it has the original photo taken when I joined -- and I look like a kid!! &lt;br /&gt;&lt;br /&gt;However, it's time to move on. I've chosen to take a new opportunity where I'll get to have even more fun. For now, I'd like to thank all my former Sun and Oracle coworkers for the great experiences you've given me and wish you luck with the future!&lt;br /&gt;&lt;br /&gt;&lt;code&gt;System.exit(0);&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-624671715528708015?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/624671715528708015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/09/systemexit0.html#comment-form' title='33 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/624671715528708015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/624671715528708015'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/09/systemexit0.html' title='System.exit(0)'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJy4ObY-qtI/AAAAAAAABgg/P_692h3FHSs/s72-c/badge.jpg' height='72' width='72'/><thr:total>33</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-7375740705540955712</id><published>2010-09-17T14:31:00.001-07:00</published><updated>2010-09-17T22:57:59.078-07:00</updated><title type='text'>New blog home</title><content type='html'>I've migrated my blog from the old Sun Microsystems blogging site (&lt;a href="http://blogs.sun.com/tor"&gt;http://blogs.sun.com/tor&lt;/a&gt;) to this new home on Blogger. It turned out to be a bit trickier than I had hoped, and as a consequence, there are probably some broken links and some bad formatting here and there. The old blogging platform was based on Apache Roller, and most other blogging platforms don't support import of Roller archives. I first tried to simply set up an account on jroller.com, but they don't allow new users. In case anyone else is trying to make a similar migration, here are some quick notes on what I did:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;I exported from Roller into a MovableType format.&amp;nbsp;&lt;/li&gt;&lt;li&gt;I used the&amp;nbsp;&lt;a href="http://code.google.com/p/google-blog-converters-appengine/"&gt;http://code.google.com/p/google-blog-converters-appengine/&lt;/a&gt;&amp;nbsp;project to convert the movable type file into a file suitable for Blogger import.&lt;/li&gt;&lt;li&gt;However, all the dates were broken; they all showed up with today's date. I tracked this down to the fact that the converter filter assumes the times in the archive are in 12 hour format (with am/pm at the end, and for me they were not.) So I fixed this by replacing the following line in&amp;nbsp;google-blog-converters-r89/src/movabletype2blogger/mt2b.py :&lt;br /&gt;return time.strptime(mt_time, "%m/%d/%Y %I:%M:%S %p")&lt;br /&gt;with&lt;br /&gt;return time.strptime(mt_time, "%m/%d/%Y %H:%M:%S")&lt;/li&gt;&lt;li&gt;The biggest challenge was dealing with the images; the blog converted okay but still referenced all my image resources on blogs.sun.com. To fix this, I first uploaded all my images to picasaweb and made them world writable. Then I looked at the page in picasaweb which shows thumbnails for all the images in the album, and I saved it. This file contains image links. Unfortunately, the images all end up with many different url prefixes, so it's not as simple as just replacing the old image prefix with the new one. I wrote a short Java program to extract all the image links, and create a map from file base name to the full url.&amp;nbsp;&lt;/li&gt;&lt;li&gt;I then wrote a simple Java program to rewrite the Blogger import file such that it replaces all urls of the form http://blogs.sun.com/... with the corresponding new Picasaweb url using the above map. I also took the image urls from the thumbnails and removed the /s128/ portion of the url, which gets you the original image rather than the thumbnail. (Also, it turns out picasaweb insists on converting all .png images and .gif images to .jpg, so the URLs have to adjusted for those cases.)&lt;/li&gt;&lt;li&gt;I also did a little bit of post processing on the results; for example, I collapsed some repeated br tags that are no longer necessary, and I inserted a "This blog entry was imported and urls might be wrong"-warning at the top of each imported post.&lt;/li&gt;&lt;li&gt;One final tip: I discovered that a number of my images were missing. It turns out that Picasa by defaults hides small images (of which I had many) - so these were not uploaded! There are places to both go and enable these as well as adding .gif to the list of included file extensions, so handling this is easy once you're aware of the problem.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Hopefully this helps anyone else wanting to make a similar migration. I have the Java code for the image url manipulation if anyone wants it (but it's not generic so you'll need to do a little massaging for your own needs.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-7375740705540955712?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/7375740705540955712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/09/new-blog-home.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7375740705540955712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7375740705540955712'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/09/new-blog-home.html' title='New blog home'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6155027039078564315</id><published>2010-06-29T16:50:00.000-07:00</published><updated>2010-09-17T13:49:13.142-07:00</updated><title type='text'>Don't Use Implicit Return Types</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;JavaFX, like Scala, is a fully statically typed language. However, unlike Java, it allows you to omit type declarations in many places, since it can infer it. Coupled with the fact that you can use expressions as statements, and that the last expression in a function will be the return value, this lets you write really simple and clear code.&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;def s = "Hello";&lt;br/&gt;def len = s.length();&lt;br/&gt;function product(a: Number, b: Number) {&lt;br/&gt;a * b&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;The function above shows an "Implicit Return Type": The compiler figures out the return type, which in this case will be a Number, and that is the signature computed for the function.&lt;br/&gt;&lt;br&gt;Unfortunately, this can sometimes lead to trouble!  Here's a real-world example:&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;public function clearSelection() {&lt;br/&gt;selected = null;&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;This function clears the selection in a node. The intention of the developer was probably for this function to have a "void" return type. But that is &lt;b&gt;not&lt;/b&gt; the return type! The last statement is an expression, an assignment, which has the type of the left hand side, which is actually a node.&lt;br/&gt;So the return type here is a Node! And it could easily have leaked an implementation class too.&lt;br/&gt;&lt;br&gt;This may not seem like a big deal here, but what if a subclass wanted to override this function?  It would try this:&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;override function clearSelection() {&lt;br/&gt;super.clearSelection();&lt;br/&gt;moreStuff();&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;And this would fail compilation, with a surprising error message:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;File.fx:1: incompatible types&lt;br/&gt;found   : void&lt;br/&gt;required: Node&lt;br/&gt;override function clearSelection() {&lt;br/&gt;1 error&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;That's right, your subclasses will now need to deal with this return type too! If it's an implementation class, they're in trouble!&lt;br/&gt;&lt;br&gt;There are other reasons implicit return types are bad too.  Here's a function specifying a desired padding for a node:&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;public function padding() {&lt;br/&gt;5&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;The user may have intended for this to be a Number, but since the default is "5" instead of "5.0", the implied type here is Integer, which means that subclasses will need to round their desired padding to an integer. And this is not always a good thing - see &lt;a href="http://blogs.sun.com/tor/entry/pixel_considerations"&gt;the pixel considerations article&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;For all of the above reasons, our &lt;a href="http://wikis.sun.com/display/JavaFxCodeConv/Home"&gt;Coding Conventions Document&lt;/a&gt; states that you should not use implicit types, at least not for any non-private API. That includes package, protected and public functions.  However, it's a simple mistake to make. We've all made it! For that reason, to help track these down, I've created a quickfix for NetBeans which identifies and fixes these problems. Here's what happens if you look at a function like the one described above:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOttPQTeoI/AAAAAAAAA90/4VMM6iAVWi0/implicit1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The light bulb and underline warns you that there is a problem here. Clicking on the light bulb, or pressing Alt+Enter when the caret is on that line, shows this info:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOse8xRFBI/AAAAAAAAAyQ/OtT55YUs9uI/implicit2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;It's telling you that you have an implicit return for a public function, and it's offering to insert the actual, current return type of the function. It's also offering to make the function Void.&lt;br/&gt;&lt;br&gt;Pressing return will fix the function:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOriSTZaiI/AAAAAAAAApU/SzSNPuP-36I/implicit3.jpg" /&gt;&lt;br/&gt;&lt;br&gt;There are certain return types you cannot express in JavaFX script - such as returns including generics signatures. The quickfix won't warn about those since there is nothing you can do.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;!--&lt;br/&gt;The quickfix module identifies a different problem too: Public variables that are bound to an expression. The public variable will cause a setter to be created by the compiler, but if anybody actually tries to assign to the property, an AssignToBound exception will be thrown. I can't see any reason why you would want a property that is bound to be a &lt;code&gt;var&lt;/code&gt; instead of a &lt;code&gt;def&lt;/code&gt;.&lt;br/&gt;&lt;br&gt;At first, I had this quickfix only report warnings when you have a &lt;code&gt;public var&lt;/code&gt; instead of a &lt;code&gt;public-read var&lt;/code&gt;, since the chance for damage is much smaller; only code in your own class can cause the assign-to-bound exception since only local code is allowed to assign to the variable. But then I thought there still isn't really any good reason to leave it as a &lt;code&gt;var&lt;/code&gt;; if you make it a &lt;code&gt;def&lt;/code&gt; then the compiler will warn you when you try assigning to it.&lt;br/&gt;&lt;br&gt;Here's the quickfix in action:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtKXTIHzI/AAAAAAAAA4w/TUFTIEyvJeU/bound-var.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Here's the quickfix warning:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrtfWxheI/AAAAAAAAArI/3R2mLyndcZ4/bound-var2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;If you apply the fix it's changed to a &lt;code&gt;def&lt;/code&gt; (and the &lt;code&gt;public-read&lt;/code&gt; is changed to just &lt;code&gt;public&lt;/code&gt;) :&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsF2jaf9I/AAAAAAAAAu4/z_WTQeK15vM/bound-var3.jpg" /&gt;&lt;br/&gt;&lt;br&gt;--&gt;&lt;br/&gt;You can find the module on the Plugin Center &lt;a href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=30077"&gt;here&lt;/a&gt;. Hopefully it will be as useful to you as it has been to me!&lt;br/&gt;&lt;br&gt;P.S. We discussed this topic (implicit return types in JavaFX and Scala) for a while on the latest&lt;br/&gt;&lt;a href="http://javaposse.com/java_posse_312_newscast_for_june_23rd_2010"&gt;Java Posse Podcast episode&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6155027039078564315?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6155027039078564315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/06/don-use-implicit-return-types.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6155027039078564315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6155027039078564315'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/06/don-use-implicit-return-types.html' title='Don&amp;#39;t Use Implicit Return Types'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOttPQTeoI/AAAAAAAAA90/4VMM6iAVWi0/s72-c/implicit1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-108676678308935795</id><published>2010-06-17T15:04:00.000-07:00</published><updated>2010-09-17T13:49:13.122-07:00</updated><title type='text'>NetBeans 6.9 Released</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtdlhGWSI/AAAAAAAAA7Y/nGB46JJ2HcU/NetBeans69New.jpg" align="right"&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;NetBeans 6.9 has been released.&lt;br/&gt;&lt;br&gt;There are important improvements for everyone here - whether you're a Java developer, JavaFX developer, Ruby developer, PHP developer, C++ developer, ... or all of the above :-)&lt;br/&gt;&lt;br&gt;Since I spend most of my time writing JavaFX and Java code, by far the biggest improvement in NetBeans 6.9 for me is the JavaFX support. While there is still room for improvement, editing works pretty well now. In particular, the source code formatter works well on most source files and constructs, so I've used it to reformat some of our large and complicated source files, though to be on the safe side I've checked the diffs carefully before checking in (and turned on whitespace diffing in the version control). I occasionally have to make manual tweaks, but it's really helpful in cleaning up poorly formatted source files.  And Go To Declaration now works reliably! The debugger still needs work. Apparently this needs some help from the compiler so hopefully the combination of JavaFX 1.3.1 and NetBeans 6.9.1 will address that.&lt;br/&gt;&lt;br&gt;One huge improvement in 6.9 is the reduction of scanning delays. In addition to performance fixes in that area, there are two life saver features:&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt; Running is no longer blocked when a scan is in progress. Even if it's scanning, running starts immediately. This used to drive me crazy!&lt;br/&gt;&lt;li&gt; I can turn off some of the extra aggressive scanning! There is an option for this now, so I can turn off automatic timestamp checking and instead perform scanning manually if I should need it:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsXHeyrVI/AAAAAAAAAxQ/v6MfHvFsGRo/scanning-option.jpg" /&gt;&lt;br/&gt;&lt;br&gt;(In case it's not obvious -- I'm talking about the checkbox at the bottom of the above dialog.)&lt;br/&gt;&lt;br&gt;If you turn off automatic scanning, you can invoke it explicitly:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtoQ1Gt8I/AAAAAAAAA9E/ZncVpBunSvI/scanning-menu.jpg" /&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;There are many other new features, and I'll get back to some of them in some other posts, but for now I'll leave you with a link:&lt;br/&gt;&lt;a href="http://blogs.sun.com/tor/resource/org-nbgit-netbeans69.nbm"&gt;Git Plugin compatible with NetBeans 6.9&lt;/a&gt;.&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-108676678308935795?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/108676678308935795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/06/netbeans-69-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/108676678308935795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/108676678308935795'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/06/netbeans-69-released.html' title='NetBeans 6.9 Released'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtdlhGWSI/AAAAAAAAA7Y/nGB46JJ2HcU/s72-c/NetBeans69New.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6605153706284329883</id><published>2010-05-20T10:11:00.000-07:00</published><updated>2010-09-17T13:49:13.095-07:00</updated><title type='text'>LCD Subpixel Rendering</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;While I'm on the topic of &lt;a href="http://blogs.sun.com/tor/entry/pixel_considerations"&gt;pixels&lt;/a&gt; -- here's another tip. This one is both Mac OSX and NetBeans (well, Swing) specific.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Subpixel rendering, an antialiasing technique, makes text look much sharper (&lt;a href="http://en.wikipedia.org/wiki/Subpixel_rendering"&gt;wikipedia article&lt;/a&gt;).&lt;br/&gt;Subpixel rendering was added to Java 6, so the NetBeans source editor looks great on Windows and Linux provided you are running Java 6.  Antialiasing was never an issue on Macs, where the JDK used its own native graphics renderer which had subpixel rendering all along - until now!!&lt;br/&gt;&lt;br&gt;Here's NetBeans on Linux and Windows:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrjcBQHNI/AAAAAAAAApc/qnP1gy0D7wY/lcd-win-linux.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Let's zoom in. Notice the "strange" colors at the perimiter of the font strokes; they look strange here but oh-so-good at the proper resolution on an LCD:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsT0K7QYI/AAAAAAAABV0/gN-G8MCLSBI/lcd-win-linux-zoom.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Unfortunately, when Apple released Java 6 on the Mac, they switched the default graphics renderer over from their own "Quartz" renderer to the standard JDK one. That shouldn't be a problem, since Java already renders LCD text, right?  &lt;b&gt;Wrong!&lt;/b&gt; For reasons I don't know, subpixel rendering is NOT working on the Mac with the standard renderer. Therefore, by default, NetBeans text looks blurry (because it is only grayscale antialiased) on Macs.&lt;br/&gt;&lt;br&gt;This is easy to "fix". Just switch the rendering back to Quartz. You can do that with the following flag, added to the &lt;code&gt;netbeans.conf&lt;/code&gt; config file:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;-J-Dapple.awt.graphics.UseQuartz=true&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;The &lt;code&gt;-J&lt;/code&gt; flag just tells the NetBeans launcher that the rest of the flag is a flag for the Java interpreter, and the &lt;code&gt;-D&lt;/code&gt; flag says set the system property &lt;code&gt;apple.awt.graphics.UseQuartz&lt;/code&gt; to true. Therefore, in your own Swing applications you can do the same thing, just drop the &lt;code&gt;-J&lt;/code&gt; flag.&lt;br/&gt;&lt;br&gt;(The config file is in a place like &lt;code&gt;/Applications/NetBeans/NetBeans 6.9 Beta.app/Contents/Resources/NetBeans/etc/netbeans.conf&lt;/code&gt; and you would add these flags to the &lt;code&gt;netbeans_default_options&lt;/code&gt; line.)&lt;br/&gt;&lt;br&gt;Here is a before-versus-after screenshot; this will only make visual sense to you if you're viewing this on an LCD screen!&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuvzgOeoI/AAAAAAAABFk/glhhl4xUZAg/lcd-mac-compare.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The subpixel rendering text is on the left.&lt;br/&gt;&lt;br&gt;Here's a zoomed in view, which shows the default (non-LCD renderered text):&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr5_LqkeI/AAAAAAAAAtA/ENNMtCkcKHo/lcd-mac-off.jpg" /&gt;&lt;br/&gt;&lt;br&gt;And here's what you get when you turn on Quartz:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOri-6F-YI/AAAAAAAAApY/iitkfW21GiE/lcd-mac-on.jpg" /&gt;&lt;br/&gt;&lt;br&gt;I presume Apple turned off Quartz by default in Java 6 for a reason. Does anyone know what it is? The &lt;a href="http://java.sun.com/javafx/1/reference/releasenotes/javafx-sdk-release-notes-1-3.html"&gt;JavaFX Release Notes&lt;/a&gt; mention some memory leaks. I've been using the flag to turn LCD text back on since I switched to Java 6 on the Mac a year ago, and it doesn't seem to have any adverse effects for normal NetBeans usage (mostly text oriented; I don't do UML editing etc).&lt;br/&gt;&lt;br&gt;More importantly, does anybody know why subpixel rendering from the JDK doesn't work on the Mac since it works everywhere else? Is there a way to trick it to work with rendering hints etc?&lt;br/&gt;&lt;br&gt;&lt;b&gt;P.S.&lt;/b&gt; Speaking of launcher arguments - I have one other customization too.  I add &lt;code&gt;-J-d32&lt;/code&gt;. This tells the JDK that I want a 32-bit VM. I haven't measured personally what this buys me, but I saw that &lt;a href="http://twitter.com/headius/statuses/13329632476"&gt;Charlie Nutter recommended it&lt;/a&gt; for NetBeans usage, and he certainly knows his way about VM tuning parameters!&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6605153706284329883?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6605153706284329883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/05/lcd-subpixel-rendering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6605153706284329883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6605153706284329883'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/05/lcd-subpixel-rendering.html' title='LCD Subpixel Rendering'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrjcBQHNI/AAAAAAAAApc/qnP1gy0D7wY/s72-c/lcd-win-linux.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-964044028475726181</id><published>2010-05-11T06:47:00.000-07:00</published><updated>2010-09-17T13:49:13.079-07:00</updated><title type='text'>Bay Area JUG Roundup 2010</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsC9ucl0I/AAAAAAAAAuU/L2slAqWeGoE/posse-small.jpg" align="right" style="margin-left: 5px" /&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you live in the San Francisco bay area, I hope you can come to the &lt;a href="http://bayareajugroundup.eventbrite.com/"&gt;Bay Area Java User Group Roundup 2010&lt;/a&gt; tomorrow night! It is going to be held at the Oracle conference center, and both beer and dinner will be provided. There will be an update on the java.net migration, and the &lt;a href="http://javaposse.com/"&gt;Java Posse&lt;/a&gt; are going to record a live podcast. Note - you need to sign up in advance so visit the &lt;a href="http://bayareajugroundup.eventbrite.com/"&gt;event details page&lt;/a&gt;.&lt;br/&gt;&lt;br&gt;Hope to see you there!&lt;br/&gt;&lt;br clear="both"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-964044028475726181?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/964044028475726181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/05/bay-area-jug-roundup-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/964044028475726181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/964044028475726181'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/05/bay-area-jug-roundup-2010.html' title='Bay Area JUG Roundup 2010'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsC9ucl0I/AAAAAAAAAuU/L2slAqWeGoE/s72-c/posse-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-4013711933374335223</id><published>2010-05-10T14:10:00.000-07:00</published><updated>2010-09-17T13:49:13.066-07:00</updated><title type='text'>Pixel Considerations</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Antialiasing makes lines and shapes look smooth - though sometimes at the expense of sharpness. What if you're trying to draw a horizontal or vertical line where you don't need antialiasing? You might be under the impression that if you position your shapes at round integer positions, you will avoid antialiasing.&lt;br/&gt;But it's not quite that simple - so avoid trying to be smart with layout code like this:&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: javafx;"&gt;&lt;br/&gt;...&lt;br/&gt;label.layoutX = (width - labelWidth) / 2 as Integer;&lt;br/&gt;....&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;The idea here is that when you're placing something in the middle you might end up with a fractional value, say 42.5, and so you added the "as Integer" to round things to a whole number to avoid introducing antialiasing.&lt;br/&gt;&lt;br&gt;Well, this may have exactly the opposite effect! Take a look at the following picture, which shows two rectangles.  Both rectangles have a stroke width of 1.0, and one of them is positioned at a round integer, and the other one is positioned at 0.5.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtZ8UWi0I/AAAAAAAAA60/eyuObwJZumI/antialiasing1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Here's a zoomed in view which makes things clearer:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOt0iuYAXI/AAAAAAAAA-o/6YKr5vAIpTs/antialiasing1-zoom.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Obviously, the rectangle on the left is blurry because antialiasing is attempting to show the line as being somewhere in the middle between them. The rectangle&lt;br/&gt;on the right on the other hand is clear and crisp because the lines overlap EXACTLY with the pixel grid the line is rendered into.&lt;br/&gt;&lt;br&gt;Here's the thing though:  The rectangle on the &lt;b&gt;left&lt;/b&gt; is the one that was positioned at round integers, and the rectangle on the right is the one positioned&lt;br/&gt;at round integer + 0.5 !&lt;br/&gt;&lt;br&gt;So should you run out and ensure that all your horizontal and vertical edges are positioned at 0.5? No. The key here is the stroke width. Take a look at the following figure, where I have position rectangles with different stroke widths (1, 2, 3) and different pixel positions (0, 0.25, 0.5).&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOs5mZXJII/AAAAAAAAA2I/_IpM3ElhRYg/antialiasing2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Zoomed in:&lt;br/&gt;&lt;/br&gt;&lt;br&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsFcOlqcI/AAAAAAAAAuw/Trb8VNKV4XY/antialiasing2-zoom.jpg" /&gt;&lt;br/&gt;&lt;br&gt;As you can see, whether you match the pixel grid perfectly depends on the stroke width and the pixel positions. This actually makes sense. Think of your pixel grid as having x coordinates at the boundaries of each pixel. In other words, "0.0" is the left edge of the first pixel, and 1.0 is the right edge of the first pixel. The line position has to be the center of the stroke. So if you want to have a line of thickness 1, then that line will run exactly through the pixel, so we must position its center at x=0.5.  When the stroke width increases to 2 however, the center will be in the middle (e.g. 1), and so we should position it at a round number. And so on.&lt;br/&gt;&lt;br&gt;When you're dealing with large shapes this isn't a big deal. But if you're trying to paint a grid (like the one below), a pattern, or small controls (like disclosure arrows - which is how I came to look into this), it can pay off.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOryevLfpI/AAAAAAAAArw/V5wXTkbJfAw/antialiasing3.jpg" /&gt;&lt;br/&gt;&lt;br&gt;By the way -- on OSX there's a nice screen zoom (hold the Option key and then do a two-fingered drag on the trackpad up or down) which makes it easy to zoom in and look at the pixels for anything on the screen. But unfortunately it doesn't show pixels as square, it does more blending, so it's much harder to tell what's going on at the individual pixel level. Get an image editor which lets you zoom in with clear pixel boundaries, or even a screen magnifying lens. Here's how the builtin screen zoom looks - as you can see it's not as clear as the pixel zooms above:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOs5BuGrvI/AAAAAAAABXM/rG6M9571QOM/antialias4.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;b&gt;UPDATE&lt;/b&gt;: Marius taught me in the comments that you can turn off the OSX zoom smoothing in the Universal Access options. Sweet! I can now instantly check the pixels without going to an intermediate screenshot! Thanks!&lt;br/&gt;&lt;br&gt;Finally: &lt;a href="http://jonathangiles.net/blog/"&gt;Jonathan Giles&lt;/a&gt; from the JavaFX controls team has been doing a great job aggregating and summarizing interesting FX articles each week -- highly recommended if you're doing anything with JavaFX.&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-4013711933374335223?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/4013711933374335223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/05/pixel-considerations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4013711933374335223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4013711933374335223'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/05/pixel-considerations.html' title='Pixel Considerations'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtZ8UWi0I/AAAAAAAAA60/eyuObwJZumI/s72-c/antialiasing1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8210502721902740777</id><published>2010-04-29T08:51:00.000-07:00</published><updated>2010-09-17T13:49:13.048-07:00</updated><title type='text'>nbgit for NetBeans 6.9 beta</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;My &lt;a href="http://trondn.blogspot.com/"&gt;brother&lt;/a&gt; was asking me for a version of &lt;a href="http://nbgit.org/"&gt;nbgit&lt;/a&gt; (git support for NetBeans) that works with NetBeans 6.9 beta. I've uploaded one &lt;a href="http://mediacast.sun.com/users/tnorbye/media/org-nbgit.nbm"&gt;here&lt;/a&gt;. By the way, look at the &lt;a href="http://code.google.com/p/nbgit/wiki/Options"&gt;Options wiki page&lt;/a&gt;, and especially the sections on &lt;a href="http://code.google.com/p/nbgit/wiki/Options#Custom_Actions"&gt;Custom Actions&lt;/a&gt;, for useful configuration tips for nbgit.&lt;br/&gt;&lt;br&gt;&lt;img width="1023" height="358" src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrampl6WI/AAAAAAAABSs/UHNsTzvY16U/nbgit.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8210502721902740777?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8210502721902740777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/04/nbgit-for-netbeans-69-beta.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8210502721902740777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8210502721902740777'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/04/nbgit-for-netbeans-69-beta.html' title='nbgit for NetBeans 6.9 beta'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrampl6WI/AAAAAAAABSs/UHNsTzvY16U/s72-c/nbgit.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-7981985849856920273</id><published>2010-04-28T12:39:00.000-07:00</published><updated>2010-09-17T13:49:13.025-07:00</updated><title type='text'>IDE tip: Go To Implementation</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;One of the best parts of using an IDE instead of an editor is "Go To Declaration". When you hold the Control key (or the Command key on Macs), identifiers under the mouse turn into hyperlinks and when you click on the hyperlink you jump to the declaration point of say the method call.&lt;br/&gt;You can also just hover over the hyperlink, and a tooltip will pop up and show you the signature of the identifier - the fully qualified type name, method arguments, and so on.&lt;br/&gt;&lt;br&gt;But what if the thing you are pointing at is an interface? Or an abstract class? Good Java programming style dictates that you should prefer interfaces over implementation types, so your code will typically only know about the interface or abstract type, and when you jump to the declaration, you go to the boring interface method definition, rather the interesting bits in the implementation!&lt;br/&gt;&lt;br&gt;This is what the &lt;b&gt;Go To Implementation&lt;/b&gt; feature is for. And I have a confession to make: I didn't start using this until recently. At the recent &lt;a href="http://blogs.sun.com/tor/entry/ide_tips"&gt;IDE tips roundup session&lt;/a&gt;, somebody asked whether NetBeans supported Go To Implementation. By instinct I went to Google and looked for a NetBeans plugin to do it, and &lt;a href="http://wiki.netbeans.org/JavaGoToImplementation"&gt;found one&lt;/a&gt;. Unfortunately, it was old and only worked with older versions of NetBeans. Uh oh. Then on a whim I decided to look in the Navigate context menu in NetBeans - and lo and behold, it's right there!&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOszuSVwQI/AAAAAAAAA1U/BTlFUxuq5Z8/goto-implementation5.jpg" /&gt;&lt;br/&gt;&lt;br&gt;And you don't need to use a context menu to access this feature. The trick is to use a second modifier key to the normal ctrl-click on the identifier! In addition to the control key (or command on Macs), also hold the Alt key (Option on Macs).&lt;br/&gt;&lt;br&gt;Here's how it works. First, let's say you want to go to the actionPerformed implementation. You ctrl-click the identifier:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtUkQCpbI/AAAAAAAAA6I/G7RNHwR5G0E/goto-implementation1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;...and that takes you into the abstract method declaration. (In this specific case, the method is in a read-only file inside a .jar file, which is why NetBeans marks the whole file in gray)&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOs7Bh0XsI/AAAAAAAAA2U/MsddtNZQoLo/goto-implementation2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;That's not what we want. Go back to the previous editor location (Ctrl-left.) This time, hold both the Control and Alt keys (or Command and Option on Macs) when you click. When you do that you get this dialog:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr14CCLgI/AAAAAAAABUQ/nyzC_0AWIC4/goto-implementation3.jpg" /&gt;&lt;br/&gt;&lt;br&gt;This dialog has focus and you can use the arrow keys to navigate and press enter -- or just click with the mouse. As soon as you pick a specific override of this method, you jump to it:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOr2WzeqFI/AAAAAAAAAsg/olcc7cwrdjs/goto-implementation4.jpg" /&gt;&lt;br/&gt;&lt;br&gt;That's all there is to it. It's doubly embarrassing that I didn't remember this feature, since I should know the implementation of it very well. You see, I shamelessly lifted most of the implementation of it for the language-infrastructure work I did to support Go To Declaration in Ruby, JavaScript etc:&lt;br/&gt;&lt;br&gt;&lt;a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week21"&gt;&lt;img border="0" src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrhp2mqLI/AAAAAAAAApM/biq7UewaBHI/goto-decl.jpg"&gt;&lt;/a&gt;&lt;br/&gt;&lt;br&gt;P.S. I've updated the wiki page with a clarification that it's built in now.&lt;br/&gt;&lt;br&gt;P.S.2: Until recent builds, Go To Implementation in NetBeans only worked for interfaces, not methods extending abstract classes. So use 6.9.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-7981985849856920273?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/7981985849856920273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/04/ide-tip-go-to-implementation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7981985849856920273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7981985849856920273'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/04/ide-tip-go-to-implementation.html' title='IDE tip: Go To Implementation'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOszuSVwQI/AAAAAAAAA1U/BTlFUxuq5Z8/s72-c/goto-implementation5.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-3035585098872172075</id><published>2010-04-13T06:41:00.000-07:00</published><updated>2010-09-17T13:49:07.030-07:00</updated><title type='text'>IDE tip: Create Build and Execution Shortcuts</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;We're moving over to Oracle's mail and file storage, so I spent a couple of hours going through my old Sun home directory to see what I wanted to save. It was pretty fun coming across all kinds of old screenshots, source code and design documents for things I worked on 10-15 years ago.&lt;br/&gt;I spent the first 5 years working on Sun's C/C++ development environment, and in particular the debugger.  One feature I built was the ability to create custom buttons which would let you run frequent &lt;code&gt;dbx&lt;/code&gt; commands (as well as reference builtin actions). Here's one screenshot I came across.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;The CDE/Motif widgets look pretty dated&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;Anyway, this reminded me of another really useful feature in NetBeans: The ability to create custom shortcuts for ant targets. If you're using ant, you probably have a number of useful, extra build targets. One I find particularly useful for our setup (where we have lots of project dependencies) is to have a "just run" build target which skips all dependency checks and just runs whatever bits are there. This is particularly useful if I change something in an upstream project and I don't want any checking downstream.&lt;br/&gt;&lt;br&gt;Here's how you do it.   First, let's say I've created an ant target to&lt;br/&gt;&lt;br/&gt;Target ideas: Run findbugs. Run code coverage. Run an arbitrary script.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-3035585098872172075?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/3035585098872172075/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/04/ide-tip-create-build-and-execution.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3035585098872172075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3035585098872172075'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/04/ide-tip-create-build-and-execution.html' title='IDE tip: Create Build and Execution Shortcuts'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-7461810934375132740</id><published>2010-04-01T13:57:00.000-07:00</published><updated>2010-09-17T13:49:12.993-07:00</updated><title type='text'>How to Write a Memory Leak Unit Test</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Unit tests are great for ensuring that your functionality is correct. But how do you make sure you don't have leaks in your code, leaks that&lt;br/&gt;eventually cause your application to crash when it runs out of memory? Unit tests don't typically don't run into memory problems directly because they tend to start up, run a little bit of code, and shut down -- getting a nice fresh memory environment on each test start.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;One great way to help protect yourself from uptime problems is to write leak tests. These are unit tests where you first perform some operations, then do normal cleanup, and finally you assert that the objects you were using during the operation have been cleaned up completely. In other words, that there are no references left anywhere on the heap.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Testing for leaks isn't very hard; the basic trick is to create a weak reference to your to-be-cleaned object (by constructing a &lt;code&gt;WeakReference&lt;/code&gt; wrapping your object), then you delete all your local references to the object, then you perform garbage collection, and finally you see whether the weak reference still contains your object. This works because the weak reference is handled specially by the garbage collection system.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;It turns out things aren't quite as easy as that, because garbage collectors try to be smart, and simply calling &lt;code&gt;System.gc()&lt;/code&gt; doesn't mean it's going to actually perform a complete and final garbage collection. This means that your unit test could incorrectly conclude you have a leak, since the reference is still held.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The NetBeans team has built a really good test infrastructure for this. When I wrote unit tests for NetBeans plugins, I could simply call their &lt;code&gt;assertGC&lt;/code&gt; method to assert that the given weak reference should be garbage collected, and it would handle the rest. (Internally, they do things like actually allocating a bunch of memory chunks to really force the garbage collection to run.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's an example:&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;// The following unit test fragment wants to ensure that a graphics object&lt;br/&gt;// which shows the current selection in the authoring tool, is cleared up after&lt;br/&gt;// the user clears the selection.&lt;br/&gt;view.selectAll();&lt;br/&gt;Node firstHandle = /* Node showing selection highlight, lookup code here */;&lt;br/&gt;assertNotNull(firstHandle);&lt;br/&gt;&lt;br/&gt;// Now clear view selection -- then assert that all the handles have disappeared&lt;br/&gt;view.selectNone();&lt;br/&gt;&lt;br/&gt;WeakReference&amp;lt;Node&amp;gt; ref = new WeakReference&amp;lt;Node&amp;gt;(firstHandle);&lt;br/&gt;firstHandle = null;&lt;br/&gt;assertGC("Selection handle leaked", ref);&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;When you write these tests you also have to make sure you null out any local variable references you are holding right there in the test.&lt;br/&gt;The above test will pass if and only if the target object, &lt;code&gt;firstHandle&lt;/code&gt;, is properly garbage collected.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;But wait -- that's not the best part. Let's say you've written a leak test, and it fails. Now what? What do you do -- make the process pause and attach a profiler and try to hunt it down?&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This is where their unit test support &lt;b&gt;really&lt;/b&gt; shines. When the unit test discovers that the reference is still held somewhere, it uses its own heap walking library to hunt down the offending reference, and dumps it out as part of the test assertion failure message!!!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's the output of a real leak test failure:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;Testcase: testMemoryLeak(SelectionHandlesTest):        FAILED&lt;br/&gt;Selection handle leaked:&lt;br/&gt;public static java.util.List javafx.scene.Scene@dc8a29-$dirtyCSSNodes-&gt;&lt;br/&gt;java.util.ArrayList@4ed14172-elementData-&gt;&lt;br/&gt;[Ljava.lang.Object;@3c22de9e-[41]-&gt;&lt;br/&gt;javafx.scene.shape.Rectangle@612e4cd&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;In other words, we see that there is a static list in &lt;code&gt;Scene&lt;/code&gt; named dirtyCSSNodes which is holding on to our target Rectangle. The syntax here is that you first see the class name for the object (where a prefix of &lt;code&gt;[L&lt;/code&gt; means it's an array-of), then its system id, then the field name - and if it's an array, the array index.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;When the unit test fails, it takes a while -- 20 seconds or so for the above test -- to actually produce the above trace. But the important part is that this is only slow when the test fails. It only has to work hard when you have a leak, and you don't want to have leaks!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I've been wanting to write leak tests for the authoring tool (which is written in JavaFX), since uptime matters a great deal in a tool which deals with potentially large objects (such as multimedia assets). And I realized that there is absolutely nothing NetBeans specific about the NetBeans leak unit test support. So I went and pulled out the relevant code into a separate library. The library basically contains two parts: a &lt;code&gt;.jar&lt;/code&gt; file which contains the &lt;a href="http://performance.netbeans.org/insane/index.html"&gt;INSANE&lt;/a&gt; heap walking library, and a second jar which contains the &lt;code&gt;assertGC()&lt;/code&gt; unit test assertion method and supporting infrastructure.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I have extracted this into standalone pieces (outside the NetBeans infrastructure) so you can get the bits easily - download &lt;a href="http://mediacast.sun.com/users/tnorbye/media/leaktests.zip"&gt;leaktests.zip&lt;/a&gt;, then add the two jars in there on your test classpath and call &lt;code&gt;assertGc()&lt;/code&gt; and &lt;code&gt;assertSize()&lt;/code&gt; from your tests as described above. Here's the basic skeleton for all leak tests:&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;// (1) Create your objects&lt;br/&gt;// (2) Look up the object you want to ensure gets cleaned up later:&lt;br/&gt;Foo foo = // code to get foo&lt;br/&gt;assertNotNull(foo);&lt;br/&gt;&lt;br/&gt;// (3) Call your cleanup code which is supposed to free everything&lt;br/&gt;&lt;br/&gt;// (4) Create a weak reference to your object reference, and null out&lt;br/&gt;//   your reference&lt;br/&gt;WeakReference&amp;lt;Foo&amp;gt; ref = new WeakReference&amp;lt;Foo&amp;gt;(foo);&lt;br/&gt;foo = null;&lt;br/&gt;assertGC("Foo leaked", ref);&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;All I've done is extract NetBeans code written by others so I've kept the licenses the same as for NetBeans. All credit goes to the author of &lt;a href="http://performance.netbeans.org/insane/index.html"&gt;INSANE&lt;/a&gt;, Petr Nejedly -- and to the authors of the memory assertion stuff in &lt;a href="http://hg.netbeans.org/main-silver/annotate/63b0eb0ebe1a/nbjunit/src/org/netbeans/junit/NbTestCase.java"&gt;NbTestCase.java&lt;/a&gt;.  All the source code for INSANE and NbTestCase are in the NetBeans mercurial repository.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In addition to &lt;code&gt;assertGC&lt;/code&gt;, there is also &lt;code&gt;assertSize()&lt;/code&gt;. This method can be used to ensure that the &lt;b&gt;transitive&lt;/b&gt; size of an object graph is below a certain threshold! This can be good for writing tests to not only ensure that you don't have leaks, but that your data structures are of the rough expected size so you don't need excessive amounts of memory. There are more details on this on the &lt;a href="http://performance.netbeans.org/insane/index.html"&gt;INSANE&lt;/a&gt; home page.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;One special note on JavaFX: The above leak isn't actually a leak; it is a deliberate optimization of the scenegraph, and the reference will be cleared up after the next scene pulse completes. Therefore, for unit leak tests, in addition to actually nulling out the weak references, you also want to run through a scene pulse as well. One really hacky, implementation-dependent and unsupported way to do that is to call &lt;code&gt;scene.$scenePulseListener.pulse();&lt;/code&gt;. You probably want to isolate that in a utility method such that you can update it in one place when it needs to change...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finally, note that I built this on JDK6. If there is interest perhaps we could create a wrapper project for this on Kenai or java.net, where people can also create say a Maven binary for this, a JDK 5 version (there is nothing JDK6 specific so it just needs a recompile, but I don't have JDK5 on this Snow Leopard Mac), etc. Hope you find this all as useful as I have!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-7461810934375132740?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/7461810934375132740/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/04/how-to-write-memory-leak-unit-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7461810934375132740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7461810934375132740'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/04/how-to-write-memory-leak-unit-test.html' title='How to Write a Memory Leak Unit Test'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2544031342977858553</id><published>2010-03-30T03:45:00.000-07:00</published><updated>2010-09-17T13:49:12.971-07:00</updated><title type='text'>IDE tip: AST-based Selection</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;AST-based selection is a feature which lets you select the surrounding "block", based not on syntactic clues (such as braces and parentheses, as is offered by practically all editors), but based on the parse tree created by the compiler (or the "AST", for abstract syntax tree).&lt;br/&gt;&lt;br&gt;In NetBeans, there are two complementary actions to deal with AST selection: Select Surrounding and its reverse. They have other names which I can never remember, but the keybindings are as follows:&lt;br&gt;&lt;br/&gt;Select surrounding block&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; Mac:  &lt;b&gt;Ctrl-Shift-.&lt;/b&gt; (period)&lt;br/&gt;&lt;li&gt; Windows/Linux/Solaris/Others: &lt;b&gt;Alt-Shift-.&lt;/b&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;Reverse:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; Mac:  &lt;b&gt;Ctrl-Shift-,&lt;/b&gt; (comma)&lt;br/&gt;&lt;li&gt; Windows/Linux/Solaris/Others: &lt;b&gt;Alt-Shift-,&lt;/b&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;On my U.S. keyboard, the comma and period keys are marked with "&lt;" and "&gt;" for the shift key which is somewhat reminiscent of blocks.&lt;br/&gt;&lt;br&gt;These two actions cooperate and are stateful: they remember the original caret location such that you can "go back".&lt;br/&gt;Here's how it works.  You want to select something surrounding the caret, say the whole method. In that case you just&lt;br/&gt;hit the surrounding action. With your fingers holding ctrl and shift you hit dot -- once, twice, bam bam bam. If you do it&lt;br/&gt;quickly you might "overshoot" and go one too far and select say the whole class instead of just the method. If so just press&lt;br/&gt;comma and voila, it goes back one step down the selection hierarchy you just came up.&lt;br/&gt;&lt;br&gt;This makes this a very quick way to select code blocks -- no more need to grab the mouse and try to hit exactly the selection&lt;br/&gt;boundaries between characters.&lt;br/&gt;&lt;br&gt;Here's an example of where this comes in useful.  I sometimes remove long expressions from method call arguments by pulling it&lt;br/&gt;out as a separate variable. Here's my call, and I want to extract the whole &lt;code&gt;Math.min&lt;/code&gt; expression.&lt;br/&gt;First I move the caret &lt;b&gt;anywhere&lt;/b&gt; within that expression:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrcjai5jI/AAAAAAAAAoc/EAkljRumXec/select1.jpg"&lt;br/&gt;&lt;br&gt;Then I press &lt;b&gt;Alt-Shift-.&lt;/b&gt; (or Ctrl-Shift-. on Mac):&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOucxFV4LI/AAAAAAAABDI/d-SUR2Ss1Qo/select2.jpg"&lt;br/&gt;&lt;br&gt;One more time:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOt-jmXCgI/AAAAAAAABY8/X2p7OTOvmIk/select3.jpg"&lt;br/&gt;&lt;br&gt;Let's pretend I was doing it quickly and hit it one extra time:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOuckKxwVI/AAAAAAAABDE/TEVvBt6Lq3E/select-too-far.jpg"&lt;br/&gt;&lt;br&gt;That's too far, so I press comma (with the modifier keys still pressed):&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOt-jmXCgI/AAAAAAAABY8/X2p7OTOvmIk/select3.jpg"&lt;br/&gt;&lt;br&gt;In practice (and with practice) this is done very quickly, faster than I can&lt;br/&gt;accurately hit both ends of the expression with a mouse drag. And to finish&lt;br/&gt;out the example, let me show a couple of more things related to the task.&lt;br/&gt;Notice how there's a light bulb in the left hand side margin of the editor.&lt;br/&gt;That tells me there are associated quick fixes. I press &lt;b&gt;Alt Enter&lt;/b&gt;,&lt;br/&gt;and the quick fix dialog is shown:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOt-2YED6I/AAAAAAAABZA/GSJhwSx4GSI/select4.jpg"&lt;br/&gt;&lt;br&gt;I choose "Introduce Variable" and press Return. This gives&lt;br/&gt;a dialog where I can choose the variable name (and whether to replace all occurrences&lt;br/&gt;when applicable).  It suggests "min" since that's the function&lt;br/&gt;name of the expression we're extracting.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOumFGAKII/AAAAAAAABEU/MtmNqvmXnek/select5.jpg"&lt;br/&gt;&lt;br&gt;Just press Return to apply the refactoring, and we've pulled out the argument&lt;br/&gt;expression:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrdEMZBBI/AAAAAAAAAog/scluFuBfUGs/select6.jpg"&lt;br/&gt;&lt;br&gt;I just pressed return and got the default name. Then I realize that this may&lt;br/&gt;not be a great name. What is that last parameter again? I can place the caret&lt;br/&gt;somewhere within the last argument and press &lt;b&gt;Cmd-P&lt;/b&gt; (or &lt;b&gt;Ctrl+P&lt;/b&gt;&lt;br/&gt;on other platforms) to get NetBeans to "Show Method Parameters".&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsk7AdwwI/AAAAAAAAAzI/GeanZxSKp14/select7.jpg"&lt;br/&gt;&lt;br&gt;Let's rename it to length instead. Press &lt;b&gt;Ctrl-R&lt;/b&gt; (all platforms) to&lt;br/&gt;apply rename refactoring, which (because this is a local or private variable)&lt;br/&gt;will have "instant rename" applied where your edits are applied immediately&lt;br/&gt;for every keystroke:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrlhPysMI/AAAAAAAAAp4/F5XHplqj9HY/select8.jpg"&lt;br/&gt;&lt;br&gt;Just type the new name - notice that all the boxed expressions are edited synchronously.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsXqsPyzI/AAAAAAAAAxU/-M13n7NOMzM/select9.jpg"&lt;br/&gt;&lt;br&gt;Using AST-based selection to identify code blocks to extract as variables or methods&lt;br/&gt;is useful, but it can be used in other ways as well. Let's say I want to add&lt;br/&gt;a second validation step to this function. First I select the code block using&lt;br/&gt;AST selection:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOskTs00jI/AAAAAAAABWU/OkIkTR_KSdU/select10.jpg"&lt;br/&gt;&lt;br&gt;&lt;br/&gt;NetBeans has a keyboard command for duplicating the current line: &lt;b&gt;Ctrl-Shift-Down&lt;/b&gt;&lt;br/&gt;(and on Mac, it's &lt;b&gt;Cmd-Shift-Down&lt;/b&gt;.)  Note that when you have a selection, this&lt;br/&gt;duplicates the entire selection. So all we have to do now is apply the duplicate command&lt;br/&gt;and we've got a second if clause we can just tweak to whatever it is it needs to do.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrlKYQ_mI/AAAAAAAABTU/0XzA1Y8eNNI/select11.jpg"&lt;br/&gt;&lt;br&gt;&lt;br/&gt;AST based selection should be available in nearly all editor types in NetBeans.&lt;br/&gt;In Ruby, JavaScript, Python, etc it also handles documentation&lt;br/&gt;blocks well - so if you apply select surrounding in say a Ruby comment, it will first select&lt;br/&gt;the current line, then the whole documentation block, then outwards in the AST hierarchy.&lt;br/&gt;&lt;br&gt;Hope you find this helpful. If there are Eclipse or IntelliJ readers who know corresponding&lt;br/&gt;keybindings in Eclipse, feel free to leave a comment so others can find it easily.&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2544031342977858553?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2544031342977858553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/03/ide-tip-ast-based-selection.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2544031342977858553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2544031342977858553'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/03/ide-tip-ast-based-selection.html' title='IDE tip: AST-based Selection'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrcjai5jI/AAAAAAAAAoc/EAkljRumXec/s72-c/select1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2243824262354407001</id><published>2010-03-25T06:45:00.000-07:00</published><updated>2010-09-17T13:49:12.941-07:00</updated><title type='text'>IDE tips</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;One of the sessions we had at the &lt;a href="http://blogs.sun.com/tor/entry/java_posse_roundup"&gt;Roundup&lt;/a&gt; was one entitled "IDE tips and tricks". We basically sat there with our laptops and did a show &amp;amp; tell of various "hidden" IDE features we knew about to help productivity. There were Eclipse, IntelliJ and NetBeans users there - and even some advocacy for Vim :)   We discovered pretty quickly that this would not make for compelling listening, so we just turned off the recorder.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;One thing I discovered (and which I saw during our languages coding dojo day as well) is that a lot of people don't use many of the productivity boosters. Therefore, I thought I'd bring some of these up here. Since I've been intending to start blogging more again, I'll make this a regular "column".&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;To kick things off, I'll just point to an old blog entry which is still relevant: &lt;a href="http://blogs.sun.com/tor/entry/hippie_completion"&gt;Hippie Completion&lt;/a&gt;. Learn to use Ctrl-K while editing, it will be worth your while.  (Eclipse has this too as of Eclipse 3.1; I believe it's bound to Alt-/).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2243824262354407001?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2243824262354407001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/03/ide-tips.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2243824262354407001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2243824262354407001'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/03/ide-tips.html' title='IDE tips'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-649808652565270302</id><published>2010-03-25T01:55:00.000-07:00</published><updated>2010-09-17T13:49:12.931-07:00</updated><title type='text'>Transparent windows on Linux</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;JavaFX makes it easy to create non-rectangular windows -- just set a &lt;code&gt;StageStyle.TRANSPARENT&lt;/code&gt; on your &lt;code&gt;stage.style&lt;/code&gt;.&lt;br/&gt;We use rounded corners on our popup menus, and we also have a non-rectangular and alpha-blended splash screen.&lt;br/&gt;&lt;br&gt;The other day I was checking how the cursors were looking on different platforms, and imagine my horror when I discovered how our new splash screen and rounded menus looked on Linux! Here they are -- as you can see you end up with white rectangles around the supposed-to-be-blended areas:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtmD-5QYI/AAAAAAAAA80/MQ9JEjP-Tqk/menu-no-alpha.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrr7MZjnI/AAAAAAAAAq4/w8To_FjcpD8/splash-no-alpha.jpg" /&gt;&lt;br/&gt;&lt;br&gt;That looks.... craptastic!&lt;br/&gt;&lt;br&gt;Historically, the JDK didn't support alpha blended windows on Linux.  However, that was added a while ago (I'm not sure exactly which version, but I think it was JDK 6 update 14). It turns out that the FX code which initializes the native frame for the stage does not do conditional checking for this; it simply turns off transparency on Linux. Fortunately, there's a System property you can set to force it to respect the transparency flag. You would obviously only do this if you know you are running on a JDK which supports transparency. And that's easy!&lt;br/&gt;&lt;br&gt;In your startup code, do something like this:&lt;br/&gt;&lt;pre class="brush: javafx;"&gt;&lt;br/&gt;if (Utils.IS_LINUX and Utils.jdkAtLeast(1, 6, 0, 14)) {&lt;br/&gt;java.lang.System.setProperty("javafx.allowTransparentStage", "true");&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;There are a couple of utility methods here that are simple - just looking at some system properties to determine whether we're on Linux and whether we're on a particular version of the JDK or higher (if you run on non-Sun/Oracle JDKs you may want to check for that as well).&lt;br/&gt;&lt;br&gt;&lt;pre class="brush: javafx;"&gt;&lt;br/&gt;public def IS_LINUX = osName.contains("linux");&lt;br/&gt;public def IS_MAC = osName.contains("mac");&lt;br/&gt;public def IS_WINDOWS = osName.contains("windows");&lt;br/&gt;public def IS_SOLARIS = osName.contains("solaris");&lt;br/&gt;&lt;br/&gt;/**&lt;br/&gt;* Is the version of the running JDK at least major.minor.micro_update?&lt;br/&gt;* In 1.6.0_18 macro=1,minor=6,micro=0,update=18&lt;br/&gt;*/&lt;br/&gt;public function jdkAtLeast(macro: Integer, minor: Integer, micro: Integer, update: Integer): Boolean {&lt;br/&gt;def runtimeVersion = java.lang.System.getProperty("java.runtime.version");&lt;br/&gt;def pattern = java.util.regex.Pattern.compile("^(\\d)\\.(\\d)\\.(\\d)_(\\d+)-");&lt;br/&gt;def matcher = pattern.matcher(runtimeVersion);&lt;br/&gt;if (matcher.find()) {&lt;br/&gt;def currentMacro = Integer.valueOf(matcher.group(1));&lt;br/&gt;def currentMinor = Integer.valueOf(matcher.group(2));&lt;br/&gt;def currentMicro = Integer.valueOf(matcher.group(3));&lt;br/&gt;def currentUpdate = Integer.valueOf(matcher.group(4));&lt;br/&gt;if (currentMacro &lt; macro or currentMinor &lt; minor or&lt;br/&gt;currentMicro &lt; micro or currentUpdate &lt; update) {&lt;br/&gt;return false;&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;true&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;With that modification at startup, we get much nicer results:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsguMDuTI/AAAAAAAAAyg/yggPGubZ-5Q/menu-alpha.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsv9PnBnI/AAAAAAAAA0w/5qJn9VbnDxc/splash-alpha.jpg" /&gt;&lt;br/&gt;&lt;br&gt;P.S. Yes, there's a JIRA issue tracking this to be automatically done by the platform, RT-4797.&lt;br&gt;&lt;br/&gt;P.S.2. This is for desktop; I'm not sure this code is mobile-safe.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-649808652565270302?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/649808652565270302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/03/transparent-windows-on-linux.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/649808652565270302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/649808652565270302'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/03/transparent-windows-on-linux.html' title='Transparent windows on Linux'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtmD-5QYI/AAAAAAAAA80/MQ9JEjP-Tqk/s72-c/menu-no-alpha.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6125633514559909064</id><published>2010-03-24T13:51:00.000-07:00</published><updated>2010-09-17T13:49:12.914-07:00</updated><title type='text'>300 Episodes</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;We had a milestone in the podcast last week: 300 episodes. That's more than one episode per week for the 4&amp;frac12; years we've been doing it!&lt;br/&gt;We spent our &lt;a href="http://javaposse.com/index.php?post_id=595077"&gt;300th episode&lt;/a&gt; as a retrospective, looking back at highlights over the years.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;We looked up some statistics, too.  The most amazing one (to us) is that we are now up to 15,000 downloads per episode! Our feedback alias has over 10,000 e-mails (not counting spam).  And our &lt;a href="http://groups.google.com/group/javaposse/"&gt;discussion forum&lt;/a&gt; has nearly 20,000 messages at this point! Wow! Thanks for listening and participating!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;a href="http://hillert.blogspot.com/2010/03/java-posse-roundup-2010-summary.html"&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsY8G5hLI/AAAAAAAAAxc/rqRQ_rMtkYo/TheJavaPosse2010CrestedButte_mod.jpg" /&gt;&lt;/a&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;(Photo by &lt;a href="http://hillert.blogspot.com/2010/03/java-posse-roundup-2010-summary.html"&gt;Gunnar Hillert&lt;/a&gt;)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6125633514559909064?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6125633514559909064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/03/300-episodes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6125633514559909064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6125633514559909064'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/03/300-episodes.html' title='300 Episodes'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsY8G5hLI/AAAAAAAAAxc/rqRQ_rMtkYo/s72-c/TheJavaPosse2010CrestedButte_mod.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8621518106787497236</id><published>2010-03-18T16:20:00.000-07:00</published><updated>2010-09-17T13:49:12.886-07:00</updated><title type='text'>Java Posse Roundup</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I've spending the week in beautiful Crested Butte, Colorado at the &lt;a href="http://www.mindviewinc.com/Conferences/JavaPosseRoundup/"&gt;Java Posse Roundup&lt;/a&gt;. It's the fourth year in a row, with record attendance. And as always, it's been fantastic. It's hard to explain an Open Space conference - it doesn't &lt;b&gt;sound&lt;/b&gt; like it would work, and I was personally surprised to see how well it worked when I attended the first time. Now I simply expect it, and it always delivers. One key reason why this open space conference works so well compared to say "unconference" events attached to major face-forward conferences is that you need to be away from everything and really immerse yourself - and here up in the Rockies we certainly are isolated!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The day before the conference started we had a "Languages Dojo" day where people pick different languages they're interested and go off building something. We had planned in advance to build a JavaFX version of the "Ohm Writer", a Zen-like text editor that is full screen, has nice relaxing background music, background sounds and typing sounds.  We had a great time, and made a lot of progress. Unfortunately, we spent a lot of the day fighting with git (the version control system). I'm a very happy Mercurial user, but I've had a little bit of git-envy since I know it can combine local changesets into a single changeset to be pushed to the repository. I could see myself using that a lot. And setting things up on github for collaboration was very easy. But that's where the fun ended - nothing worked, simple merges aborted, error messages were completely unhelpful, and in general we repeatedly ended up checking out new clean workspaces and hand applying changes. I liked Mercurial before but now I appreciate it even more. (I hear the guys who were doing functional programming &lt;b&gt;also&lt;/b&gt; were ripping their hair out with git. P.S. Joel Spolsky just &lt;a href="http://hginit.com/"&gt;posted a Mercurial tutorial&lt;/a&gt;).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The app is functional, and more importantly we made the editor start up immediately, load images and audio in the background and gradually fade in the image as soon as it's available. We also had difficulty playing the keyboard "click" sound until we realized you don't want to just repeatedly call &lt;code&gt;play()&lt;/code&gt; on a media player -- you have to reset it -- either setting &lt;code&gt;mediaPlayer.currentTime = 0s&lt;/code&gt; or calling &lt;code&gt;mediaPlayer.playFromStart()&lt;/code&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;We also ran into another bug -- and this is a gotcha I've seen before, so it seems useful to highlight it here: For JavaFX Strings, null and "" are the same! Therefore, you &lt;b&gt;don't&lt;/b&gt; want to write code like this:&lt;br/&gt;&lt;pre class="brush: javafx;"&gt;&lt;br/&gt;while ((line = reader.readLine()) != null) {&lt;br/&gt;// use line&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;because this will terminate the loop as soon as you reach an empty line!! Be &lt;b&gt;very&lt;/b&gt; careful about checking for nulls explicitly when dealing with Strings.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;We've also had Lightning Talks in the evenings. If you're not familiar with Lightning Talks, these are very quick presentations, one after the other, on any subject, but limited to 5 minutes. Yes, with a HARD 5 minute limit. The advantage of limiting the lightning talks to 5 minutes is that it forces the presenter to &lt;b&gt;really&lt;/b&gt; focus on the interesting parts of the subject, and if it's really not interesting, at least you're only bored for a couple of minutes! The topics this year were really great though - there was even a fire-eating demonstration!&lt;br/&gt;One way to keep track of the time is to use a countdown timer. We wrote one in JavaFX last year, which displays a classic countdown timer (imported Photoshop graphics) and a sound file playing as the timer is expiring. It's available as a &lt;a href="http://www.sondow.com/shutup"&gt;webstart app&lt;/a&gt; if you want to run it for your own lightning talks, or you can &lt;a href="http://code.google.com/p/jpr09/source/checkout"&gt;study the code&lt;/a&gt;.&lt;br/&gt;&lt;br&gt;&lt;a href="http://www.sondow.com/Shutup.jnlp"&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOswbCnlZI/AAAAAAAAA00/sdMc38wSGzY/timer-small.jpg" border="0"&gt;&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In addition to the morning open space conference sessions, the evening lightning talks, the progressive dinners, we've had some afternoon technical presentations and coding sessions -- check out our improvised projector screen in our living room:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOucO1FYJI/AAAAAAAABDA/ui88KTiki_w/screen.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8621518106787497236?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8621518106787497236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/03/java-posse-roundup.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8621518106787497236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8621518106787497236'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/03/java-posse-roundup.html' title='Java Posse Roundup'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOswbCnlZI/AAAAAAAAA00/sdMc38wSGzY/s72-c/timer-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-9097254312749298563</id><published>2010-03-01T13:16:00.000-08:00</published><updated>2010-09-17T13:49:12.875-07:00</updated><title type='text'>Using Mercurial over ssh without typing the password</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;We're using Mercurial. Our release engineering servers run web servers, so we can browse our repositories, just like the public NetBeans ones at &lt;a href="http://hg.netbeans.org"&gt;http://hg.netbeans.org&lt;/a&gt;, and pull down new changesets anonymously. However, for authentication purposes, we also use ssh, so all pushes to the repository has to go through ssh.&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;$ cat .hg/hgrc&lt;br/&gt;[paths]&lt;br/&gt;default = http://our.server.sun.com/our/repository&lt;br/&gt;default-push = ssh://our.server.sun.com//our/repository&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;(P.S. Notice how there are &lt;b&gt;2&lt;/b&gt; slashes in the SSH path and only one in the http path - if you forget about that Bad Stuff(tm) happens.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This means that whenever I pull (or determine incoming changes via &lt;code&gt;hg incoming&lt;/code&gt;) it executes immediately, but whenever I want to push (or determine outgoing changes), I need to supply a password.  And let's just say typing my password is not easy, since the password requirements at Sun (and shortly, Oracle) are really strict - no nice, short and simple passwords here!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I've been putting up with it for a year now - after all, it's just a couple of seconds here and a couple of seconds there - but I knew it should be possible to fix this, since back in my hardcore Solaris days I had all this stuff configured correctly via the ssh key agent so that I could ssh from one account to the next. On the other hand, I've googled it (mercurial + ssh) a couple of times, and the information I've found has always been for doing more complicated things (&lt;a href="http://www.selenic.com/repo/hg-stable/raw-file/tip/contrib/hg-ssh"&gt;1&lt;/a&gt;,&lt;a href="http://mercurial.selenic.com/wiki/HgLogin"&gt;2&lt;/a&gt;) than the simple authentication setup I wanted. So I just put it off.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I decided to bite the bullet and look into configuring it - and it was really trivial. I'm bummed I haven't tried earlier! I thought I'd write this up in case it helps anyone else in a similar situation.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The reason it's trivial, is that it turns out there is nothing specific about using Mercurial here. &lt;i&gt;This is actually a case where Googling something was harmful! If I had just tried it, instead of searching for a recipe and getting confused, I would have had this set up a long time ago!&lt;/i&gt; Hopefully this blog entry will help anyone searching for "hg ssh passwords" ! Anyway... You just need to ensure that you can ssh directly into the system you are trying to push to, and if you can do that, then mercurial can do the rest. And this setup is easy and well documented.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;First, you need to generate a local key.&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;$ &lt;b&gt;ssh-keygen -t rsa&lt;/b&gt;&lt;br/&gt;Generating public/private rsa key pair.&lt;br/&gt;Enter file in which to save the key (/Users/tor/.ssh/id_rsa):&lt;br/&gt;Created directory '/Users/tor/.ssh'.&lt;br/&gt;Enter passphrase (empty for no passphrase):&lt;br/&gt;Enter same passphrase again:&lt;br/&gt;Your identification has been saved in /Users/tor/.ssh/id_rsa.&lt;br/&gt;Your public key has been saved in /Users/tor/.ssh/id_rsa.pub.&lt;br/&gt;The key fingerprint is:&lt;br/&gt;&lt;i&gt;... (omitted) ...&lt;/i&gt;&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Next you need to copy this file to the server and call it ~/.ssh/authorized_keys. Actually, that file may already exist and you really want to append to it, not replace it. So first ensure the directory exists:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;$ &lt;b&gt;ssh tor@our.server.sun.com mkdir -p .ssh&lt;/b&gt;&lt;br/&gt;Password:&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;And finally copy your authentication key over to the server:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;$ &lt;b&gt;scp .ssh/id_rsa.pub tor@our.server.sun.com:.ssh/authorized_keys&lt;/b&gt;&lt;br/&gt;Password:&lt;br/&gt;id_rsa.pub   100%  422     0.4KB/s   00:00&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;That's it!  Now try logging in again:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;$ &lt;b&gt;ssh tor@our.server.sun.com&lt;/b&gt;&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;On my Mac, this actually pops up the system authentication dialog:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtulQ_mdI/AAAAAAAAA-A/3cL4p6D9hKI/keyagent.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Not only can I enter my password in the dialog, but I can tell it to remember this key in the keychain, and from now on, the &lt;b&gt;system&lt;/b&gt; supplies the password to ssh when it wants to log in to hosts.&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;$ &lt;b&gt;ssh tor@our.server.sun.com&lt;/b&gt;&lt;br/&gt;Identity added: &lt;i&gt;details omitted&lt;/i&gt;&lt;br/&gt;Last login: Mon Mar  1 19:22:18 2010&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;And now, the whole point of this exercise -- I can run "hg out" and "hg push" (as well as scripts which operate over multiple mercurial repositories) without the need to type that annoying password again. On the other hand, how will I remember it now that I'm not repeating it like a mantra dozens of times per day?&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;$ &lt;b&gt;hg out&lt;/b&gt;&lt;br/&gt;comparing with ssh://our.server.sun.com//our/repository&lt;br/&gt;searching for changes&lt;br/&gt;no changes found&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. &lt;a href="http://bit.ly/7JJSz8"&gt;Here's&lt;/a&gt; a copy of my own authentication keys in case that helps you configure your own system. Please don't use these to log into our system.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-9097254312749298563?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/9097254312749298563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/03/using-mercurial-over-ssh-without-typing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/9097254312749298563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/9097254312749298563'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/03/using-mercurial-over-ssh-without-typing.html' title='Using Mercurial over ssh without typing the password'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtulQ_mdI/AAAAAAAAA-A/3cL4p6D9hKI/s72-c/keyagent.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5686146691319845230</id><published>2010-02-11T15:12:00.000-08:00</published><updated>2010-09-17T13:49:07.042-07:00</updated><title type='text'>How to Render a JavaFX Node into an Image</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Sometimes you want to render a Node tree into an Image.  For example, you may want to do it for performance reasons (such as &lt;a href="http://piliq.com/javafx/?p=1108"&gt;this example&lt;/a&gt;), or you may want to create thumbnail views, or perhaps you want to create a nice drag &amp;amp; drop effect where there is a ghost image of the object being manipulated showing both the current position (the real node) and its target position (its image).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There are some solutions posted for this, but they rely on pretty deep ties to AWT and scenegraph internals. There isn't a way to do it using public APIs yet, but here is a simpler solution. This uses a method on Scene to render the scene to an image, so the trick is to temporarily remove the Node from its current location in the node hierarchy, place it in a new Scene, render the image and put the Node back. This is all pretty simple - you just have to take care of some minor details - like the fact that the scene render will render from (0,0) to the size of the scene bounds, rather than from minX to maxX and minY to maxY. So, we have to add a reverse Translation to place the image back. There is also a problem that the scene render will truncate the bottom and rightmost pixels, so we need to explicitly set the scene size and padd it by 1. And finally, with CSS in the picture we want to duplicate the stylesheet reference from the Node's scene in the render scene, and we also need to preserve the style context. (There are more issues here around CSS; it is a key new feature in JavaFX 1.3 and central to the controls, and there are implementation aspects here for when the CSS phase is running, and it turns out currently the layout styles stay intact - they only get recomputed on the next layout pulse - so this all works beautifully. But the implementation is changing a lot these days so this may need tweaking before this ink dries!)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The only limitation here is that we need to be able to move the Node to render it - which means you cannot render any Nodes that are bound to its parent, e.g. you have a parent group whose content property is a bound sequence including the Node.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;http://piliq.com/javafx/?p=1108&lt;br/&gt;http://forums.sun.com/thread.jspa?threadID=5392972&lt;br/&gt;&lt;br/&gt;Note - NOT official APIs - much cleaner.&lt;br/&gt;Limitation&lt;br/&gt;Couple of necessary tricks: must set scene bounds, and shift it to (0,0); scale&lt;br/&gt;&lt;br/&gt;def platformImage = scene.renderToImage(null);&lt;br/&gt;image = Image.impl_fromPlatformImage(platformImage);&lt;br/&gt;&lt;br/&gt;Anyway, I wrote some code to do this today. This doesn't only render the node; it also has the possibility to scale the image if its width or height exceeds a certain number. We do that because in the authoring tool we show a little preview of the selected component, and this uses the render to node facility.&lt;br/&gt;(Screenshot here)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5686146691319845230?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5686146691319845230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/02/how-to-render-javafx-node-into-image.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5686146691319845230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5686146691319845230'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/02/how-to-render-javafx-node-into-image.html' title='How to Render a JavaFX Node into an Image'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6270353453825016458</id><published>2010-02-11T13:02:00.000-08:00</published><updated>2010-09-17T13:49:07.065-07:00</updated><title type='text'>My Test Environment</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Last year I &lt;a href="http://blogs.sun.com/tor/entry/run_tests_without_focus_loss"&gt;documented&lt;/a&gt; my setup for running unit tests on my Mac. The solution relied on a quirk of how the window system on the Mac worked. And unfortunately, when I upgraded to Snow Leopard a few months ago, the solution stopped working.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;However, after trying a few things I've found a new setup which works -- and thanks to some other improvements I now have a better setup than ever!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In short,&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; I run the unit tests via Hudson, the continuous integration server. The tests are running on a different account on this Mac, such that&lt;br/&gt;the UI tests never interfere with my work - no focus loss, no windows popping up, etc.&lt;br/&gt;&lt;li&gt; I use a special Hudson plugin to filecopy my source tree to the build server repository, such that I don't have to check in the code I want to run tests again.&lt;br/&gt;&lt;li&gt; Since Hudson is running locally it has access to my audio, so I have it speak when the build is done (and whether it succeeded or failed) so that I know immediately whether to push my changes or investigate the build or test failures.&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The tri&lt;br/&gt;AUDIO&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6270353453825016458?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6270353453825016458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2010/02/my-test-environment.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6270353453825016458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6270353453825016458'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2010/02/my-test-environment.html' title='My Test Environment'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-4032348574354958151</id><published>2009-12-11T01:44:00.000-08:00</published><updated>2010-09-17T13:49:12.846-07:00</updated><title type='text'>How to determine the JUnit 4 current test name</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;In my unit tests I often want to know the name of the test that is executing. For example, I often want to have the golden file (expected test output) computed automatically from the testname. As another example in my JavaFX testing, I often generate screenshots inside failing tests and it's useful to name these screenshots by the failing tests.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In JUnit 3 this was simple, since your testcases would extend a builtin JUnit class which had a method you could call to return the current test. However, with JUnit 4 that's no longer possible. I've googled and found the "correct" way to do it - &lt;a href="http://stackoverflow.com/questions/1069456/how-to-obtain-test-case-name-in-junit-4-at-runtime"&gt;using a special @RunWith to run the test class&lt;/a&gt; - but I find that solution unsatisfying. My utility methods which are invoked to read golden files and screenshot etc are in one place and I now have to decorate all my tests. Besides, I &lt;i&gt;already&lt;/i&gt; have a &lt;code&gt;@RunWith&lt;/code&gt; annotation on my tests because I want to run them on the event dispatch thread so I have a special test runner for that.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;So, I've found a better way to do it. Better &lt;i&gt;for me&lt;/i&gt; I mean - this may have problems and limitations I'm not aware of, but for all of &lt;i&gt;my&lt;/i&gt; tests this worked wonderfully, and doesn't have the @RunWith requirements (though note that I don't do multithreading in my tests, other than invoke them on the event dispatch thread, so if you try to call this from a thread that didn't invoke the test it probably won't work):&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;public static String getTestName() {&lt;br/&gt;// Try to find a method on the stack which is annotated with @Test -- if so, that's the one&lt;br/&gt;StackTraceElement[] elements = new Throwable().fillInStackTrace().getStackTrace();&lt;br/&gt;for (int i = 1; i &lt; elements.length; i++) {&lt;br/&gt;StackTraceElement element = elements[i];&lt;br/&gt;try {&lt;br/&gt;Class&lt;?&gt; clz = Class.forName(element.getClassName());&lt;br/&gt;Method method = clz.getMethod(element.getMethodName(), new Class[0]);&lt;br/&gt;for (Annotation annotation : method.getAnnotations()) {&lt;br/&gt;if (annotation.annotationType() == org.junit.Test.class) {&lt;br/&gt;return element.getMethodName();&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;} catch (NoSuchMethodException ex) {&lt;br/&gt;} catch (SecurityException ex) {&lt;br/&gt;} catch (ClassNotFoundException classNotFoundException) {&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;// Just assuming it's the calling method&lt;br/&gt;return elements[1].getMethodName();&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;As with most of my test utilities, it's a public static method living in a class called &lt;code&gt;TestUtils&lt;/code&gt;, which I statically import from my test cases such that I can simply reference the test name getter like I would in the JUnit 3 days:&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;import static org.junit.Assert.*;&lt;br/&gt;import static my.package.name.TestUtils.*;&lt;br/&gt;&lt;br/&gt;/* ... */&lt;br/&gt;&lt;br/&gt;screenshot(scene, getTestName());&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;By the way if you're using JavaFX you might be interested in the screenshot utility method. It's really simple:&lt;br/&gt;&lt;pre class="brush: java;"&gt;&lt;br/&gt;public static File screenshot(Scene scene, String fileName) throws Exception {&lt;br/&gt;BufferedImage image = (BufferedImage) scene.renderToImage(null);&lt;br/&gt;if (!fileName.endsWith(".png")) {&lt;br/&gt;fileName = fileName + ".png";&lt;br/&gt;}&lt;br/&gt;File file = new File(getScreenshotDir(), fileName);&lt;br/&gt;file.createNewFile();&lt;br/&gt;ImageIO.write(image, "png", file);&lt;br/&gt;return file;&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;(where obviously getScreenshotDir() returns a File folder where you want your screenshots generated. A decent default implementation is return new File(System.getProperty("java.io.tmpdir")); ...)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-4032348574354958151?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/4032348574354958151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/12/how-to-determine-junit-4-current-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4032348574354958151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4032348574354958151'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/12/how-to-determine-junit-4-current-test.html' title='How to determine the JUnit 4 current test name'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8109514755495456306</id><published>2009-11-08T12:29:00.000-08:00</published><updated>2010-09-17T13:49:12.836-07:00</updated><title type='text'>JavaFX Coding Conventions</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I've been writing a lot of JavaFX code over the last year. After some tweaking I've arrived at a style that I like a lot. I notice that even on my team there are some variations in how people format their code, so I thought I would document what I like in case this helps others get started. (I did a quick google search and didn't find any JavaFX coding convention documents anywhere. The closest thing I found was a &lt;a href="http://nick-software.blogspot.com/2009/10/coding-conventions-for-javafx-script.html"&gt;blog entry&lt;/a&gt;, but while it contains a lot of good advice, the style it recommends does not match the practice of the JavaFX team (or the Sun Java style) either).  Therefore, I thought I would document what I consider good JavaFX coding conventions.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Rather than post them here in a blog entry, I placed them in a Wiki page such that they can easily be improved and kept up to date as I get feedback and in case I change my mind :)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;You can find the coding conventions document here:&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;a href="http://wikis.sun.com/display/JavaFxCodeConv/Home"&gt;http://wikis.sun.com/display/JavaFxCodeConv/Home&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. I will be speaking at Devoxx in Antwerp, Belgium next week! Hope to meet some of you there!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8109514755495456306?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8109514755495456306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/11/javafx-coding-conventions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8109514755495456306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8109514755495456306'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/11/javafx-coding-conventions.html' title='JavaFX Coding Conventions'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5074912529552560766</id><published>2009-07-28T11:03:00.000-07:00</published><updated>2010-09-17T13:49:12.826-07:00</updated><title type='text'>NetBeans 6.7.1 is out - with JavaFX 1.2 support</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;NetBeans 6.7.1 was released yesterday, which in addition to a number of important bug fixes in various areas, also now includes support for JavaFX.&lt;br/&gt;&lt;br&gt;It looks very promising; the biggest problems I &lt;a href="http://blogs.sun.com/tor/entry/javafx_editing_tips"&gt;mentioned a couple of months ago&lt;/a&gt; are fixed. I no longer get any bogus or stale error messages.  And the preview pane seems to work - I'm not getting exceptions left and right. Also, the preview panel is docked into the navigator area - that seems like a good place for it.&lt;br/&gt;&lt;br&gt;Code completion and import management works as before - which means it might be a little surprising (see my &lt;a href="http://blogs.sun.com/tor/entry/javafx_editing_tips"&gt;old blog entry&lt;/a&gt; for tips), but it works.&lt;br/&gt;&lt;br&gt;Unfortunately, my two other pet peeves are still there: No toggle comment, and no mark occurrences jumping - which is extra problematic since there's no Find Usages for the JavaFX support. I took a quick peek at the sources, and adding it is trivial - so I submitted a &lt;a href="http://www.netbeans.org/issues/show_bug.cgi?id=169400"&gt;patch&lt;/a&gt;.&lt;br/&gt;&lt;br&gt;In the meantime, you can &lt;a href="http://blogs.sun.com/tor/resource/org-netbeans-modules-javafx-editor.nbm"&gt;download this .nbm plugin file&lt;/a&gt; and install it via &lt;b&gt;Tools &amp;gt; Plugins&lt;/b&gt; if you want to get these two features. Cmd-/ to toggle comments, and Ctrl-Up/Down to jump between the occurrences in the current file. Note that I couldn't create a separate plugin to do this - I hacked the existing JavaFX editor support. That's because the mark occurrences feature needs to access a method which is package private (and I didn't want to mess around with reflection - I can't spent time on this).  This unfortunately means though that you are using a hacked version of the FX editor module. If they release patch updates later you'll be replacing this functionality. But hopefully by then they will have applied the patch!&lt;br/&gt;&lt;br&gt;I noticed by the way that all the source code for the NetBeans JavaFX plugin is available right there in the public NetBeans Mercurial repository - so you can not only grab the source code and build it yourself, but you can fix and contribute patches to make the support better. I want a good JavaFX source formatter! Actually I'll even settle for just a simple indenter. Please, pretty please? P.S. I see that there is already a code formatter class in there - I added a breakpoint and stepped through it a bit but I couldn't see anything obvious, and I unfortunately can't spend any time on this, so hopefully somebody else can step up to the plate?&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtcRQ6rPI/AAAAAAAABYA/vhb07qouSmc/install-fxeditor.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5074912529552560766?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5074912529552560766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/07/netbeans-671-is-out-with-javafx-12.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5074912529552560766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5074912529552560766'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/07/netbeans-671-is-out-with-javafx-12.html' title='NetBeans 6.7.1 is out - with JavaFX 1.2 support'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtcRQ6rPI/AAAAAAAABYA/vhb07qouSmc/s72-c/install-fxeditor.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-4418393215730651017</id><published>2009-07-06T06:14:00.000-07:00</published><updated>2010-09-17T13:49:12.818-07:00</updated><title type='text'>Back from Vacation</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I'm back from a nice but short vacation. We didn't have a detailed itinerary - we just took one day at a time and decided where to head next. We spent several days in the old Gold Rush country in the Sierra foothills - there were many things to see, such as museums, mines and caverns, and a preserved whole gold rush town with original buildings, a no-cars main road and all employees wearing authentic clothing. From there we visited the central coast and went to several of the original Missions, and ended up seeing the 4th of July fireworks from the beach in Santa Barbara. While I was gone I see that &lt;a href="http://www.netbeans.org/community/releases/67/"&gt;NetBeans 6.7&lt;/a&gt;, and &lt;a href="http://www.virtualbox.org/"&gt;Virtual Box 3.0&lt;/a&gt; have both been released. Both should help me as I get back to work...&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrX8qRgCI/AAAAAAAAAnw/PTTXNRGSojs/kids-avilabeach.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-4418393215730651017?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/4418393215730651017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/07/back-from-vacation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4418393215730651017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4418393215730651017'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/07/back-from-vacation.html' title='Back from Vacation'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrX8qRgCI/AAAAAAAAAnw/PTTXNRGSojs/s72-c/kids-avilabeach.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8730980904346291668</id><published>2009-06-17T04:20:00.000-07:00</published><updated>2010-09-17T13:49:12.810-07:00</updated><title type='text'>New iPhone software - now with podcast speedup</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;img align="right" style="margin-left: 5px; margin-bottom: 5px" src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtxxbdBjI/AAAAAAAAA-U/ztmKyy763bs/speedtest.jpg" /&gt;&lt;br/&gt;The new iPhone 3.0 software was released a little under an hour ago.  The upgrade was trivial. I clicked the Check For Update a few minutes after the release, and it downloaded the new OS in around 3 minutes!  I recently switched ISPs so I have really good bandwidth now - but I had expected a lot of traffic on Apple's servers to slow things down.&lt;br/&gt;&lt;br&gt;The update looks really good. I tested a few of the things I have been looking forward to -- I personally don't care about the feature highlights listed on most sites, such as MMS, Copy and Paste, etc.&lt;br/&gt;&lt;br&gt;The first feature I've been waiting for is the ability in the browser to open a link in another window. With tabbed browsing I'm used to just ctrl-clicking on links such that pages load in the background, and when I'm done with the current page I go read the other tabs which by then are fully loaded.  On the iPhone on the other hand I haven't been able to do this, since there hasn't been a way to open a link without throwing away the page you're on. But in 3.0, it's there - just click and hold a link and you get the option to open the link in a new page. It's not as good as tabbed browsing - it instantly jumps to the new, not yet loaded page, but it's trivial to jump back and keep reading while the new page is loading.&lt;br/&gt;&lt;br&gt;The second feature I've been waiting for is improved iPod controls. The primary usage for my iPhone is as an iPod - while running, doing chores or driving - and I listen to a lot of podcasts. With 3.0, the scrubbing feature is improved - it's now a lot easier to jump to arbitrary points in the podcast. I like to listen to This Week in Technology for example, but I'm getting really, REALLY sick of the 5+ minutes of Audible commercials in each and every episode. This is the DVR generation -- if a commercial is longer than 30 seconds I'm going to start resenting you. In 2.0 it was difficult to either fast forward (too slow, then too fast) or jump to arbitrary points in the podcast. With 3.0 it works really well - I just place my thumb on the scrollbar and lean it to the right then left to tweak the final endpoint.&lt;br/&gt;&lt;br&gt;Another iPod improvement is the ability to play podcasts at a faster rate. For the &lt;a href="http://javaposse.com"&gt;Java Posse&lt;/a&gt; some volunteers (thank you!) set up a server which would download our podcasts, apply audio processing to speed up the podcast, and then release these as faster versions of our episodes - called the &lt;a href="http://tempoposse.herod.net/"&gt;Tempo Posse&lt;/a&gt;. This is no longer necessary with 3.0 - there's a button you can click to cycle between half speed, full speed and double speed playback:&lt;br&gt;&lt;br/&gt;&lt;a href="http://www.apple.com/iphone/how-to/index.html#ipod.podcast-and-audiobook-controls"&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuibijg4I/AAAAAAAABDw/3w6GOEFCdE0/ipodpodcastctrls.jpg" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;br&gt;I don't think this will run the Tempo Posse out of "business", because I looked at our download stats the other day and nearly half of all episodes are downloaded &lt;i&gt;outside&lt;/i&gt; of iTunes! Are there really that many Zune users? ;-)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8730980904346291668?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8730980904346291668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/06/new-iphone-software-now-with-podcast.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8730980904346291668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8730980904346291668'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/06/new-iphone-software-now-with-podcast.html' title='New iPhone software - now with podcast speedup'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtxxbdBjI/AAAAAAAAA-U/ztmKyy763bs/s72-c/speedtest.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-844002444566599913</id><published>2009-06-16T07:10:00.000-07:00</published><updated>2010-09-17T13:49:12.796-07:00</updated><title type='text'>Code Advice #16: Don't Encode Symbol Type in Variable Names!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;(See &lt;a href="http://blogs.sun.com/roller/page/tor?entry=code_advice"&gt;intro&lt;/a&gt; for a background and caveats on these coding advice blog entries.)&lt;br/&gt;&lt;br&gt;I came &lt;a href="http://groups.google.com/group/javaposse/browse_frm/thread/7b66fdb48619f77d"&gt;across&lt;/a&gt; a JavaWorld &lt;a href="http://www.javaworld.com/javaworld/jw-07-2008/jw-07-harmful-idioms.html"&gt;coding-advice article&lt;/a&gt; the other day. While the thread which led me there referenced the second point of the article, I couldn't get past the first one where the author argues that&lt;br/&gt;&lt;blockquote&gt;&lt;br/&gt;...a reader needs to know which items are local variables, which are fields, and which are method arguments. [...] It's likely best to use a simple naming convention to distinguish between these three cases.&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;&lt;br&gt;I couldn't disagree more!&lt;br/&gt;&lt;br&gt;His key argument seems to be that when you are reading code, it's important to know whether something is a field since when you read a method, you might suddenly see a reference to something you haven't seen before. To make his point he shows this graphic:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr6Yi0VTI/AAAAAAAAAtE/xNYOIRm3LhY/method-without-sigils.jpg" /&gt;&lt;br/&gt;&lt;br&gt;His improved version is here:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsLEyOLQI/AAAAAAAAAvw/hyPzZz5GB-I/method-with-sigils.jpg" /&gt;&lt;br/&gt;&lt;br&gt;I have a couple of problems with this.&lt;br/&gt;&lt;br&gt;First of all, why encode this information in the symbol name when IDEs will show this information automatically? NetBeans will show fields in greens, and statics in italics - and it will always be right, whereas the code might lie. Just like comments can get out of sync with reality, you could inline a field without remembering to change its name (especially if another developer did it without realizing the meaning of the variable prefix). Or if you get in the habit of seeing an "f" prefix as meaning field, what about local variables that legitimately should start with an f, such as "focus" ? Sure, the second variable should be capitalized, but what about typographically similar symbols like lowercase l and uppercase I?&lt;br/&gt;&lt;br&gt;Here's how the same function looks in NetBeans:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr7J79oJI/AAAAAAAAAtM/YoWHzlJA6Pc/netbeans-field-colors.jpg"&gt;&lt;br/&gt;&lt;br&gt;In addition to showing us the fields in clear green, the IDE also pointed out that this method is overriding another method (I hovered over the overrides glyph in the editor margin). The yellow line is warning us that this override doesn't have an @Override explicit annotation on it.&lt;br/&gt;Information about overrides is just as important as whether an identifier is a field.&lt;br/&gt;&lt;br&gt;Highlighting fields in green isn't specific to Java... We do this for many other languages - see some screenshots of&lt;br/&gt;&lt;a href="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtivgV4BI/AAAAAAAAA8Q/gTLZQG2vaV4/colorchart.jpg"&gt;Ruby&lt;/a&gt;, &lt;a href="http://blogs.sun.com/netbeansphp/entry/semantic_coloring_improved"&gt;PHP&lt;/a&gt;, &lt;a href="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtbg9UCbI/AAAAAAAAA7E/sjG8bHgM8O4/groovy.jpg"&gt;Groovy&lt;/a&gt;, etc.&lt;br/&gt;&lt;br&gt;Here's a snippet of JavaScript - notice how we have a reference to a global variable in there shown in green:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsPCcrBlI/AAAAAAAAAwQ/glAsoSf9YI4/colors-javascript.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;The key point here is that you shouldn't write your code to target reading code in black and white on paper.  You shouldn't print out your code at all! Reading code with an IDE lets you easily check any condition you encounter (and just like in a browser there is a little go-back icon in the editor toolbar which maintains a visit stack so you can easily pursue multiple ctrl-clicks to track something down and then easily go back).&lt;br/&gt;&lt;br&gt;There are some other conventions left over from the days of code written on tiny terminals and printed out on paper for review - such as the "maximum 72 characters per line" limit. There's no reason for that when using modern tools. If the code is more readable unwrapped at 100 characters, leave it that way rather than introduce arbitrary breaks in the middle. (Having said that, don't take this as an endorsement to write deeply nested methods, that's a sign of poorly thought out design.)&lt;br/&gt;&lt;br&gt;&lt;br/&gt;My second objection to the article is that it is not clear to me that knowing whether something is a field or not is the critical piece of information you need. I think the following questions are probably more important:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; What is the &lt;i&gt;meaning&lt;/i&gt; of the variable, and what is the &lt;i&gt;intended use&lt;/i&gt;?&lt;br/&gt;&lt;li&gt; Can it be null? Can it be negative?&lt;br/&gt;&lt;li&gt; What is its type?&lt;br/&gt;&lt;li&gt; Where else is it referenced?&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;And so on.  Just prepending an "f" on a field &lt;i&gt;reduces&lt;/i&gt; readability in order to avoid a simple lookup, when I believe you in general&lt;br/&gt;need to know more context anyway.&lt;br/&gt;And again, a tool can help you here. In NetBeans, hold down the Ctrl key (Command on the Mac) and hover over a symbol and you get help like&lt;br/&gt;this:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrg_K1TII/AAAAAAAAApA/wRCwQxmQgfI/doc-tooltip.jpg" /&gt;&lt;br/&gt;&lt;br&gt;(As a side note: I heard that at a Scala talk in JavaOne, Bill Venners was showing NetBeans through most of his talk, but he switched&lt;br/&gt;to Eclipse to show one feature: Pointing at symbols show the actual inferred types of scala identifiers. Scala is as you know a statically&lt;br/&gt;typed language, but uses a lot of type inference so the types aren't obvious from looking at the source. That's a very useful feature,&lt;br/&gt;and I thought I'd point out that NetBeans has this feature too -- using the exact same mechanism as the above; just hold the Cmd/Ctrl key&lt;br/&gt;and hover over a symbol, and you will see its type.)&lt;br/&gt;&lt;br&gt;Finally, the article makes a point that you probably want to distinguish parameters as well. I agree with that, but again not by changing&lt;br/&gt;the name of the parameters, but through color identification.  In Ruby, JavaScript, Python etc. we do that automatically in NetBeans - parameters are orange by default. For Java, it's not enabled by default (at one point it was, but somebody determined that the source code just looked too colorful, so the default color scheme was dialed back. I was working on Ruby at the time so my colors flew under the radar... and&lt;br/&gt;all GSF-based languages such as JavaScript, Python, Scala etc. now inherit that color scheme...)&lt;br/&gt;&lt;br&gt;You &lt;b&gt;can&lt;/b&gt; turn this on for Java as well. Just open the preferences, and for Fonts and Colors choose the Java language, then customize the Parameter Use and Parameter Declaration values:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOu3bmaDvI/AAAAAAAABGU/76NYf8GLN9M/netbeans-change-color.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Some languages like Ruby use sigils, where fields start with @, globals with $, symbols with : and so on. I don't have a problem with that&lt;br/&gt;since I don't think these are as obtrusive as -letters- in variable names.&lt;br/&gt;&lt;br&gt;If you are reading code on paper, or with an editor that doesn't support semantic highlighting, you are voluntarily handicapping yourself.&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-844002444566599913?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/844002444566599913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/06/code-advice-16-don-encode-symbol-type.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/844002444566599913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/844002444566599913'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/06/code-advice-16-don-encode-symbol-type.html' title='Code Advice #16: Don&amp;#39;t Encode Symbol Type in Variable Names!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr6Yi0VTI/AAAAAAAAAtE/xNYOIRm3LhY/s72-c/method-without-sigils.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6230456483404120860</id><published>2009-06-16T05:37:00.000-07:00</published><updated>2010-09-17T13:49:07.057-07:00</updated><title type='text'>Format All</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;One feature I'm missing from NetBeans is the ability to format a whole project, or a package or directory. Opening each file only to press Ctrl-Shift-F to format it is just too cumbersome.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Fortunately, this is trivial to fix. I wrote a simple plugin to do this, and uploaded it to the Plugin Portal:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;&lt;a href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=18365"&gt;http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=18365&lt;/a&gt;.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Once you've installed the plugin, you can right click on projects, or select a project, package (nonrecursive folder) or directory, and choose &lt;b&gt;Source | Format Files&lt;/b&gt;.&lt;br/&gt;&lt;br/&gt;TODO: picture&lt;br/&gt;&lt;br/&gt;TODO: team comment&lt;br/&gt;&lt;br/&gt;TODO: Generic, not java specific.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6230456483404120860?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6230456483404120860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/06/format-all.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6230456483404120860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6230456483404120860'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/06/format-all.html' title='Format All'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-3209447427972622836</id><published>2009-06-08T04:23:00.000-07:00</published><updated>2010-09-17T13:49:12.775-07:00</updated><title type='text'>The Authoring Tool</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;We lifted the veil on the new designer tool for JavaFX last week at the JavaOne 2009 conference. Here's a screenshot:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsdBVG-RI/AAAAAAAAAx8/7ZbmjIRNp9g/designertool3-small.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The tool made a number of appearances:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; First in the Tuesday keynote where my boss Nandini showed the basics of the tool.&lt;br/&gt;&lt;a href="http://link.brightcove.com/services/player/bcpid22207469001?bclid=24485121001&amp;bctid=25089918001"&gt;Video&lt;/a&gt;,&lt;br/&gt;starts at 23:08.&lt;br/&gt;&lt;br/&gt;&lt;li&gt; Then in the mobile keynote where Eric Klein showed the multiscreen support and mobile deployment.&lt;br/&gt;&lt;a href="http://link.brightcove.com/services/player/bcpid22207469001?bclid=24491680001&amp;bctid=25240109001"&gt;Video&lt;/a&gt;,&lt;br/&gt;starts at the beginning.&lt;br/&gt;&lt;br/&gt;&lt;li&gt; And finally in the Friday keynote where I got to do a longer 10 minute segment on the tool.&lt;br/&gt;&lt;a href="http://link.brightcove.com/services/player/bcpid22207469001?bclid=24589760001&amp;bctid=25474033001"&gt;Video&lt;/a&gt;,&lt;br/&gt;starts at 10:25.&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;The above video links just point to small chapters of each keynote; for full video replay go to&lt;br/&gt;&lt;a href="http://java.sun.com/javaone/2009/general_sessions.jsp"&gt;the keynote replay page&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I've scanned the blogosphere and twitter for comments on the tool and demos and the feedback is very positive.&lt;br/&gt;&lt;a href="http://sellmic.com/blog/2009/06/05/javafx-authoring-tool-demo-at-javaone-2009-with-video/"&gt;Here's&lt;/a&gt;&lt;br/&gt;a particularly detailed blog post with pictures and video snippets detailing the Friday demo.&lt;br/&gt;Now we just need to finish the feature set, fix the bugs and polish everything! It's been a sprint for the whole team to get to this point. But we're not building a demo! We're building a product! So we're not getting much of a rest, it's right back to work to finish this thing!&lt;br/&gt;&lt;br&gt;&lt;a href="http://ctpjava.blogspot.com/2009/06/javaone-2009-summary-friday-day-4.html"&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrXKBxXpI/AAAAAAAAAno/NSlGzaSNaTY/DSC_2752-small.jpg" border="0"&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;(Photo by &lt;a href="http://ctpjava.blogspot.com/2009/06/javaone-2009-summary-friday-day-4.html"&gt;Balz Schreier&lt;/a&gt;)&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. In case you missed it, Larry Ellison from Oracle went on stage and made several comments regarding JavaFX in case the acquisition should happen - here's one &lt;a href="http://www.javaworld.com/community/?q=node/3025"&gt;article&lt;/a&gt;, there are many others.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S.2. We had our fourth annual Java Posse BOF live recording session last week. It was a blast. Dick stayed up editing and releasing&lt;br/&gt;&lt;a href="http://javaposse.com/index.php?post_id=487315"&gt;the podcast&lt;/a&gt;&lt;br/&gt;the same night. If you're wondering what happened in the middle of the episode, where there's not much audio and a lot of laughing, that's me nearly drowning. I took a big swig of beer just as Joe made a joke; the beer went down the wrong tube, and then I was laughing so hard I couldn't breathe. My eyes were runny and I had beer all over my face and chest. Pretty embarrassing but reportedly also entertaining for others! Here's a &lt;a href="http://eppleton.sharedhost.de/blog/?p=684"&gt;photo&lt;/a&gt; from our get-together at a bar afterwards:&lt;br/&gt;&lt;br&gt;&lt;a href="http://eppleton.sharedhost.de/blog/?p=684"&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOr4cs9PMI/AAAAAAAAAsw/CcyT_Wyj4e8/javaposse2-small.jpg" border="0"&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;(Photo by &lt;a href="http://eppleton.sharedhost.de/blog/?p=684"&gt;Toni Epple&lt;/a&gt;)&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-3209447427972622836?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/3209447427972622836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/06/authoring-tool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3209447427972622836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3209447427972622836'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/06/authoring-tool.html' title='The Authoring Tool'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsdBVG-RI/AAAAAAAAAx8/7ZbmjIRNp9g/s72-c/designertool3-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5205995820216254517</id><published>2009-05-14T15:49:00.000-07:00</published><updated>2010-09-17T13:49:12.759-07:00</updated><title type='text'>Run Tests - Without Focus Loss!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I like unit tests - but running them can be painful. Commit-validation tests&lt;br/&gt;which bring up UI are obviously annoying, but even simple unit tests that&lt;br/&gt;get in the way. Does this look familiar?&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtWmY_gJI/AAAAAAAAA6Y/ONawFYDCdIs/junit-menubar.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The above menubar should look familiar to anyone on a Mac who's run unit tests for client side&lt;br/&gt;Java code. Not necessarily GUI tests, just any test where GUI libraries are loaded.&lt;br/&gt;&lt;br&gt;For &lt;i&gt;every testcase&lt;/i&gt;, the test runner fires up a new process, which tells&lt;br/&gt;OSX that "I'm graphical, give me focus!", and this steals the focus from the user.&lt;br/&gt;The test finishes quickly thereafter, the process quits - and then the test runner&lt;br/&gt;goes to the next test and the whole cycle starts over.&lt;br/&gt;&lt;br&gt;This is really painful because I like to have lots of tests. The Python editor support&lt;br/&gt;for Netbeans had &lt;a href="http://deadlock.netbeans.org/hudson/job/python/"&gt;600+ tests&lt;/a&gt;;&lt;br/&gt;the counts for the JavaScript support was higher, and&lt;br/&gt;the Ruby support even higher than that.  Whenever I run tests, I basically have to&lt;br/&gt;fight with my computer to get focus. Forget trying to write anything - every second&lt;br/&gt;or so my keystrokes get stolen as the next test grabs focus - so I've gotten in&lt;br/&gt;the habit of using the time for browsing, since I'm mostly reading, and I can handle&lt;br/&gt;clicking a link a second time if the first click got lost. But every now and then&lt;br/&gt;somebody will ping me on instant messaging - and it's maddening trying to respond while&lt;br/&gt;this is going on.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If this is sounding painfully familiar to you, I have good news. I've finally figured&lt;br/&gt;out a setup where this is no longer a problem!&lt;br/&gt;&lt;br&gt;The key discovery was that I can run my tests from another account on the system.&lt;br/&gt;With OSX' fast user switching, I can switch to the alternate account, launch the&lt;br/&gt;unit tests, and return back to my regular account where the tests won't interfere&lt;br/&gt;with display focus.  In order to let me run my tests from that other account, I&lt;br/&gt;just open a terminal there and &lt;code&gt;su -l tor&lt;/code&gt; in the shell to run all the&lt;br/&gt;commands (or NetBeans) as myself.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtINE2LuI/AAAAAAAAA4Y/V0qwNDumru8/user-switching.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This was a huge improvement since it removes the 10-30 minutes testrun downtime.&lt;br/&gt;But it had some disadvantages - first, I don't like running tests from a shell, and second,&lt;br/&gt;it's hard to know when things finish - and switching back and forth to check is annoying&lt;br/&gt;since I always have passwords on my accounts so the machine isn't open.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;So the second step was to set up &lt;a href="https://hudson.dev.java.net/"&gt;Hudson&lt;/a&gt; (a&lt;br/&gt;continuous integration server that is trivial to setup, and has a huge number of&lt;br/&gt;&lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Plugins"&gt;plugins&lt;/a&gt; which makes&lt;br/&gt;graphing code coverage, unit tests, findbugs results, integrating with version control&lt;br/&gt;systems etc trivial.  And it's &lt;a href="http://redsolo.blogspot.com/2007/11/hudson-embraces-python.html"&gt;&lt;br/&gt;not just for Java developers&lt;/a&gt;.)&lt;br/&gt;&lt;br&gt;Instead of logging into the other account&lt;br/&gt;for each test run, I log into the other account &lt;i&gt;once&lt;/i&gt;, and start up &lt;a href="https://glassfish.dev.java.net/"&gt;Glassfish&lt;/a&gt;&lt;br/&gt;with Hudson running. From now on I can access, configure and launch builds right&lt;br/&gt;from my own browser in my primary account. The &lt;i&gt;key step&lt;/i&gt; here is that Glassfish was&lt;br/&gt;started from the secondary account, so its primary display is associated with the builder account.&lt;br/&gt;When my build in Glassfish gets to the test stage, it's actually doing the display&lt;br/&gt;connection just as before, and if I log into the secondary account, I get the annoying&lt;br/&gt;focus flashing just as before. Look - the tested process is a user visible application in the dock:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOr5Tc60JI/AAAAAAAAAs8/G9aaOAH5msQ/junit-builder.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Another improvement which really helped is the "File System" version control plugin for Hudson.&lt;br/&gt;I want my Hudson builds to build my &lt;b&gt;current working copy&lt;/b&gt;. I don't want to&lt;br/&gt;check my code into Mercurial (even a local repository) just so that Hudson can&lt;br/&gt;grab the code and build it.  I want Hudson to build my current changes - my current&lt;br/&gt;edits. After all, I'm trying to test them before checking in!  And I discovered that&lt;br/&gt;there is a plugin which will let me do that - it's just&lt;br/&gt;a "file system" version control wrapper - which means you just point Hudson to your local&lt;br/&gt;directory, and off it goes. When the build starts, it makes a quick disk-copy of the&lt;br/&gt;source tree.  Even though Mercurial cloning is pretty fast, this is even faster.&lt;br/&gt;The disk copy also lets me specify a filter of files to exclude, so I had it ignore&lt;br/&gt;*.class files.  The diskcopy only takes 10 seconds or so before the build kicks&lt;br/&gt;off, and it's building a snapshot of my current in-progress, edited working copy!&lt;br/&gt;(It can also just update the copy based on changed filestamps - that's even faster,&lt;br/&gt;but it didn't seem to correctly delete removed files, so I let it start from scratch&lt;br/&gt;each time.)&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsqan8g8I/AAAAAAAAAz8/o87LPSKMmAA/hudson-filesystem.jpg" /&gt;&lt;br/&gt;&lt;br&gt;(Note - this plugin isn't in the catalog that you can browse right from within the&lt;br/&gt;Manage Plugins page within Hudson; I downloaded the .hpi file from&lt;br/&gt;&lt;a href="http://wiki.hudson-ci.org/display/HUDSON/File+System+SCM"&gt;http://wiki.hudson-ci.org/display/HUDSON/File+System+SCM&lt;/a&gt;&lt;br/&gt;and installed it in the Advanced tab.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The final ingredient is the new Hudson support in NetBeans 6.7. I don't even have&lt;br/&gt;to go to the browser to kick off build jobs. I just point NetBeans to my Hudson&lt;br/&gt;server once, and from then on I have full Hudson integration. When I want to&lt;br/&gt;run my tests I just select Launch job:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOr3VHl2BI/AAAAAAAAAso/cFNFu-8nFa0/hudson-runjob.jpg" /&gt;&lt;br/&gt;&lt;br&gt;I get notified if there's a problem:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOszxbeJlI/AAAAAAAAA1Y/7v6_bw-lIVg/hudson-failurenotify.jpg" /&gt;&lt;br/&gt;&lt;br&gt;I can look at failures and logs:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtsqaw9tI/AAAAAAAAA9w/uDIYIwq1oQo/hudson-show-failures.jpg" /&gt;&lt;br/&gt;&lt;br&gt;I can see build logs etc. directly in the output window, and hyperlinks warp to directly to files - to the files as they were in the build, not the current state:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuTlwiDfI/AAAAAAAABCI/NwEevBHt8WU/hudson-tabs.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;So to recap - with this setup, as I'm editing my code and I want to check the tests,&lt;br/&gt;I just right click on a node and say "Start Job" - and off it goes without bothering&lt;br/&gt;me at all - no more focus interruptions, and no more GUI windows popping up from&lt;br/&gt;interactive tests.  It's trivial to check the results. And it's even added one more&lt;br/&gt;level of convenience: I have multiple projects, each with unit tests, and from the&lt;br/&gt;IDE I couldn't have them all run with a single gesture. My build job does that.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I'm really stoked!  I was at one point able to do this when I was working on Linux&lt;br/&gt;and Solaris by setting my $DISPLAY variable and doing tricks with VNC. But that&lt;br/&gt;still required my tests to run in a console - which made interpreting the results sucky.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you haven't played with Hudson, try it - it's unbelievably easy to set up. Just download&lt;br/&gt;the Glassfish appserver and install it, download the Hudson .war file, and drop the hudson.war&lt;br/&gt;into the autodeploy directory of the appserver, and browse to &lt;code&gt;localhost:8080/hudson&lt;/code&gt;.&lt;br/&gt;Once you're there you can install&lt;br/&gt;plugins (under Manage hudson), point to your local installations of the JDK, ant,&lt;br/&gt;etc., and configure your build jobs by running scripts, launching maven scripts, writing&lt;br/&gt;ruby scripts, or obviously running ant scripts.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Some final miscellaneous tips:&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt; I don't want Time Machine to back up my builds trees, or Spotlight to&lt;br/&gt;index data in these directories, so I went to the TimeMachine preferences and had it&lt;br/&gt;exclude the &lt;code&gt;~/.hudson/jobs/&lt;/code&gt; directory.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt; I did the same thing for Spotlight - but unlike&lt;br/&gt;the Time Machine preferences, there was no checkbox to "Display Invisible Files" (e.g.&lt;br/&gt;files that start with a dot, such as &lt;code&gt;.hudson&lt;/code&gt;) in its file chooser. Here's a tip I didn't&lt;br/&gt;learn until recently: When a Mac filechooser has focus, you can press slash (/) - and this&lt;br/&gt;will open a text field where you can directly type the path it should jump to. I typed&lt;br/&gt;&lt;code&gt;/Users/tor/.hudson&lt;/code&gt; and from there I was able to select the jobs directory to exclude.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt; You might be tempted to skip the "filesystem version control" plugin and just have&lt;br/&gt;your build symlink to your working copy. Be careful; if Hudson is configured to delete&lt;br/&gt;older builds you might find yourself without your source code. I'm not saying it will&lt;br/&gt;follow your symlinks - Java has support for symlinks now - but I haven't tried it, and&lt;br/&gt;I &lt;b&gt;have&lt;/b&gt; been bitten by &lt;code&gt;ant&lt;/code&gt; in the past where it decided to follow symlinks in its&lt;br/&gt;zeal to delete recursively!&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;I recently discovered that you can reorder the build steps in a Hudson job. The little&lt;br/&gt;graphic to the left of a build task is a handle you can just drag to reorder!&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsqKJCf3I/AAAAAAAAAz4/LEQkrLQcGv8/hudson-drag.jpg" /&gt;&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5205995820216254517?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5205995820216254517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/05/run-tests-without-focus-loss.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5205995820216254517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5205995820216254517'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/05/run-tests-without-focus-loss.html' title='Run Tests - Without Focus Loss!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtWmY_gJI/AAAAAAAAA6Y/ONawFYDCdIs/s72-c/junit-menubar.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-3505823185933083796</id><published>2009-05-12T10:07:00.000-07:00</published><updated>2010-09-17T13:49:12.744-07:00</updated><title type='text'>...at least my house didn't burn down!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;As I was working yesterday my laptop felt kinda wobbly. I didn't think too much about it. But it started getting annoying. I lifted the laptop and looked under it to make sure my laptop wasn't accidentally sitting on top of a USB cable or something like that.  Nope.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;A little while later I was getting really annoyed - so I flipped the computer all the over to see what was up.  And to my surprise my battery was completely warped. It looks like it had "exploded" sometime this weekend. Check out how warped it is:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrW-bEbeI/AAAAAAAAAnk/R4IhLJVNVPc/warped-battery.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;A couple of years ago one of my Apple power supplies would make humming noices now and then, and one day I happened to be looking at it when it shot some sparks! Luckily I had a floor mat so any previous sparks hadn't ignited the carpet. I got that adapter replaced.  But I'm definitely thankful neither incident caused fires!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-3505823185933083796?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/3505823185933083796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/05/at-least-my-house-didn-burn-down.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3505823185933083796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3505823185933083796'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/05/at-least-my-house-didn-burn-down.html' title='...at least my house didn&amp;#39;t burn down!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrW-bEbeI/AAAAAAAAAnk/R4IhLJVNVPc/s72-c/warped-battery.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5805301434199011318</id><published>2009-04-29T10:42:00.000-07:00</published><updated>2010-09-17T13:49:12.726-07:00</updated><title type='text'>JavaFX editing tips!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;The NetBeans support for editing JavaFX isn't as mature as for other languages. After working with it for a little bit I've figured out a few things you might find helpful:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;One thing I do a lot when experimenting with FX is trying to comment out parts of the scenegraph to try different things.&lt;br/&gt;The way I comment/uncomment&lt;br/&gt;in NetBeans is using the Toggle Comment action -- Ctrl-/ or Cmd-/ depending on your platform. But in JavaFX that keystroke does nothing!&lt;br/&gt;It turns out they &lt;i&gt;have&lt;/i&gt; implemented Comment and Uncomment, just not toggle. So you can just use those actions instead (they're in&lt;br/&gt;the editor toolbar on the right.)&lt;br/&gt;&lt;br&gt;Or, if you're like me, you &lt;b&gt;really&lt;/b&gt; want Toggle Comment. Especially because it has a keybinding. In that case you can install&lt;br/&gt;&lt;a href="http://blogs.sun.com/tor/resource/netbeans-javafx-togglecomment.nbm"&gt;this plugin&lt;/a&gt; which adds toggle comment&lt;br/&gt;support for .fx files. It's a trivial module (just two small files (&lt;a href="http://blogs.sun.com/tor/resource/JavaFxToggleCommentAction.java"&gt;1&lt;/a&gt;,&lt;a href="http://blogs.sun.com/tor/resource/layer.xml"&gt;2&lt;/a&gt;)) so I'm hoping this will be&lt;br/&gt;included in the next version.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;The second issue I ran into is that the editor sometimes tells me my source code is wrong - and I'll stare at it without figuring out&lt;br/&gt;the problem.  Turns out - I'm often right. The code is okay, and the background parser is confused. At the&lt;br/&gt;&lt;a href="http://blogs.sun.com/tor/entry/java_posse_roundup_2009"&gt;roundup&lt;/a&gt; a number of other people ran into this bug.&lt;br/&gt;&lt;br&gt;Fortunately, there's a simple workaround for this - just select all (Ctrl-A), hit delete to wipe the file clean,&lt;br/&gt;and then undo (Ctrl-Z). You'll get your source&lt;br/&gt;file back, and the file should be (re)parsed correctly. It looks like there is some kind of incremental parsing bug. If you disagree&lt;br/&gt;with what the IDE error message is telling you, go ahead and try this workaround.&lt;br/&gt;&lt;br&gt;Here's an example. The editor is telling me I have an invalid assignment -- huh? There's no assignment there!&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrZq-izAI/AAAAAAAAAoE/53Ayg8VF6Jg/fx-wrong.jpg" /&gt;&lt;br/&gt;&lt;br&gt;If I select all, delete, paste, I get this - all better:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtsDX0EzI/AAAAAAAAA9s/M8FD8cObJ00/fx-right.jpg" /&gt;&lt;br/&gt;&lt;br&gt;An annoying bug, but once you know about it it's pretty trivial to work around it.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;At first I thought code completion was really broken. Let's say I wanted to insert a &lt;code&gt;DropShadow&lt;/code&gt;. Not knowing&lt;br/&gt;where it lives I would just type &lt;code&gt;DropS&lt;/code&gt; to get NetBeans to show it to me and also import it for me (and advantage&lt;br/&gt;of using code completion instead of just typing the name).  But that just didn't work - after typing &lt;code&gt;DropShadow&lt;/code&gt; and&lt;br/&gt;attempting code completion it wouldn't show me any matches!&lt;br/&gt;&lt;br&gt;Turns out there's another workaround for this. Just hit Ctrl-Space again!   In the Java editor, we distinguish between&lt;br/&gt;completing only the &lt;b&gt;imported&lt;/b&gt; classes and &lt;b&gt;all&lt;/b&gt; available classes. If you for example have imported a class named "Video"&lt;br/&gt;in your class and you code complete on "V", it will &lt;b&gt;not&lt;/b&gt; list "Vector" as a match (unless that class is also already imported) -&lt;br/&gt;it will only show the imported classes that match the V prefix. If you press Ctrl-Space a &lt;b&gt;second&lt;/b&gt; time, you get to see &lt;b&gt;all&lt;/b&gt;&lt;br/&gt;V matches. Of course, the code completion dialog tells you this - it says "Imported Items; Press Ctrl-Space Again for All Items" right&lt;br/&gt;there in the list.&lt;br/&gt;&lt;br&gt;However, this never seems to bite me when coding Java, because it does something else: If there is no match, it will proceed to do&lt;br/&gt;the all-items completion on its own - so most people don't have to think about it. The JavaFX editor on the other hand does not do this&lt;br/&gt;so you end up typing a prefix you know exist, complete, and - nothing.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOusgFCpDI/AAAAAAAABFM/r-V0WHPVePI/fx-empty-completion.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The workaround is simple - just press Ctrl-Space a second time when this happens, and voila - the class shows up and gets imported&lt;br/&gt;as well. Of course - the message at the bottom of the semi-empty code completion window says as much, but since you don't usually&lt;br/&gt;have to pay attention to this in Java (because it auto imports when there isn't a prefix match) you might have missed it:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtrljF1TI/AAAAAAAAA9o/90hO9-nEvEc/fx-fixed-completion.jpg" /&gt;&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;Import Management.  At first I would try to just type "DropShadow { }" - and the editor would complain that it doesn't&lt;br/&gt;know what I'm talking about. Alt-Shift-i, which imports the symbol under the caret doesn't do anything.&lt;br/&gt;But it turns out that Cmd-Shift-i, Fix All Imports, DOES work. So use that one instead. It doesn't give you the dialog&lt;br/&gt;you get in Java showing all the matches; instead it works its way sequentially through all missing symbols.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOruMPEL9I/AAAAAAAAArQ/HOJY7CuSlCc/fx-import.jpg" /&gt;&lt;br/&gt;&lt;br&gt;P.S. Fix Imports also cleans up unused imports.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;The Preview Panel seems to be a bit hit or miss. I loved using it, but I would occasionally get lots of exceptions from it,&lt;br/&gt;so now I only use it for simple scenegraph experiments and tend to just run instead to test stuff - it's been fast enough.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;The main thing I'm missing is keyboard navigation among occurrences. As you (hopefully) know, Ctrl-Up and Ctrl-Down lets you&lt;br/&gt;cycle through the yellow occurrences of a symbol when you're editing Java, JavaScript, Ruby, etc.  This is really handy since&lt;br/&gt;it gives you instant "find usages" within a file - just click on a symbol and ctrl-down to cycle through the references.&lt;br/&gt;JavaFX &lt;b&gt;has&lt;/b&gt; mark occurrences - but unfortunately they're missing the small code to iterate this through the keyboard.&lt;br/&gt;I thought I could just add that trivially along with the toggle-comment code plugin above, but unlike toggle comment which&lt;br/&gt;took 3 minutes to write, I couldn't see a simple (30 minutes or less) way to get access to the occurrences highlights from&lt;br/&gt;the outside, so I instead fired&lt;br/&gt;off an e-mail to the FX editor team - I'm crossing my fingers that they can get this in the next version!&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5805301434199011318?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5805301434199011318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/04/javafx-editing-tips.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5805301434199011318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5805301434199011318'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/04/javafx-editing-tips.html' title='JavaFX editing tips!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrZq-izAI/AAAAAAAAAoE/53Ayg8VF6Jg/s72-c/fx-wrong.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-3664235844597124147</id><published>2009-04-27T06:34:00.000-07:00</published><updated>2010-09-17T13:49:12.703-07:00</updated><title type='text'>Nice touch, Skype!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I work from home, so I rely heavily on Instant Messaging and IRC to communicate with my co-workers, and for video conferencing I use Skype.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I sometimes make typing mistakes. And if the typo is particularly embarrassing, to the extent that I want to fix it to show that I know better,&lt;br/&gt;I usually write something like this:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;12:00   I agre.&lt;br/&gt;12:00   s/agre/agree/&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Anybody with &lt;code&gt;vi&lt;/code&gt; experience or even &lt;code&gt;sed&lt;/code&gt; experience will recognize the second line as a search/replace command, so I'm really saying "I said agre but I meant agree".  It's reflex at this point - I'll do it for the most minor accident.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I usually only use Skype for video conferencing, not instant messaging. But I just discovered, by accident, that Skype does something wonderful. Instead of showing my substitution command, it &lt;i&gt;applies&lt;/i&gt; it to the previous line, instantly, on both sides of the conversation!  Look at this:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrv1d3HXI/AAAAAAAAArc/KsgDcTRRwuY/skype1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Ugh, typo, reflexively type &lt;code&gt;s/foo/bar&lt;/code&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOu6M6GcXI/AAAAAAAABGo/iQP6xTh5Jbk/skype2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Voila:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtorcqoPI/AAAAAAAAA9I/V2pKvAUe9rs/skype3.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Instead of adding my correction command to the log for the viewer to interpret, it just edited the previous command in place. If I can type this quickly enough, perhaps the reader won't notice!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Chatzilla, Adium, Others - Please please please do this too!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. On the topic of terminal conventions.... I like using ^H's as a "just kidding" device:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;12:00   Ok, I'll slap^H^H^H^H tell him about it.&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Anyone who's logged into terminals with wrong tty settings will recognize the ^H's as failed backspaces... And I &lt;i&gt;don't&lt;/i&gt; want IM clients processing these :)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-3664235844597124147?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/3664235844597124147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/04/nice-touch-skype.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3664235844597124147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3664235844597124147'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/04/nice-touch-skype.html' title='Nice touch, Skype!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrv1d3HXI/AAAAAAAAArc/KsgDcTRRwuY/s72-c/skype1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-7806177119901597106</id><published>2009-04-24T06:42:00.000-07:00</published><updated>2010-09-17T13:49:12.690-07:00</updated><title type='text'>Catchup</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;A lot of stuff is happening these days, so here are some quickies... is this what people use &lt;a href="http://twitter.com/tornorbye"&gt;Twitter&lt;/a&gt; for?&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt; My &lt;a href="http://blogs.sun.com/trond/"&gt;brother&lt;/a&gt; is visiting me these days. He's in town for the MySQL conference, where he &lt;a href="http://blogs.sun.com/trond/entry/presentation_at_the_mysql_users"&gt;presented&lt;/a&gt; his work on &lt;a href="http://en.wikipedia.org/wiki/Memcached"&gt;memcached&lt;/a&gt;. He's also a huge fan of Solaris, so I'm now running OpenSolaris on my desktop machine. It's fun to see how user friendly the (always powerful) operating system has gotten. And his blog entries like &lt;a href="http://blogs.sun.com/trond/entry/debugging_memcached_udf_for_mysql"&gt;this&lt;/a&gt; and &lt;a href="http://blogs.sun.com/trond/entry/adding_debugging_functionality_into_your"&gt;this&lt;/a&gt; take me back to my first job at Sun - working on the Solaris debugger UI. Good memories.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;&lt;img align="right" style="margin: 5px" src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrWDIgE0I/AAAAAAAAAnc/B9N_RKNac5w/kids_at_sun.jpg"&gt;&lt;br/&gt;&lt;img align="right" style="margin: 5px" src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrV6Vj7cI/AAAAAAAAAnY/ZEKByz6qkh4/kids_at_sun2.jpg"&gt;&lt;br/&gt;Yesterday was "Take Your Daughters and Sons to Work Day", so I brought my kids down to the Santa Clara campus. They had a great time. After "working" in an office while I was on my laptop, we walked around the campus, they met my boss, and I'm sure the highlight for them was having lunch in the Sun cafeteria - which even had a special kids menu for the day. In our walk through some of the buildings we came across a pool table where they got to try pool for the first time.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;I had the honor of being interviewed on the &lt;a href="http://blogs.sun.com/theplanetarium/tags/planetcast"&gt;PlanetCast&lt;/a&gt; a week or two ago. That's the third episode of the podcast, but do yourself a favor and listen to the first two - with John Rose on the DaVinci Machine Project, and James Gosling on Java and JavaFX.  I've had to drive down to the Valley almost every day the last couple of weeks for meetings, so the timing of my discovery of the PlanetCast couldn't have been better!&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;&lt;a href="http://1.bp.blogspot.com/_NxSWeAWtdNg/SfE-Jywu5RI/AAAAAAAABlM/Be9bJyoMBAU/s1600-h/IMG_1010.JPG"&gt;&lt;br/&gt;&lt;img align="left" style="margin: 5px" src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuAK8kmjI/AAAAAAAAA_4/vPX4YUX_pmY/tesla2.jpg" border="0"&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;My friend Carl Quinn just got his &lt;a href="http://www.teslamotors.com/"&gt;Tesla&lt;/a&gt; - an all electric super sporty car. He's waited two years or so since he ordered it and they're just now coming off the assembly line. When we got together for a podcast recording session Wednesday night he brought the car, and took each of us for a spin around the block. Wow! It felt like like getting a ride in a fighter jet - but while the acceleration force was amazing, unlike a jet the all electric motor is unbelievably silent. I can't wait for cars like these to get to mass market!  There are some pictures of our rides on &lt;a href="http://quaintjackie.blogspot.com/2009/04/carls-new-tesla.html"&gt;Jackie's blog&lt;/a&gt;, and Joe has a lot more &lt;a href="http://www.flickr.com/photos/joenuxoll/sets/72157617107562108/"&gt;pictures&lt;/a&gt; and even some &lt;a href="http://www.youtube.com/watch?v=rkbWoeJ6Hrg"&gt;video&lt;/a&gt;.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br clear="all"&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt; The Ruby support in NetBeans 6.7 is coming along nicely.  Erno just announced that preliminary Ruby 1.9 support is in the builds now. More details on that in &lt;a href="http://blogs.sun.com/emononen/entry/ruby_1_9_support"&gt;his blog entry&lt;/a&gt;.  And in &lt;a href="http://blogs.sun.com/emononen/entry/type_inference_for_constants"&gt;another blog entry&lt;/a&gt; he's describing work he and Martin did recently to improve the type inference support in NetBeans. Here's some Ruby 1.9 goodness:&lt;br/&gt;&lt;br&gt;&lt;img src="http://blogs.sun.com/emononen/resource/ruby-editor-19.png"&gt;&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt; Finally, we're using JIRA as the issue tracker for the JavaFX project, so I've been using &lt;a href="http://code.google.com/p/cubeon/"&gt;Cubeon&lt;/a&gt; for NetBeans a lot recently to handle querying and updating issues from within the IDE. I don't have Eclipse envy, but I'm impressed by their Mylyn project which looks both nice and useful, so I definitely welcome task oriented flow into NetBeans as well. In addition to connecting to repositories like Bugzilla, JIRA and Trac, Cubeon adds some basic support for tasks (e.g. when you "activate" one task, all breakpoints you set in the debugger get grouped and associated with this task and so on), so I'll be playing more with that. I'm using a daily snapshot rather than the most recent published version, and I'm pretty happy with it. I'll probably have more to say about this in another blog entry as I get more experience with it.&lt;br/&gt;&lt;br&gt;&lt;a href="http://cubeon.googlecode.com/files/home.PNG"&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtizpHCNI/AAAAAAAAA8U/SoySmutZ18w/cubeon.jpg" border="0"&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-7806177119901597106?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/7806177119901597106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/04/catchup.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7806177119901597106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7806177119901597106'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/04/catchup.html' title='Catchup'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrWDIgE0I/AAAAAAAAAnc/B9N_RKNac5w/s72-c/kids_at_sun.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-4521101289450577941</id><published>2009-04-07T12:38:00.000-07:00</published><updated>2010-09-17T13:49:12.672-07:00</updated><title type='text'>Add Effects to the right Container!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;The Flubber application I &lt;a href="http://blogs.sun.com/tor/entry/javafx_text_component"&gt;described earlier&lt;/a&gt; has an old stop-watch style timer with second and minute hands:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrzTZP58I/AAAAAAAAAr4/0wbRk2xl--Q/clock1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Making the clock hand move was trivial using value binding and a rotation transform on the hand graphics object:&lt;br/&gt;&lt;pre class="brush: javafx;"&gt;&lt;br/&gt;transforms: Rotate {&lt;br/&gt;angle: bind (360.0 / 60 * minutes) - 90.0&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Since we are using a binding expression, setting the &lt;code&gt;minutes&lt;/code&gt; variable anywhere (and yes, assigning to it!) will cause the hand angle to be recomputed and the graphics updated.&lt;br/&gt;&lt;br&gt;Anyway - once we had the clock moving, the first thing we wanted to do was improve the look of the clock by adding a drop&lt;br/&gt;shadow. That was trivial; all we had to add was this:&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: javafx;"&gt;&lt;br/&gt;effect: DropShadow {&lt;br/&gt;offsetX: 5&lt;br/&gt;offsetY: 5&lt;br/&gt;color: Color.BLACK&lt;br/&gt;radius: 10&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;That looked pretty good:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOt2VkcsRI/AAAAAAAAA-0/3GIurSkOdfw/clock2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;But look what happened when we let the timer run... Where is the light source?&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtaQHog3I/AAAAAAAAA64/EpP57WmaLQE/clock3.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;What's happening here is that the drop shadow is rotating with the hand. Not what we want.&lt;br/&gt;We were all learning JavaFX that day, so we hacked it, using the following code:&lt;br/&gt;&lt;br/&gt;&lt;pre class="brush: javafx;"&gt;&lt;br/&gt;effect: DropShadow {&lt;br/&gt;offsetX: bind Math.sin(Math.toRadians(handAngle + 45)) * 5.0&lt;br/&gt;offsetY: bind Math.cos(Math.toRadians(handAngle + 45)) * 5.0&lt;br/&gt;color: Color.BLACK&lt;br/&gt;radius: 10&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;Now, the drop shadow offset moves along with the rotation such that the shadow always appears in the right place.&lt;br/&gt;It worked, and we moved on.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Now that I understand JavaFX and the scenegraph a bit better I realize that this approach is wrong - there's a much simpler solution!&lt;br/&gt;We don't want to apply the drop shadow to the Path object directly, since the path is what we are rotating with our minute angle.&lt;br/&gt;Instead, we should simply move the effect out to the surrounding parent. That will apply the drop shadow &lt;b&gt;after&lt;/b&gt; the shape&lt;br/&gt;has been rotated.&lt;br/&gt;Doing that, we can set our drop shadow initialization back to the original simple 5,5 delta, and we get exactly the result we want:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtRtF9V0I/AAAAAAAAA5w/5NQFcotayQw/clock4.jpg" /&gt;&lt;br/&gt;&lt;br&gt;So, think about which node you apply effects to! And by the way, the effects framework is really fun to play with - you should definitely&lt;br/&gt;explore &lt;code&gt;javafx.scene.effect.*&lt;/code&gt; !&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-4521101289450577941?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/4521101289450577941/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/04/add-effects-to-right-container.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4521101289450577941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4521101289450577941'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/04/add-effects-to-right-container.html' title='Add Effects to the right Container!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrzTZP58I/AAAAAAAAAr4/0wbRk2xl--Q/s72-c/clock1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-987193065433592456</id><published>2009-03-23T02:51:00.000-07:00</published><updated>2010-09-17T13:49:12.651-07:00</updated><title type='text'>JavaFX Text Component</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;At the &lt;a href="http://blogs.sun.com/tor/entry/java_posse_roundup_2009"&gt;Roundup&lt;/a&gt; a few weeks ago we rewrote the old Swing &lt;a href="http://dickwallsblog.blogspot.com/2006/09/jflubber-reloaded.html"&gt;JFlubber&lt;/a&gt; application to JavaFX. We had a brand new graphical design done in PhotoShop, and we hooked up the functionality with some swanky effects. I might get into that in another blog entry.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;But one challenge we ran into was that of displaying text. In the Flubber application we need to have an editable text area where flub times are automatically inserted and the user can add additional comments. JavaFX makes it easy to throw some simple text in a design, but edit, scroll, and so on? Not yet.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Proper GUI components for JavaFX is coming. But in the mean time, there are some tricks you can use.  Put simply, you can use a Swing text area, but without looking like Swing. Here's how. First, create a JavaFX scenegraph node for the Swing text component:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; textPane = &lt;span class="keyword"&gt;new&lt;/span&gt; JTextPane();&lt;br/&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; scrollPane = &lt;span class="keyword"&gt;new&lt;/span&gt; JScrollPane(textPane);&lt;br/&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; text: SwingComponent = SwingComponent.wrap(scrollPane);&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Let's see how that looks:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsAbdx_jI/AAAAAAAAAt0/h2h-otAuueM/fxtext1.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;b&gt;Ugh&lt;/b&gt;!! Not what we want. Obviously, we don't want the text area to look like Swing... we have a nice background as part of the PhotoShop design that we want to use under below the text.  But that's not hard to fix.  Java colors have an alpha channel, for opacity. We can use a completely transparent background on the text area to make it just pass through its background (and we have to make the scroll pane nonopaque as well):&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;textPane.setBackground(&lt;span class="keyword"&gt;new&lt;/span&gt; java.awt.Color(0,0,0,0)); &lt;span class="comment"&gt;// 0 opacity =&amp;gt; 100% transparent!&lt;/span&gt;&lt;br/&gt;textPane.setForeground(java.awt.Color.WHITE);&lt;br/&gt;textPane.setCaretColor(java.awt.Color.WHITE);&lt;br/&gt;scrollPane.setOpaque(&lt;span class="keyword"&gt;false&lt;/span&gt;);&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Let's try again:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuJjQTXII/AAAAAAAABA8/EJNyt7UCHM4/fxtext2.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;Much better! But there is still a gray rectangle on top of the graphics, placed there by the border of the scrollpane. We can get rid of that too:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;scrollPane.setBorder(&lt;span class="keyword"&gt;new&lt;/span&gt; EmptyBorder(&lt;span class="keyword"&gt;new&lt;/span&gt; Insets(0,0,0,0)));&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtLg8sXGI/AAAAAAAAA5A/skcjmYSPQJc/fxtext3.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;Now we're talking! But the font is too small. Dick told me he wants to use a Courier font. So let's try this one:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;textPane.setFont(&lt;span class="keyword"&gt;new&lt;/span&gt; java.awt.Font(&lt;span class="string"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;American Typewriter&lt;/span&gt;&lt;span class="string"&gt;&amp;quot;&lt;/span&gt;, 0, 14));&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Here's what we get:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtEuCjSeI/AAAAAAAAA30/33zcPyyNQ28/fxtext4.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;Ewwwwww!  The font is not antialiased.  I tried a bunch of things to fix this -- for example setting antialias rendering hints on the component itself, setting the aa system property, etc. It looks like there is a bug here in that the rendering hints aren't picked up properly for the wrapped Swing components. But I did find a workaround that works: We can set the antialiasing rendering hints directly on the graphics object ourselves. That means we need to get involved in the painting of the component itself, but luckily that's trivial. Instead of creating a new JTextPane, we'll create a simple subclass of it where we override the paint method to add the rendering hints:&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; java.awt.Graphics;&lt;br/&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; java.awt.Graphics2D;&lt;br/&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; java.awt.RenderingHints;&lt;br/&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; javax.swing.JTextPane;&lt;br/&gt;&lt;br/&gt;&lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;class&lt;/span&gt; AntiAliasedTextArea &lt;span class="keyword"&gt;extends&lt;/span&gt; JTextPane&lt;br/&gt;{&lt;br/&gt;@Override&lt;br/&gt;&lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;void&lt;/span&gt; paint(Graphics g)&lt;br/&gt;{&lt;br/&gt;Graphics2D g2d = (Graphics2D) g;&lt;br/&gt;g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,&lt;br/&gt;RenderingHints.VALUE_TEXT_ANTIALIAS_ON);&lt;br/&gt;&lt;span class="keyword"&gt;super&lt;/span&gt;.paint(g);&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;Now we can just change&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; textPane = &lt;span class="keyword"&gt;new&lt;/span&gt; JTextPane();&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;to&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; textPane = &lt;span class="keyword"&gt;new&lt;/span&gt; AntiAliasedTextPane();&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;and we get this:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuKNPVZ2I/AAAAAAAABBA/qeZOLU-05-Y/fxtext5.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;Ta-da!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;But there is one more problem... What if we add a lot of text:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr1dt0PiI/AAAAAAAAAsU/731xjXD5tHY/fxtext6.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;Scrollbars! We don't want those. This text pane won't be used for much text, so you can just move the caret around like in a text field to navigate the overflow content.  So let's turn off the scrollbars:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);&lt;br/&gt;scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;and with that, the text pane behaves exactly the way we want.  Now you can manipulate text in the usual way: &lt;code&gt;textPane.setText(string)&lt;/code&gt;, &lt;code&gt;textPane.getText()&lt;/code&gt;, etc.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;While we're at it, let's fix the selection colors as well such that when you select text you don't get the telltale Swing light blue:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;textPane.setSelectionColor(new Color(255, 255, 255, 50));&lt;br/&gt;textPane.setSelectedTextColor(new Color(255, 255, 255, 255));&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Note again how we can use transparency on this colors to give a nice glass effect on the selection (I also bumped up the font size):&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsp145YxI/AAAAAAAAAz0/sjm73yMo86k/fxtext7.jpg"&gt;&lt;br/&gt;&lt;br&gt;Hopefully these tricks will help you with your text needs until we have real JavaFX components...&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-987193065433592456?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/987193065433592456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/03/javafx-text-component.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/987193065433592456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/987193065433592456'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/03/javafx-text-component.html' title='JavaFX Text Component'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsAbdx_jI/AAAAAAAAAt0/h2h-otAuueM/s72-c/fxtext1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6000665016785791102</id><published>2009-03-16T03:37:00.000-07:00</published><updated>2010-09-17T13:49:12.622-07:00</updated><title type='text'>NetBeans Screenshot of the Week 42: JavaScript Native Interface</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;At the &lt;a href="http://blogs.sun.com/tor/entry/java_posse_roundup_2009"&gt;Roundup&lt;/a&gt; last week I talked to&lt;br/&gt;&lt;a href="http://twitter.com/kebernet"&gt;Robert Cooper&lt;/a&gt;, who's doing a lot of interesting work with GWT (Google Web Toolkit). In GWT (which compiles Java to JavaScript), you can embed JavaScript directly within the Java files inside comments with special markers. Robert mentioned that IntelliJ has a nice feature for GWT programmers where your native JavaScript snippets get JavaScript highlighting etc.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I figured that would be a trivial thing to add to NetBeans with our language embedding infrastructure. Sure enough, &lt;a href="http://blogs.sun.com/tor/resource/jsni-patch.diff"&gt;the patch&lt;/a&gt; just adds 13 lines of code. Here's a screenshot - showing JavaScript (regular expressions etc) inside Java code (with packages etc) - it's inside comments that start and end with &lt;code&gt;-{&lt;/code&gt; and &lt;code&gt;}-&lt;/code&gt;:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsTcrXGYI/AAAAAAAAAww/hSha6kHeppg/jsni.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you want this functionality in your own 7.0 build, just download &lt;a href="http://blogs.sun.com/tor/resource/org-netbeans-modules-java-lexer.nbm"&gt;this module nbm&lt;/a&gt;, or apply &lt;a href="http://blogs.sun.com/tor/resource/jsni-patch.diff"&gt;the patch&lt;/a&gt; to your own build.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6000665016785791102?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6000665016785791102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/03/netbeans-screenshot-of-week-42.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6000665016785791102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6000665016785791102'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/03/netbeans-screenshot-of-week-42.html' title='NetBeans Screenshot of the Week 42: JavaScript Native Interface'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsTcrXGYI/AAAAAAAAAww/hSha6kHeppg/s72-c/jsni.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-7694778687469634063</id><published>2009-03-12T10:53:00.000-07:00</published><updated>2010-09-17T13:49:12.598-07:00</updated><title type='text'>Java Posse Roundup 2009</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I just got back from the Java Posse Roundup 2009.   It was our third year (blog entries from &lt;a href="http://blogs.sun.com/tor/entry/posse_roundup_pictures"&gt;2007&lt;/a&gt;, &lt;a href="http://blogs.sun.com/tor/entry/roundup_roundup"&gt;2008&lt;/a&gt;), and therefore I can add "as usual" when I state that it was a wonderful time.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This year's topic was "developer productivity", which is obviously a passion of mine, so I found all the technical sessions thoroughly enjoyable. We recorded all of them so they will be released slowly through the regular podcast &lt;a href="http://www.javaposse.com"&gt;channel&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I was able to redeem myself from last year's &lt;a href="http://www.youtube.com/watch?v=h_mDjbWIMso&amp;feature=channel_page"&gt;skiing disaster&lt;a /&gt; but &lt;b&gt;not&lt;/b&gt; falling doesn't make very compelling video...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Another highlight is the lightning talks. This year we had two hours of lightning talks every night. We'll be releasing those on a quicker schedule as YouTube videos in our &lt;a href="http://www.youtube.com/javaposse"&gt;YouTube channel&lt;/a&gt;. I can recommend Barry Hawkins' &lt;a href="http://www.youtube.com/watch?v=U6fwxVG0wRI&amp;feature=channel_page"&gt;talk&lt;/a&gt; as a starter. The nice thing about lightning talks are that they are short so go ahead, give it a try!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In order to enforce the 5 minute rule for lightning talks, we wrote a little timer app, as seen in this picture:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuD5-HcuI/AAAAAAAABAU/EGlcBD3C2NE/fxtimer.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;The laptop on the left is running our downcounter. It starts at 5 minutes, and when it gets down to 0 it plays a sound effect which politely asks the user to, ehm, stop.   We wrote this app as a collaboration on the first day of the conference, during the language dojos. We had 3-4 sites where different people studied Scala, Groovy, Python, Fan and JavaFX, according to their interests.  In the JavaFX group we played around with the language in the morning, and then decided to build something real - the countdown timer. We needed a sound effect to play when the timer expires, so we held up one of our conference audio recorders and all at once yelled "Shut Up!" into it.  In the room next door Dick Wall had just started talking about Scala, and our brief recording session apparently caused some confusion...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. There are a lot of &lt;a href="http://www.flickr.com/search/?z=t&amp;w=all&amp;q=JPR09"&gt;pictures from the Roundup&lt;/a&gt; on flickr.&lt;br/&gt;The below are by &lt;a href="http://www.flickr.com/photos/joenuxoll/"&gt;Joe Nuxoll&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Crested Butte, Colorado by night:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtNMOvegI/AAAAAAAAA5M/EM7ccJruaA0/jpr09_crestedbutte.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The first day of the Open Conference we held a languages-on-the-JVM dojo. This is a picture of those of us playing with JavaFX:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOt5agnPGI/AAAAAAAAA_I/8W5IRgPEb-s/jpr09_dojo.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The lightning talks schedule for the Tuesday night:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsBz4H3KI/AAAAAAAAAuI/cXGLYyWQK3M/jpr09_talks1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;On Thursday we had a progressive dinner where each household served one course for the other participants. Carl made Indian Style chicken wings and Ido is getting ready to serve:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsKLi0SMI/AAAAAAAAAvo/OemLCLgkeFU/jpr09_dinner.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Dick and Dianne talking during the progressive dinner.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOr4qlhxhI/AAAAAAAAAs0/GmZHoBhADNA/jpr09_dinner2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-7694778687469634063?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/7694778687469634063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/03/java-posse-roundup-2009.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7694778687469634063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7694778687469634063'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/03/java-posse-roundup-2009.html' title='Java Posse Roundup 2009'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuD5-HcuI/AAAAAAAABAU/EGlcBD3C2NE/s72-c/fxtimer.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8601929872124740398</id><published>2009-03-11T11:47:00.000-07:00</published><updated>2010-09-17T13:49:12.579-07:00</updated><title type='text'>New Job</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Apologies for the recent blog silence for me. It's not that I've been slacking off. Quite to the contrary!&lt;br/&gt;The biggest news is that I've changed teams: I'm now working on JavaFX! And more specifically, the designer tool.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsrg1b8zI/AAAAAAAAA0M/fG351EJ5mEY/Javafx-logo.jpg" align="right" /&gt;&lt;br/&gt;If you don't know what JavaFX is, you're probably reading my blog because you're interested in Ruby, Python or the various other languages for NetBeans I've been involved with. If so, fear not - NetBeans language support is in great hands - Erno just improved the &lt;a href="http://blogs.sun.com/emononen/entry/code_completion_for_dynamic_finders"&gt;Rails dynamic finders code completion&lt;/a&gt; for Ruby for example. Of course, as an open source project we can always use more contributors! I've received a bunch of patches for the Python support recently which I've been happy to apply immediately. Keep 'em coming!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Briefly, JavaFX is a new UI stack for Java which makes it trivial to build pretty, dynamic and interactive UIs. While Java has always made it easy to target multiple operating systems, JavaFX makes it easy to target the completely separate platforms of desktop, web and mobile. If you haven't looked into it, you should.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;JavaFX has its own language, JavaFX Script. It has some language level features which makes it really suited to building UI applications - from something simple like a literal for durations (so you can write &lt;code&gt;2m&lt;/code&gt; or &lt;code&gt;5s&lt;/code&gt; or &lt;code&gt;250ms&lt;/code&gt; in your source code), to something advanced like variable bindings which give you all of the power of traditional property change listeners, but without the pain (and it's more powerful than that - you can for example bind the rotation angle of a clock hand to an expression which computes the angle from the current time, and whenever the time variable changes the clock hand rotation is updated.)   As a Java developer (and a Ruby and Python and JavaScript coder as well) I can truly say I've seen some things in JavaFX Script that I would like to see in other languages. I might talk about that in an upcoming blog entry.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you're one of the alternate-languages-on-the-JVM people, I think you should seriously look into adding a binding layer for the JavaFX platform to your language. Libraries like Groovy Swingbuilders (and similar libraries for Ruby etc) have made Swing more accessible, but at the end of the day you're still dealing with Swing. If you want to add drop shadows, transition animations etc. a JavaFX DSL would be a much better approach. And besides, we're firing on all 256 cylinders on the JavaFX platform -- from the base Java platform (adding modularity so we can provide a barebones FX runtime), to the graphics system, to components, to the language, and up to the designer tool! I think it's going to shake up the RIA space - which is why I wanted to be part of it.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I promise my next blog entry won't be long in waiting, I've got a bunch of things queued up!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8601929872124740398?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8601929872124740398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/03/new-job.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8601929872124740398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8601929872124740398'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/03/new-job.html' title='New Job'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsrg1b8zI/AAAAAAAAA0M/fG351EJ5mEY/s72-c/Javafx-logo.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-131382932772752240</id><published>2009-01-13T02:52:00.000-08:00</published><updated>2010-09-17T13:49:12.564-07:00</updated><title type='text'>NetBeans Screenshot of the Week #41: Type Assertions</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Python and Ruby are dynamically typed languages. We have a lot of heuristics in our editors to figure out the types - tracking assignments, analyzing your database migrations, etc - to help code completion, go to declaration and other IDE features work correctly. And &lt;a href="http://blogs.sun.com/martink/"&gt;Martin Krauskopf&lt;/a&gt;, who owns the Ruby editor now, has been improving the type inference for Ruby a lot lately.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;However, there are cases where we just can't help.  What if you're writing a brand new method you haven't called from anywhere, and you're trying to access methods on one of your parameters? We don't know the type of the parameter.  In that case, NetBeans will provide "fallback code completion" - it will list ALL methods across ALL known classes in your project, libraries and current platform.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you're looking for the documentation or parameters for a specific method - that's useful - after typing 2-3 characters you've typically narrowed the result set down to a handful of methods and you can pick the one you're looking for.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;But what if you're not sure what the method is called? That exact scenario happened to me a couple of days ago. I was writing some Python code to do some string manipulation, and not being very familiar with Python I wanted to know what the equivalent of Java's &lt;code&gt;indexOf&lt;/code&gt; method was in Python. I knew that the parameter in my method was a String, but I didn't have a way of telling the IDE that.  I applied my usual workaround of adding a line above the current call:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;x = ""&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;and then I could invoke &lt;code&gt;x.&lt;/code&gt; to see the methods available for a String.  However, that's definitely not a good way to do it. What if I forget to remove my fake assignment? (Yep, I did that too. I couldn't figure out why my code wasn't working until I debugged and realized I was clearing out the parameter with a bogus assignment... Doh!)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The "obvious" solution for this is supporting type assertions.  We've had those for a long time in the Ruby editor&lt;br/&gt;(&lt;a href="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsWvK5ruI/AAAAAAAAAxM/0csby_a7kO0/ruby-types.jpg"&gt;picture&lt;/a&gt;), and obviously for JavaScript using the &lt;code&gt;@type&lt;/code&gt; and &lt;code&gt;@param {&lt;i&gt;type&lt;/i&gt;}&lt;/code&gt; syntax. And the PHP editor just added support for type assertions as well (more &lt;a href="http://blogs.sun.com/netbeansphp/entry/defining_variable_type_in_a"&gt;here&lt;/a&gt; and &lt;a href="http://blogs.sun.com/netbeansphp/entry/defining_a_variable_type_in"&gt;here&lt;/a&gt;).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I've just added this for the Python editor as well. But I've gone one step further which I think makes the feature much more obvious, and easy to use.  In code completion, if the editor detects that you are attempting to complete on a simple variable (as opposed to for example a complicated expression), and the type of that variable cannot be resolved, then we add a new special code completion item at the top of the list. Here's what it says (and a more detailed explanation in the documentation popup):&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuFD0mBaI/AAAAAAAABAc/Tm4CqQDL2Kg/specify-type1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;As soon as you press enter, the IDE will insert a special comment referencing the variable you were completing on, and automatically invoke code completion again to complete on the type statement:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOr91Sc8aI/AAAAAAAAAtg/fwNd_q_Q2NE/specify-type2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The contents of this list has two parts: First, it lists the pseudo-types for many of the core builtin types, like ints, strings, lists and tuples. After that it will list all the known types in the system, such as the user and library classes. If you select one of these and try code completing the original expression again, you can now see that the type resolver knows what to do:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOs3gVTRxI/AAAAAAAAA14/fA9A_T4LCCk/specify-type4.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;A couple of notes about this. First, note that the type assertions are just comments in your source. You can delete them - they are merely an aid to the IDE. Not only code completion uses these - go to declaration for example will also be more accurate if it is explicitly told the type of a variable it cannot figure out.  You can also use multiple type assertions within a method in case the variable type changes during the method. This isn't the case with Ruby yet; the type assertions apply to parameters only, at the method level. But Martin has promised to look into this for Ruby as well so hopefully there will be full parity between the two editors shortly!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. Just like in the PHP editor, mark occurrences and instant rename are type-assertion-aware:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtAeNoCfI/AAAAAAAAA3A/-kOva0-bFqc/specify-type3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-131382932772752240?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/131382932772752240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/01/netbeans-screenshot-of-week-41-type.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/131382932772752240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/131382932772752240'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/01/netbeans-screenshot-of-week-41-type.html' title='NetBeans Screenshot of the Week #41: Type Assertions'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuFD0mBaI/AAAAAAAABAc/Tm4CqQDL2Kg/s72-c/specify-type1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8053351885570744349</id><published>2009-01-05T04:51:00.000-08:00</published><updated>2010-09-17T13:49:12.550-07:00</updated><title type='text'>NetBeans Screenshot of the Week #40: Python Test Runner UI</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;In the 7.0 builds, we have a dedicated unit test runner for Python now. Running a file as a test, or running the test project action, will open a test runner with the output docked on its right hand side, instead of just the output window (click for full size screenshot):&lt;br/&gt;&lt;br&gt;&lt;a href="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOujtBw-NI/AAAAAAAABaM/99RYD5ogpeQ/python-testrunner.jpg" /&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuXLJwxgI/AAAAAAAABCk/jCadYhSfez4/python-testrunner-small.jpg" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;br&gt;Here's the test runner itself:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrkr8pKJI/AAAAAAAABTQ/cxo3JdtvPN0/python-testrunner4.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;What you want to see in the output is a single green line which says "All &lt;i&gt;n&lt;/i&gt; Tests Passed", where &lt;i&gt;n&lt;/i&gt; is hopefully a large number. But when one or more of the tests fail, you see something like the above.  Running the Next Error action (Cmd-.) will jump to the next failed test, just like it normally jumps to the next error in the current output window, or the next task in the tasklist.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;One thing to notice (and this is new in 7.0) is that we now include the failure message right there in the test summary for each test, so you don't have to drill into an individual test to see the failure message. You can also hover over a test and any output from that test is shown in a tooltip. You can also right click on tests and select "Run Again" to run just one specific test over again.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This is the same window as the one we have for Ruby. In fact, &lt;a href="http://blogs.sun.com/emononen"&gt;Erno&lt;/a&gt;, who wrote the Ruby test runner, has modularized the code now such that it's the same implementation for both languages - we just have language specific plugins to actually hook into the various testing frameworks. Currently, for Python we support the two builtin testing frameworks: &lt;code&gt;unittest&lt;/code&gt; and &lt;code&gt;doctest&lt;/code&gt;. The above screenshot showed a regular unittest run. Here's a doctest:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsishqc6I/AAAAAAAABWM/4dDGzTXnjUc/python-testrunner2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;One important thing to note is that you don't have to instrument your code with any test running code. As long as you place doctests in your docstrings, or as long as you have any classes extending &lt;code&gt;unittest.TestCase&lt;/code&gt;, the test runner will find them. All you have to do is run Test Project:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOujDWGhnI/AAAAAAAABD4/cFPDo9NBKLI/python-testproject.jpg" /&gt;&lt;br/&gt;&lt;br&gt;and when you have done that, both unittests and doctests are found and included in the same test run - here's both failing doctests and unit tests:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrbhBb_9I/AAAAAAAAAoU/GNcwiMiO99o/python-testrunner3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Once again, kudos to Erno for writing the excellent test runner support! And as usual, let us know of any problems.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. Jean-Yves Mengant has also done some excellent work recently. In addition to some cool new quickfixes in the Python editor for NetBeans, he has just &lt;a href="http://jpydbg.blogspot.com/2009/01/jpydbg-mutithreaded-python-debugger.html"&gt;integrated a multithreaded debugger for Python&lt;/a&gt;!&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsCVxFXWI/AAAAAAAAAuM/SvGYV-VVjnE/jythonswing.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8053351885570744349?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8053351885570744349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/01/netbeans-screenshot-of-week-40-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8053351885570744349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8053351885570744349'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/01/netbeans-screenshot-of-week-40-python.html' title='NetBeans Screenshot of the Week #40: Python Test Runner UI'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuXLJwxgI/AAAAAAAABCk/jCadYhSfez4/s72-c/python-testrunner-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5332582039025467585</id><published>2009-01-02T03:37:00.000-08:00</published><updated>2010-09-17T13:49:12.541-07:00</updated><title type='text'>Ruby Code Coverage in the builds now</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I've checked the Ruby code coverage code into the trunk now, so if you grab a recent daily 7.0 build, it should be there. I found a Windows-specific bug in the Python code coverage code as well, so grab a new build if you're on that platform.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I've had some fun with Java2D lately. Instead of the ugly coverage bars I showed in my &lt;a href="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOu4y6wVHI/AAAAAAAABas/8F8eBVNKjFU/rails-coverage.jpg"&gt;screenshots&lt;/a&gt; a couple of weeks ago, the coverage bars now have proper gradients, drop shadows behind the text etc.:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuxw9NO7I/AAAAAAAABF0/YB5WJoycuns/ruby-coveragereport.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Another thing I added is a bar in the editor footer (while code coverage is enabled) which lists the coverage percentage for the current file, along with actions to quickly run the tests again, or bring up the coverage report, or clear the results, or finish the coverage mode. As well as warn you when your data is older than your code.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsGb9IMvI/AAAAAAAABVY/Evcyk6HKpHg/coverage-footer.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;And finally, I updated the built-in and &lt;a href="http://mediacast.sun.com/users/tnorbye/media/org-netbeans-modules-ruby-themes70.nbm"&gt;extra color themes&lt;/a&gt; to also have color definitions for the coverage highlights. Here's the Dark Pastels color theme with coverage data enabled:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsnR27ZhI/AAAAAAAAAzg/V39EM6hkhuw/coverage-dark.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Please let me know of any problems while this code is still fresh in my mind :)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5332582039025467585?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5332582039025467585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2009/01/ruby-code-coverage-in-builds-now.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5332582039025467585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5332582039025467585'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2009/01/ruby-code-coverage-in-builds-now.html' title='Ruby Code Coverage in the builds now'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuxw9NO7I/AAAAAAAABF0/YB5WJoycuns/s72-c/ruby-coveragereport.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6494890478889429623</id><published>2008-12-31T06:16:00.000-08:00</published><updated>2010-09-17T13:49:12.532-07:00</updated><title type='text'>Happy New Year!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;My music teacher in middle school had a great tradition. Every New Years Eve, at midnight, he would lift his stereo speakers up to his open windows, and on full blast, play ABBA's "Happy New Year" for the neighborhood.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I'm going to do the same thing here, on my little corner of the internet. Enjoy!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;a href="http://www.youtube.com/watch?v=dcLMH8pwusw"&gt;&lt;br/&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/dcLMH8pwusw&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/dcLMH8pwusw&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;My kids have recently discovered ABBA through the Mamma Mia movie. Now they want to listen&lt;br/&gt;to ABBA when we're driving around. No, don't pity me - it's a lot better than what they usually&lt;br/&gt;want to listen to (I'm looking at you, Hannah Montana!). And besides, having grown up&lt;br/&gt;in Norway I'm an ABBA fan at heart. When I was in 4th grade, all the girls in my class&lt;br/&gt;liked ABBA, all the boys in my class liked Kiss, and then there was me - I sided with&lt;br/&gt;the girls. And I'm still not ashamed of it. Despite some of their ridiculous outfits,&lt;br/&gt;ABBA created some timeless melodies and had great sound production values that hold&lt;br/&gt;up to this day.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6494890478889429623?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6494890478889429623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/12/happy-new-year.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6494890478889429623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6494890478889429623'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/12/happy-new-year.html' title='Happy New Year!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-510107619082784932</id><published>2008-12-23T07:17:00.000-08:00</published><updated>2010-09-17T13:49:12.522-07:00</updated><title type='text'>VirtualBox Rocks!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;In order to get &lt;a href="http://blogs.sun.com/tor/entry/netbeans_screenshot_of_the_week6"&gt;code coverage&lt;/a&gt; to work seamlessly in the presence of the Rake build tool, I had to do some pretty ugly tricks - a lot of path manipulation that surely won't work on Windows. Rather than just getting bug reports, I'll need to debug through it to find the troublespots and fix them.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I don't have a Windows machine. I have a Solaris desktop box, and a Mac laptop. And since I don't have any short term plans to go in to the office (I work from home most of the time) I don't want to wait to look into this until my next chance to stop by a computer lab with Windows machines.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img align="right" style="margin-left: 5px; margin-bottom: 3px" src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtm4KHjtI/AAAAAAAAA84/Il1OYore1Zg/network-drive.jpg"&gt;&lt;br/&gt;So, I decided to dust off the &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt; instance I installed and tested a while back. Back then, it worked fine - but was a bit painful to use. Actually, it was my fault. I never went and "finished" my installation. Turns out, after installing Windows on the virtual machine, there is some additional software shipped with VirtualBox that can be installed into Windows to make things work more smoothly.&lt;br/&gt;For example, a special mouse driver makes the Mac mouse also work as the Windows mouse. There's support to share file systems. This is a huge benefit.  I simply mapped my working source tree that I have already checked out, edited and built, as a new Windows drive! I didn't have to go and install Mercurial, Python, check out the whole NeBeans source tree, build it, etc.  I could simply open up drive Z:, and run the NetBeans IDE from within Windows!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;Another cool thing these special tools add is "seamless mode". I'm running the Windows applications running as if they are regular Mac applications on my Mac desktop! So I can debug through my Windows instance of NetBeans while at the same time having my Mac mail and instant messaging programs part of the screen. Look at the below screenshot (click for full size) -- I have the Mac doc on the left, and the Windows doc on the bottom - as well as a mixture of Mac and Windows (uhm) windows on the desktop!&lt;br/&gt;&lt;br&gt;&lt;br clear="all"&gt;&lt;br/&gt;&lt;a href="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuDVc_JUI/AAAAAAAABZY/XXd6QeiAyDs/desktop.jpg"&gt;&lt;br/&gt;&lt;img border="0" src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtS2lHNtI/AAAAAAAAA58/g1IprtIqOzA/desktop-small.jpg" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;br&gt;There's my mailtool again... Last year I &lt;a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week22"&gt;posted a screenshot&lt;/a&gt; showing how I had 13,000 unread mails, but plans to finally catch up. I guess I didn't put that high enough up on my priority list. The above screenshot shows how I'm up to 56,000 unread mails now. Ugh. Oh well, at least the number of unread mails addressed directly to me is decreasing.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Wow. Installation was flawless. It's working beautifully. And it's free. And it's open source. Wow.  Oh, and it runs on many other platforms as well.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As I wrote this blog entry I looked up the &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox home page&lt;/a&gt; to I could link to it, and I discovered a news blurb:&lt;br/&gt;&lt;blockquote&gt;&lt;br/&gt;&lt;span style="color: red"&gt;New Dec 17, 2008&lt;/span&gt;&lt;br&gt;&lt;br/&gt;&lt;b&gt;VirtualBox 2.1.0 released!&lt;/b&gt;&lt;br&gt;&lt;br/&gt;Sun today released VirtualBox 2.1.0, a major update with exciting new features: among them better 64-bit support, hardware virtualization on the Mac, 3D acceleration, easier networking on Windows and Linux plus full VMDK/VHD support including snapshots. See the &lt;a href="http://www.virtualbox.org/wiki/Changelog"&gt;ChangeLog&lt;/a&gt; for a detailed list of changes.&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I just installed it and took it for a quick spin, and things are looking great.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. One little tip: Installing the Guest Additions into Windows is easy - there's a menu item in the Device menu, "Install Guest Additions...".  I tried it, and it popped up an installer inside Windows. But since I was in the middle of applying service packs to Windows, I dismissed it so I could deal with it after my service pack upgrade reboot. But when I tried it later, it didn't work! Uh oh, is this incompatible with service pack 3 I wonder?  Nope, it's much simpler than that. What "Install Guest Additions..." does, is mount a new CD-ROM into Windows. I'm guessing Service Pack 3 turns off auto-run! Probably a security thing. So all I had to do was open the computer folder, and click on the CD-ROM there to run the installer.&lt;br/&gt;&lt;br&gt;Oh, one other tip: The default RAM allocated to the virtual machine is pretty small: 512Mb. In the Settings for the machine you can crank it up bigger - I set it to 2 Gb. That makes the machine run quite a bit faster under load since it's not continually swapping to disk for virtual memory.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-510107619082784932?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/510107619082784932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/12/virtualbox-rocks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/510107619082784932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/510107619082784932'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/12/virtualbox-rocks.html' title='VirtualBox Rocks!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtm4KHjtI/AAAAAAAAA84/Il1OYore1Zg/s72-c/network-drive.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5917038599508695514</id><published>2008-12-18T09:29:00.000-08:00</published><updated>2010-09-17T13:49:12.503-07:00</updated><title type='text'>JavaOne Submissions Due</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;The deadline for &lt;a href="http://www28.cplan.com/cfp_prod/CFPLogin.jsp?wId=69MQ81"&gt;submitting talks for JavaOne 2009&lt;/a&gt; is almost here.  I was on one of the review committees last year, and saw many common patterns for rejected talks.  I wrote these up in a blog entry last year - "&lt;a href="http://blogs.sun.com/tor/entry/why_your_javaone_submission_was"&gt;Why Your JavaOne Submission Was Rejected&lt;/a&gt;. You might want to skim through it again while reviewing your submissions one final time!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;a href="http://www.apress.com/book/view/1430216360"&gt;&lt;br/&gt;&lt;img border="0" align="right" style="margin-left: 5px" src="http://www.apress.com/resource/bookcover/9781430216360?size=medium"&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;Also, there's a &lt;a href="http://blogs.sun.com/divas/entry/our_netbeans_ruby_book_is"&gt;new book&lt;/a&gt; about develping Ruby and Rails code with NetBeans, written by &lt;a href="http://blogs.sun.com/divas/entry/our_netbeans_ruby_book_is"&gt;Chris Kutler&lt;/a&gt; and &lt;a href="http://weblogs.java.net/blog/bleonard/"&gt;Brian Leonard&lt;/a&gt;. I reviewed some of the content and it looked very good. There are a lot of books on Ruby and Rails, but this book really shows you how to do things effectively with NetBeans. Mastering your tools is one of the best gifts you can give yourself as a developer (or as a craftsman of any craft, I think). I gave this advice a while back when I was interviewed for the JavaOne daily newspaper. Highlights from these interviews were recently compiled in &lt;a href="http://java.sun.com/developer/technicalArticles/Interviews/studentdevs/index.html"&gt;this article&lt;/a&gt;, containing advice for students from a variety of developers. When this article was &lt;a href="http://java.dzone.com/news/what-advice-would-you-give-to-"&gt;discussed on DZone&lt;/a&gt; I was surprised to see some people still talk about IDEs as something to be avoided until you know what you're doing. I think &lt;b&gt;precisely&lt;/b&gt; when you are new to Java should you use an IDE to help you explore IDEs, to pinpoint errors are you're typing code rather when you try to run &lt;code&gt;javac&lt;/code&gt; from the command line etc. The same goes for Ruby, Python, PHP, and so on. The IDEs let you explore APIs using code completion and go to declaration, they present important operations in project and execution menus, quickfixes and semantic warnings pinpoint errors in your code, and so on. If you're still writing code with Notepad, you're missing out.&lt;br/&gt;&lt;br clear="all"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5917038599508695514?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5917038599508695514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/12/javaone-submissions-due.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5917038599508695514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5917038599508695514'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/12/javaone-submissions-due.html' title='JavaOne Submissions Due'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-900800196592823839</id><published>2008-12-16T10:09:00.000-08:00</published><updated>2010-09-17T13:49:12.486-07:00</updated><title type='text'>NetBeans Screenshot of the Week #39: Ruby Code Coverage, Python Code Coverage</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Here's a new feature for NetBeans 7.0: Code Coverage support!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;First a screenshot:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrcK_XRrI/AAAAAAAABS8/AM7C8Ho-uPI/rails-coverage2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There are a couple of key points about the code coverage support:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; It is fully integrated into the IDE, and especially the editor. You don't get read-only views of your files with coverage information; the files themselves include coverage highlights. You can view and edit the code directly, use your normal IDE navigation commands to jump around, and so on.&lt;br/&gt;&lt;li&gt; Enabling and disabling code coverage is trivial. There is no need to modify your build files, run special rake targets etc. Just select the menu checkbox to enable coverage in the new Code Coverage project menu, and then continue as before - run unit tests, run files, run the tests in your project - and the results are updated live as soon as the executed process finishes.&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I didn't think a screenshot really described this feature well, so I recorded a couple of quick sessions where I use the feature:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; Here's Ruby (Quicktime, 8.1 Mb, 2 minutes 11 seconds, click on the image - or &lt;a href="http://www.youtube.com/watch?v=Sj8lIKoCctU"&gt;low-res youtube version&lt;/a&gt;):&lt;br/&gt;&lt;br&gt;&lt;a href="http://mediacast.sun.com/users/tnorbye/media/RubyCodeCoverage.mov"&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOubCg78-I/AAAAAAAABC4/K0JvpoQTv9Q/ruby-movie.jpg" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;br&gt;&lt;li&gt; Here's Python (Quicktime, 4.3 Mb, 1 minute 5 seconds, click on the image - or &lt;a href="http://www.youtube.com/watch?v=jGJa_2UyHrY"&gt;low-res youtube version&lt;/a&gt;):&lt;br/&gt;&lt;br&gt;&lt;a href="http://mediacast.sun.com/users/tnorbye/media/PythonCodeCoverage.mov"&gt;&lt;br/&gt;&lt;img border="0" src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOuxi9t1QI/AAAAAAAABFw/0R8pau8p-Vk/python-movie.jpg" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;br&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's a couple more images if you have problems loading the videos:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOu4y6wVHI/AAAAAAAABas/8F8eBVNKjFU/rails-coverage.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;br&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsh12gDrI/AAAAAAAABWI/jhLGGCFpfCI/python-coverage.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsyCEd2oI/AAAAAAAABWs/OAnZRd34Po0/aggregate-results.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;script type="text/javascript"&gt;&lt;br/&gt;digg_url = 'http://blogs.sun.com/tor/entry/netbeans_screenshot_of_the_week6';&lt;br/&gt;&lt;/script&gt;&lt;br/&gt;&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br/&gt;&lt;br clear="all"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The Python version is already in the 7.0 builds. The Ruby support isn't integrated yet; it probably needs some tweaking to make it work on Windows.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-900800196592823839?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/900800196592823839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/12/netbeans-screenshot-of-week-39-ruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/900800196592823839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/900800196592823839'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/12/netbeans-screenshot-of-week-39-ruby.html' title='NetBeans Screenshot of the Week #39: Ruby Code Coverage, Python Code Coverage'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrcK_XRrI/AAAAAAAABS8/AM7C8Ho-uPI/s72-c/rails-coverage2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2271044505235793870</id><published>2008-11-28T02:14:00.000-08:00</published><updated>2010-09-17T13:49:12.468-07:00</updated><title type='text'>NetBeans Screenshot of the Week #38: E4X Support</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;As part of the &lt;a href="http://blogs.sun.com/tor/entry/netbeans_screenshot_of_the_week4"&gt;JavaScript 1.7&lt;/a&gt; work,&lt;br/&gt;I also beefed up the &lt;a href="http://en.wikipedia.org/wiki/E4X"&gt;E4X&lt;/a&gt; support. E4X allows you to embed XML objects&lt;br/&gt;directly in your JavaScript source. Here's some simple E4X JavaScript:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOr_BbW_VI/AAAAAAAAAts/A4QvV36qRj4/e4x-none.jpg" /&gt;&lt;br/&gt;&lt;br&gt;We've had E4X support in NetBeans in both NetBeans 6.1 and 6.5. But now, in NetBeans 7.0, semantic highlighting is E4X aware, such that the source code looks like this instead:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtqE6xa2I/AAAAAAAAA9Y/XICdX-D7NwM/e4x-before.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The whole XML document declaration has a faint purple background, element names are blue and document content is bolded.&lt;br/&gt;(The green here, as for all JavaScript code in NetBeans, indicates variables in global scope.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;Another new E4X feature is formatting/pretty printing.  If you press Alt-Shift-F to format the above source, the E4X is&lt;br/&gt;reformatted and indented:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtazsMslI/AAAAAAAAA68/k_tz6FKbnI4/e4x-reformatted.jpg" /&gt;&lt;br/&gt;&lt;br&gt;In addition, the navigator window shows the logical structure of the XML document as well. Clicking in the source&lt;br/&gt;will expand and select the corresponding item in the navigator, and conversely double clicking in the navigator&lt;br/&gt;warps the source to the corresponding location in the XML declaration:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsGoRlqnI/AAAAAAAAAvE/pO0ZnA1D_Tg/e4x-navigator-sync.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Finally, there's some primitive support in code completion for the XML document:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsQUKAfaI/AAAAAAAAAwY/jE8rBSRZArI/e4x-completion.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2271044505235793870?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2271044505235793870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-38-e4x.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2271044505235793870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2271044505235793870'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-38-e4x.html' title='NetBeans Screenshot of the Week #38: E4X Support'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOr_BbW_VI/AAAAAAAAAts/A4QvV36qRj4/s72-c/e4x-none.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-7045265318717051582</id><published>2008-11-25T06:46:00.000-08:00</published><updated>2010-09-17T13:49:12.459-07:00</updated><title type='text'>NetBeans Screenshot of the Week #37: JavaScript 1.7 Support</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I just checked in support for JavaScript 1.7. This means that NetBeans will no longer give you syntax errors if you try to use the new language. Here are some screenshots. First, let's open a file using JavaScript 1.7 constructs:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrsgOTRaI/AAAAAAAAArA/kW_a-FNcnSA/wrong-yield2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Obviously the file is using &lt;code&gt;yield&lt;/code&gt; which is not recognized as a keyword, and in particular, this is just a syntax error - the parser was expecting a semicolon. But there's a little lightbulb... let's see what it says (type Alt-Enter or click on the lightbulb):&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOthc52ceI/AAAAAAAAA8E/CR-ybAfUxtQ/wrong-yield.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Let's select the option to change the active language to 1.7. I could also open the JavaScript options dialog directly and set it to 1.7 as shown here:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOry6lK5QI/AAAAAAAAAr0/2KGwvQMR9Lc/choosing-language.jpg" /&gt;&lt;br/&gt;&lt;br&gt;After applying the language change, the editor immediately re-lexes and reparses the file according to the new language. The errors are gone, and yield is now a proper keyword:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrx9p0AaI/AAAAAAAAArs/sZ1klur8wjg/yield-ok.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Similarly, the &lt;code&gt;let&lt;/code&gt; keyword can be used, as well as destructuring assignments, generators and iterators, etc. (See &lt;a href="https://developer.mozilla.org/en/New_in_JavaScript_1.7"&gt;New In JavaScript 1.7&lt;/a&gt; for more information).&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOt6F21uuI/AAAAAAAAA_M/UaPQe5F4fQc/let.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you place the caret on function definitions, it will highlight all exit points, and this includes yields now.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This work isn't done; I'd like it to be smarter about generators, and there may be some issues with scope handling. But at least the editor doesn't get in your way with false error messages now - you can start writing JavaScript 1.7 clean code. (This is with NetBeans 7.0 dev).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In related news, I just heard from &lt;a href="http://www.bloglines.com/blog/ThomasEEnebo"&gt;Tom Enebo&lt;/a&gt; that a lot of Ruby 1.9 language features are now supported by the JRuby trunk parser, so hopefully we can soon start fully supporting Ruby 1.9 features in NetBeans as well.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-7045265318717051582?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/7045265318717051582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-37.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7045265318717051582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7045265318717051582'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-37.html' title='NetBeans Screenshot of the Week #37: JavaScript 1.7 Support'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrsgOTRaI/AAAAAAAAArA/kW_a-FNcnSA/s72-c/wrong-yield2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-3227035215323686276</id><published>2008-11-14T01:30:00.000-08:00</published><updated>2010-09-17T13:49:12.445-07:00</updated><title type='text'>NetBeans Screenshot of the Week #36: Python Code Completion</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Here are some screenshots of the code completion working for Python.&lt;br/&gt;First, let's try it from an import statement:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrqEKLHvI/AAAAAAAAAqo/rzrPHzRH8pQ/pycompletion1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Note that the documentation for the module is shown. Next, let's&lt;br/&gt;try completing on imported symbols - again we've got the documentation:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOu4RfEbkI/AAAAAAAABGc/FLToADtbQWM/pycompletion2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;I'm writing a unit test, extending &lt;code&gt;TestCase&lt;/code&gt;. Now let's try overriding&lt;br/&gt;some methods - completion after typing &lt;code&gt;def&lt;/code&gt;:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOteR1lZBI/AAAAAAAAA7k/-l6C53Nugxw/pycompletion3.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Obviously, invoking methods on &lt;code&gt;self.&lt;/code&gt; will show the inherited&lt;br/&gt;methods - and their documentation:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtnkgarZI/AAAAAAAAA88/hf0CPP81jpE/pycompletion4.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Here's completion in my function (not on &lt;code&gt;self&lt;/code&gt;) showing&lt;br/&gt;the local variables, imported symbols and builtins. Notice that deprecated&lt;br/&gt;methods are marked with strikethrough (and deprecated modules are in imports&lt;br/&gt;as well, though I didn't show that above).&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuwwEZeVI/AAAAAAAABFs/J_rE9GH3AfE/pycompletion5.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Notice also that the documentation here looks better - it has links,&lt;br/&gt;colors, etc. This is because NetBeans supports the reStructuredText&lt;br/&gt;Docstring Format (see &lt;a href="http://www.python.org/dev/peps/pep-0287/"&gt;PEP 287&lt;/a&gt;).&lt;br/&gt;System libraries are being documented in this way now, so more of the&lt;br/&gt;documentation will start looking like this.&lt;br/&gt;&lt;br&gt;When NetBeans finds embedded code, it will also syntax highlight the&lt;br/&gt;code fragments in the documentation:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOru6bhkDI/AAAAAAAAArU/Awwek0S-zuU/pycompletion6.jpg" /&gt;&lt;br/&gt;&lt;br&gt;You can use this in your own documentation as well obviously.&lt;br/&gt;Here's a file where I have restructured text. As I'm writing it,&lt;br/&gt;I can -immediately- preview the text myself by just pressing&lt;br/&gt;Ctrl-Shift-Space (Show Documentation - for those who don't know, you&lt;br/&gt;can do this on regular code as well if you want to just get the documentation&lt;br/&gt;for the code at the caret, rather than completion alternatives up to&lt;br/&gt;the caret prefix.)&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrqt2xMRI/AAAAAAAAAqs/Jyx7g3YMlgo/pycompletion8.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Here's a final example - completion after &lt;code&gt;raise&lt;/code&gt; (or&lt;br/&gt;&lt;code&gt;exception&lt;/code&gt;) will show completion for all &lt;code&gt;Error&lt;/code&gt;&lt;br/&gt;classes:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsMvZV7KI/AAAAAAAAAv8/_K192mJ5xWQ/pycompletion7.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I'll be quiet or about a week now -- I'm going on vacation! Not great&lt;br/&gt;timing given the release date, but this has been planned since February...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-3227035215323686276?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/3227035215323686276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-36-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3227035215323686276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3227035215323686276'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-36-python.html' title='NetBeans Screenshot of the Week #36: Python Code Completion'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrqEKLHvI/AAAAAAAAAqo/rzrPHzRH8pQ/s72-c/pycompletion1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2575744409666082534</id><published>2008-11-13T06:32:00.000-08:00</published><updated>2010-09-17T13:49:12.419-07:00</updated><title type='text'>NetBeans Screenshot of the Week #35: Support for Python's __all__ Variable</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Let's start with a pretty simple module - an import, a function, and a couple of classes:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOt_pkIOAI/AAAAAAAAA_0/HL8qETPnI24/simple-module.jpg" /&gt;&lt;br/&gt;&lt;br&gt;(Notice by the way the semantic highlighting here - the unused parameters and variables are marked with a slight grey underline,&lt;br/&gt;method names in bold, parameters in orange. More on that another day.)&lt;br/&gt;&lt;br&gt;Now let's go to a different file and import this module. Code completion is context dependent and shows us&lt;br/&gt;which symbols are being exported by the given module. We see not only our functions and classes, the imported symbol &lt;code&gt;sys&lt;/code&gt;&lt;br/&gt;is also being defined by module, meaning that if you do &lt;code&gt;from compl4 import *&lt;/code&gt; you would have &lt;code&gt;sys&lt;/code&gt; defined as well:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr66XOIZI/AAAAAAAAAtI/PSoIHa7sXgw/moduleimport1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Python has a way to deal with this: You can specify a variable named &lt;code&gt;__all__&lt;/code&gt;, which lets you define exactly what the public API for&lt;br/&gt;this module should be (&lt;a href="http://www.python.org/doc/2.5.2/tut/node8.html#pkg-import-star"&gt;more details&lt;/a&gt;).&lt;br/&gt;&lt;br&gt;Let's go in and define the names we want exported by our module. I will add &lt;code&gt;__all__ = [ "Bar " ]&lt;/code&gt; somewhere in the file, to specify that only &lt;code&gt;Bar&lt;/code&gt; should be exported:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr0Hnd6yI/AAAAAAAAAsE/HOZfzBWlePI/definedall.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Look at the file outline / navigator on the left hand side. As soon as I typed in the &lt;code&gt;__all__&lt;/code&gt; line,&lt;br/&gt;the icons changed to show me that only the &lt;code&gt;Bar&lt;/code&gt; class and its method are now "public"; there are little&lt;br/&gt;lock icons on everything else! Let's see what code completion offers when we try to import this module again:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOt67o9thI/AAAAAAAAA_U/uMeEXO1qm-4/moduleimport2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Yep, only the public API is exported now. Let's append to the &lt;code&gt;__all__&lt;/code&gt; list to export the &lt;code&gt;func&lt;/code&gt; function:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOu1h3XXyI/AAAAAAAABGE/_YYyM-ETeeM/defineall2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;You don't have to rely on icons to tell you if something is wrong though. Let's say I've forgotten all about this, and I decided&lt;br/&gt;to rename my &lt;code&gt;Bar&lt;/code&gt; class:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtCHw_wSI/AAAAAAAAA3U/Su3b2McVObk/alldeferror.jpg" /&gt;&lt;br/&gt;&lt;br&gt;NetBeans checks that all the symbols you declare in your &lt;code&gt;__all&lt;/code&gt; list actually exist, and points out any discrepancies. Here, the public &lt;code&gt;Bar&lt;/code&gt; class no longer exists since we renamed it.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's another little bug I came across related to this. I was checking the &lt;code&gt;__all__&lt;/code&gt; handling on various library files,&lt;br/&gt;in this case &lt;code&gt;posixpath.py&lt;/code&gt;. Notice how in the navigator, all the functions are public, except one...&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuk4XC9MI/AAAAAAAABaU/aKrJ-Wii7DM/sameopenfile.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Sure enough, the code looks like it's registering this conditionally added method... Do you spot the problem? There's a dot missing!&lt;br/&gt;As soon as we add it, we get this:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOukYRN6CI/AAAAAAAABEE/QSoNBQLsluY/sameoldfile2.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Of course, this last bug was already detected by the&lt;br/&gt;&lt;a href="http://blogs.sun.com/tor/entry/netbeans_screenshot_of_the_week1"&gt;unresolved symbol detector&lt;/a&gt;...&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrelZ7r6I/AAAAAAAAAow/l32xvCZcxiE/allappendmissing.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2575744409666082534?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2575744409666082534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-35-support.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2575744409666082534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2575744409666082534'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-35-support.html' title='NetBeans Screenshot of the Week #35: Support for Python&amp;#39;s __all__ Variable'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOt_pkIOAI/AAAAAAAAA_0/HL8qETPnI24/s72-c/simple-module.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-9023211593371119058</id><published>2008-11-12T10:50:00.000-08:00</published><updated>2010-09-17T13:49:12.405-07:00</updated><title type='text'>Ruby Screenshot of the Week #34: Detecting Duplicates Hash Keys</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;You didn't think we had forgotten Ruby, did you?  Here's a new Ruby editor feature: Detecting duplicate hashkeys. As "Fjan" (who filed the&lt;br/&gt;&lt;a href="http://www.netbeans.org/issues/show_bug.cgi?id=153074"&gt;request&lt;/a&gt;) says, when some Rails calls allow dozens or more keys, you can accidentally add a hash key twice, with subtle results. NetBeans now tracks these down and points them out for you.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrt7uNlGI/AAAAAAAABUA/ceKZbTRa_OY/duplicate-hashes.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This is going into 7.0, but you can use &lt;a href="http://www.netbeans.org/nonav/issues/showattachment.cgi/73712/org-netbeans-modules-ruby-extrahints.nbm"&gt;this 6.5-compatible module&lt;/a&gt; as well.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Martin and Erno have also been &lt;a href="http://wiki.netbeans.org/RubyRecentChanges"&gt;hard at work&lt;/a&gt;. There are many new features in 6.5 (which I'll cover when 6.5 ships in a week or two). But in the 7.0 trunk, the debugger can attach to arbitrary and remote processes - see&lt;br/&gt;&lt;a href="http://blogs.sun.com/martink/entry/remote_debugging_debug_whatever_ruby"&gt;Martin's blog entry&lt;/a&gt; for more info. And Erno has added support for Shoulda testing and more test runner improvements - &lt;a href="http://blogs.sun.com/emononen/entry/netbeans_next"&gt;details here&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-9023211593371119058?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/9023211593371119058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/11/ruby-screenshot-of-week-34-detecting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/9023211593371119058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/9023211593371119058'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/11/ruby-screenshot-of-week-34-detecting.html' title='Ruby Screenshot of the Week #34: Detecting Duplicates Hash Keys'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrt7uNlGI/AAAAAAAABUA/ceKZbTRa_OY/s72-c/duplicate-hashes.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-3552982254485699707</id><published>2008-11-11T01:23:00.000-08:00</published><updated>2010-09-17T13:49:12.389-07:00</updated><title type='text'>NetBeans Screenshot of the Week #33: Finding Unresolved Symbols</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;In my &lt;a href="http://blogs.sun.com/tor/entry/netbeans_screenshot_of_the_week"&gt;last entry&lt;/a&gt; I showed that the Fix Imports action will alert you to an unresolved symbol. This is really helpful since it can help you track down runtime problems.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Obviously, you shouldn't have to go run Fix Imports on every file, periodically, to look for unresolved symbols!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;NetBeans has a special semantic checker for this. It is off by default, for two reasons:&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt; I added it just a couple of days ago - during the stabilization period for EA, so I didn't dare enable it in case it's seriously broken.&lt;br/&gt;&lt;li&gt; There are cases where it doesn't yet work. I'll describe that later.&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;To enable it, open up the Editor options dialog, and under Hints, select Python. You should now see the current batch of Python hints. Enable the "Unresolved Symbol" hint:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsHDHtd3I/AAAAAAAAAvM/GPMVmWFBxhA/enable-unresolvedhint.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Now let's open up the &lt;code&gt;datetime.py&lt;/code&gt; file again:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsZhj1P8I/AAAAAAAAAxg/Q1o1kWFSVyI/unresolved-valueerror.jpg" /&gt;&lt;br/&gt;&lt;br&gt;As you can see, the file is marked erroneous (by the red square above the scrollbar), and the scrollbar indicates where in the file the error is. Clicking on it to expose the error location you can see an underline under the unresolved symbol, and a tooltip explaining what the problem is. The error is also shown in the tasklist, so you don't have to open each file to look for problems - just let the tasklist scan your project for problems.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's another example. I opened up the Django 1.0 sources, and NetBeans pointed out this problem to me, in &lt;code&gt;django.utils.simplejson.tool&lt;/code&gt;:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtAE87LAI/AAAAAAAAA28/H6E7ACcf8fg/simplejson.jpg" /&gt;&lt;br/&gt;&lt;br&gt;This shows that the import is unused, and that the attempts to call methods on the import do not work. The call would need to be changed to&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;obj = django.utils.simplejson.load(infile)&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;or the import changed to be&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;import django.utils.simplejson as simplejson&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br&gt;Here's one final one... Perhaps helpful to people having done a lot of Java development recently:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr73M6iqI/AAAAAAAAAtQ/uxQGXU9PVlo/nil-none.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finding unresolved symbols means that NetBeans must be able to find all the libraries you are importing. This means you can't just point NetBeans at a plain Python file - your project has to contain all the libraries you are using, and, you have to configure your source path correctly such that NetBeans computes the correct package names for your python modules. (I accidentally pointed to the "django" folder instead of its parent folder at first, which meant &lt;code&gt;django.&lt;/code&gt; wasn't part of the package prefix and that meant that all kinds of symbols couldn't be resolved.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Second, this won't work for dynamically generated symbols (eval etc). I haven't run into this a lot yet - but I'm sure there are areas where the unresolved detection can't find symbols that really do exist.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. Is there a canonical Python term for what I've called "unresolved" here that we should use instead?&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-3552982254485699707?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/3552982254485699707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-33-finding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3552982254485699707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3552982254485699707'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-33-finding.html' title='NetBeans Screenshot of the Week #33: Finding Unresolved Symbols'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsHDHtd3I/AAAAAAAAAvM/GPMVmWFBxhA/s72-c/enable-unresolvedhint.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-1010940161089711982</id><published>2008-11-10T14:03:00.000-08:00</published><updated>2010-09-17T13:49:12.375-07:00</updated><title type='text'>NetBeans Screenshot of the Week #32: Python Import Management</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;We're about to release an early access release of Python support for NetBeans. We have ambitious goals for the Python support: NetBeans should be the best IDE for Python development, bar none!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Over the next couple of weeks I'll post screenshots of a bunch of editor related features for Python. Today I'll start with a feature near and dear to my heart: Import Management.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I used to be a die hard XEmacs user. When I started coding in Java, I continued using emacs for a couple of years. And the feature which finally made me abandon emacs for a Java IDE?  You guessed it -- import management.  If I wanted to use for example the &lt;code&gt;List&lt;/code&gt; class, I could just press a keystroke to choose which List class I had in mind, and the import statement was added for it at the top of the file while I could continue working in the middle of the file somewhere.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;To be sure, this is not rocket science, and Emacs support for Java has improved a lot over the years. But at the time, this was a huge productivity boost and coupled with other code-intelligence and navigation features was enough to lure my away from my comfort zone in the IDE to what was a less powerful plain text editor, but a more powerful Java coding tool.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Anyway, Python shares some similarities with Java. There are lots of libraries, and you need to import modules before you can use them. And this is where NetBeans' Python support can help.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Let's say I've tried calling the &lt;code&gt;cmp&lt;/code&gt; method to compare files. I ran the code and realized I need to import &lt;code&gt;cmp&lt;/code&gt; before I can use it. To get the IDE to import the symbol for me, I can just pull up the context menu and select &lt;b&gt;Fast Import&lt;/b&gt; (or more realistically, just use the keybinding Alt-Shift-I):&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOt832HTUI/AAAAAAAAA_g/_aXllDthtcU/python-menu1.jpg" /&gt;&lt;br/&gt;&lt;br&gt;This brings up an import dialog like this:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsfUEHyfI/AAAAAAAAAyU/wjH4nHIuRFQ/import-default.jpg" /&gt;&lt;br/&gt;&lt;br&gt;This tells us there are two definitions of a function named &lt;code&gt;cmp&lt;/code&gt; - one in &lt;code&gt;filecmp&lt;/code&gt; and one in &lt;code&gt;functions&lt;/code&gt;. I'm interested in the first one. The label below the list tells me that I can hold the Alt key or the Shift key when I select the list entry to change the import statement. And below that, there is a preview of the import statement that will be generate. As soon as I press the Alt key, the window changes to this:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsqwc4t1I/AAAAAAAAA0A/YRFr-fisvfI/import-alt.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Here, the bottom line is showing that we will be doing a wildcard import of all symbols instead of just the target symbol. And finally, let's press Shift:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOs0TETqoI/AAAAAAAAA1c/sR16jWb4B78/import-ctrl.jpg" /&gt;&lt;br/&gt;&lt;br&gt;This will not just import the &lt;code&gt;cmp&lt;/code&gt; symbol, it will instead import the whole module and change my current call to use the imported module symbol. When I press Enter my editor looks like this:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsRZ5bgCI/AAAAAAAAAwg/nNzJ_c2Lj0U/imported-symbol.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This is the import facility I ditched Emacs for ten years ago. But it's not how I manage imports for Java anymore. Instead, there is the &lt;b&gt;Fix Imports&lt;/b&gt; action (it's also there in the menu -- Ctrl-Shift-I for short). Unlike Fast Import, which looks at the identifier under the editor caret, Fix Imports will look at all your imports in the file, and, well, fix them!  This means sorting them, removing duplicates, even removing unused imports. And obviously, resolving imports automatically using the machinery I showed above. Here's how this works.&lt;br/&gt;&lt;br&gt;Here I've opened the &lt;code&gt;SocketServer.py&lt;/code&gt; file, and then I've commented out all the imports:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOt3OTG6aI/AAAAAAAAA-4/KWK8_KwQ45A/comment-out.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The file is now broken - it has various references to functions that are not defined/imported anymore. Let's see what happens if I press Ctrl-Shift-I:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtl0DHtXI/AAAAAAAAA8w/sr7R1CQ5074/imported.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Tadaaa!  It has figured out the missing imports and has inserted them. This is confirmed by a message in the lower left hand corner:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrwUpJ6TI/AAAAAAAAArg/8LiAp5NmQIA/statusmsg.jpg" /&gt;&lt;br/&gt;&lt;br&gt;This just happened automatically because NetBeans could figure out, unambiguously, what the missing imports must be.  Let's make it less clear-cut. I'm going to insert a call to &lt;code&gt;get()&lt;/code&gt;. Now let's try again:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOt0ErQYKI/AAAAAAAAA-k/lezRB7pw_eU/ambiguous.jpg" /&gt;&lt;br/&gt;&lt;br&gt;This time we get a dialog. You can see that it has figured out the &lt;code&gt;sys&lt;/code&gt; and &lt;code&gt;os&lt;/code&gt; imports - but it is not certain to do about the call to &lt;code&gt;get()&lt;/code&gt;. There are two modules defining this function - &lt;code&gt;unicodedata&lt;/code&gt; and &lt;code&gt;webbrowser&lt;/code&gt;:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuO5KHifI/AAAAAAAABBg/vVevKSnJGbQ/ambiguous3.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The corresponding function signatures are listed to help me decide which one I'm interested in. I can choose one of them, and when I press Ok, the imports are applied.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In some cases it may not find the symbol at all. Let's put in a bogus call:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtBps0idI/AAAAAAAAA3Q/cdll-Mux5TE/unresolved.jpg" /&gt;&lt;br/&gt;&lt;br&gt;Here the import manager can't figure out what to do - there is no known matching function. Only when NetBeans is certain about the imports does it proceed to clean up the imports without any user intervention.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This facility can also help find bugs! When I was testing this feature, I happened to invoke it in the &lt;code&gt;datetime.py&lt;/code&gt; file which ships with Jython. Here's what it said:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOslXaR1fI/AAAAAAAAAzM/JM51vjp1Pys/value-error.jpg" /&gt;&lt;br/&gt;&lt;br&gt;That's right - the code is referencing nonexistent class &lt;code&gt;ValuError&lt;/code&gt;. This clearly should be &lt;code&gt;ValueError&lt;/code&gt;!&lt;br/&gt;NetBeans has additional facilities for tracking down these types of bugs which I'll cover in another post.&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;So far I've focused on using the import facility to import new symbols. If you're writing code using the editor you may not need it, since when you use code completion to insert calls, it also automatically inserts import statements as needed.&lt;br/&gt;However, another useful aspect of Fix Imports is cleaning up your imports: removing duplicates, sorting alphabetically (configurable), and even deleting unused imports.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you open up a file with unused imports, NetBeans will show you that immediately:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtY30PHoI/AAAAAAAAA6s/HAN07Un1Dyw/unused-imports.jpg" /&gt;&lt;br/&gt;&lt;br&gt;There are quickfixes here, so if you click on the lightbulbs or press Alt-Enter, you can see the import actions:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtKo88EBI/AAAAAAAAA40/Gh-DyyqLFGw/clean-imports.jpg" /&gt;&lt;br/&gt;&lt;br&gt;The integration with quickfixes means that if you look in the tasklist, it will show files containing unused imports. But when you're editing, you can just press Ctrl-Shift-I to clean up the imports - it will do everything we've covered so far: Add missing imports, remove duplicates, remove unused, and sort the remaining imports.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Import management is also tied into source formatting. If you format your source, you can optionally have it clean up formats. Here are the formatting options for Python:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOszQb-PmI/AAAAAAAABW0/xhO1_0Ou9Nk/format.jpg" /&gt;&lt;br/&gt;&lt;br&gt;You can play with the checkboxes and the preview will show you the effect. Here's what happens if we enable sorting system libraries to the top. Note also that removing unused imports is not done by default during formatting (whereas Fix Imports will perform it automatically). You can change that in this formatting preference panel:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtqHS_oKI/AAAAAAAABYo/hf_TRdHi1zE/delete-unused.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As I mentioned, we'll have an early access version out very soon. If you're feeling adventurous, you can always download builds from the continuous build server - &lt;a href="http://deadlock.netbeans.org/hudson/job/python/"&gt;http://deadlock.netbeans.org/hudson/job/python/&lt;/a&gt;. Please file bugs and ideas &lt;a href="http://ide.netbeans.org/issues/enter_bug.cgi?component=python&amp;issue_type=DEFECT"&gt;here&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-1010940161089711982?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/1010940161089711982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-32-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1010940161089711982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1010940161089711982'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/11/netbeans-screenshot-of-week-32-python.html' title='NetBeans Screenshot of the Week #32: Python Import Management'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOt832HTUI/AAAAAAAAA_g/_aXllDthtcU/s72-c/python-menu1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8960375963116488629</id><published>2008-11-06T08:39:00.000-08:00</published><updated>2010-09-17T13:49:12.363-07:00</updated><title type='text'>Champagne!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I'm extremely proud and relieved. If it hadn't been for the embarrassing passage of Prop 8, it would have been a perfect ending to the last eight years.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrVX4Nv8I/AAAAAAAAAnQ/7OqahyqlVhA/champage2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8960375963116488629?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8960375963116488629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/11/champagne.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8960375963116488629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8960375963116488629'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/11/champagne.html' title='Champagne!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrVX4Nv8I/AAAAAAAAAnQ/7OqahyqlVhA/s72-c/champage2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-7528547404356258666</id><published>2008-10-31T03:53:00.000-07:00</published><updated>2010-09-17T13:49:12.354-07:00</updated><title type='text'>Mercurial Tip: Checking in regularly with uncommitted changes in your clone</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;NetBeans, like OpenJDK and OpenSolaris, uses the &lt;a href="http://www.selenic.com/mercurial/wiki/"&gt;Mercurial&lt;/a&gt; distributed version control system. I'm a big fan of of distributed version control.   However, one thing that drives me nuts is this error message:&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;% hg merge&lt;br/&gt;abort: outstanding uncommitted changes&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;This isn't just going to be a rant - I've finally found a solution which is working extremely well for me. I've suggested it to some other developers who have also reported that it works well for them, so I thought I would share it with you.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The reason I run into this all the time is my preferred style of work:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; I like to work on many things simultaneously. If while working on something, I come across a bug and I spot the problem, I just fix it right there and add a test for it.  When I get ideas, I might go and put &lt;code&gt;@todo&lt;/code&gt; tasks for myself, or leave editorial comments in various source files. I might also work on a couple of larger tasks simultaneously. Yes, I know the preferred Mercurial idiom for this is to have multiple clones, one for each task - but that isn't &lt;b&gt;my&lt;/b&gt; preferred way of doing it. Each NetBeans clone is huge and takes a while to both clone and build - and I would have to switch my IDE editing context between these large source trees all the time.&lt;br/&gt;&lt;br/&gt;&lt;li&gt; I like to check things in in logical chunks with a message that pertains to that particular change. This means I often check in a subset of the edited files in the tree.&lt;br/&gt;&lt;br/&gt;&lt;li&gt; I like to check in code regularly rather than leaving all files edited until I'm ready to check everything in.&lt;br/&gt;&lt;br/&gt;&lt;li&gt; I like to keep up to date. I'm using the bits I'm working on and I report problems when I see them so I want to make sure these are truly new and current bugs.  Therefore, I update to the tip at least every day.&lt;br/&gt;&lt;br&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;It turns out that the above requirements are tricky to fulfill with a default setup. Here's what happens.&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; I'm working on something and a high priority bug comes in. I find and fix it. I check in just the fix for this one problem. I&lt;br/&gt;still have many other edited files in my clone since I was in the middle of something else.&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt; Since it's a high priority bug, I want to push it. However, when I do, I get this:&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;% hg push&lt;br/&gt;pushing to https://tor:***@hg.netbeans.org/main/&lt;br/&gt;searching for changes&lt;br/&gt;abort: push creates new remote heads!&lt;br/&gt;(did you forget to merge? use push -f to force)&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;This tells me that somebody has checked in something since my last pull. That happens a lot with a project like NetBeans&lt;br/&gt;where there are checkins every few minutes.&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt; No problem - I'll just pull down their changes, merge, and push again, right?&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;% hg pull &amp;&amp; hg update&lt;br/&gt;pulling from http://hg.netbeans.org/main/&lt;br/&gt;searching for changes&lt;br/&gt;adding changesets&lt;br/&gt;adding manifests&lt;br/&gt;adding file changes&lt;br/&gt;added 1 changesets with 1 changes to 1 files (+1 heads)&lt;br/&gt;(run 'hg heads' to see heads, 'hg merge' to merge)&lt;br/&gt;abort: crosses branches (use 'hg merge' or 'hg update -C')&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;Ah, I couldn't just update, I have to merge since I have checked in changesets of my own. Let's do that:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;% hg merge&lt;br/&gt;abort: outstanding uncommitted changes&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;!@#@%*#%$%&amp;*$ !  Now, if I have dozens of changes, what do I do? When I first started using Mercurial, I would either&lt;br/&gt;try to finish my other changes and check them in and then try the merge again, or if I really wasn't ready to do that,&lt;br/&gt;I would copy the contents of my modified files to another location, hg revert the changes, and try again.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;It's not unreasonable of Mercurial to insist that you cannot merge with uncommitted changes.  When it's merging, it will think&lt;br/&gt;file modifications in the clone are your manual edits to resolve any merge conflicts.  However, it does make using&lt;br/&gt;my workflow difficult.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;h3&gt;The Solution&lt;/h3&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;It's really very simple: Use two clones. Do all your work in clone "main", and all your merging and pushing from clone "sync".&lt;br/&gt;Let's say the main repository is "master", and your two clones are "main" and "sync":&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtC6v1mSI/AAAAAAAAA3g/mM6nqEgXtDg/clones.jpg" /&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;To get set up, either clone the master repository twice, or, you can clone your main locally, but be sure to update&lt;br/&gt;the "parent" reference in your &lt;code&gt;sync&lt;/code&gt; clone such that it points to the master instead of your working clone&lt;br/&gt;(I do that by copying &lt;code&gt;main/.hg/hgrc&lt;/code&gt; to &lt;code&gt;sync/.hg/hgrc&lt;/code&gt;.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's the new workflow:&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt; As before, work in main. Edit files at will, and check in logical changesets as needed.&lt;br/&gt;&lt;br&gt;&lt;li&gt; When you want to push a changeset, go to your &lt;code&gt;sync&lt;/code&gt; clone, and pull your new changesets from your working clone:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;% cd ../sync&lt;br/&gt;% hg pull ../main &amp;&amp; hg update&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;At this point, it's best to try a build/test as well, to make sure changeset is complete. If you're working&lt;br/&gt;on many things in parallel, it's possible that your changeset is depending on a change in a file you haven't&lt;br/&gt;checked in yet.&lt;br/&gt;&lt;br&gt;&lt;li&gt; Now pull in the new changes from the master, and merge these:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;% hg fetch&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;(Or if don't have the fetch extension installed, do it manually - &lt;code&gt;hg pull &amp;&amp; hg merge &amp;&amp; hg ci -m "Merge"&lt;/code&gt;).&lt;br/&gt;&lt;br&gt;&lt;li&gt; If something went wrong with the merge - no problem. You can just go and nuke the entire &lt;code&gt;sync&lt;/code&gt; clone&lt;br/&gt;and try again! Your modified files, and your new changesets, are still sitting completely unaffected in the &lt;code&gt;main&lt;/code&gt;&lt;br/&gt;clone. Just clone &lt;code&gt;sync&lt;/code&gt; again and try more carefully :)&lt;br/&gt;&lt;br&gt;&lt;li&gt; Now you can push your merged changesets to the master repository:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;% hg push&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;li&gt; ...and now you can pull these changes back into your &lt;code&gt;main&lt;/code&gt; repository:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;% hg pull ../sync &amp;&amp; hg update&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;This will give you all the tip changes into your working clone, but without the risk of causing multiple heads that you&lt;br/&gt;have to merge. You've already merged your local changesets over in the &lt;code&gt;sync&lt;/code&gt; clone, and therefore there is no&lt;br/&gt;conflict between your local changesets and the new changesets in the tip!&lt;br/&gt;&lt;br&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;This process may seem tricky, but it's trivial once you try it:&lt;br/&gt;&lt;blockquote&gt;&lt;br/&gt;Work in &lt;code&gt;main&lt;/code&gt;, push and merge in &lt;code&gt;sync&lt;/code&gt;, and pull back into &lt;code&gt;main&lt;/code&gt;.&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;&lt;br/&gt;Finally, I want to call attention to item #4. Doing it this way means that it's trivial to try again if something wrong happens&lt;br/&gt;during the merge. I've had a couple of merges where I've really mucked things up. Unfortunately, this was in my tree that contained&lt;br/&gt;the changesets that I cared about. In the end I had to go and manually copy out the files I wanted to check in and try again. With&lt;br/&gt;the above approach, if something goes wrong, just nuke the sync clone and try again.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This is the reason I'm suggesting this approach to anyone using Mercurial, not just people who want to work with edited files.&lt;br/&gt;Especially when you're new to distributed version control systems or Mercurial, it's great to be able to go back if you make&lt;br/&gt;a mistake. Just make sure you know what you're doing before you submit that final &lt;code&gt;hg push&lt;/code&gt; command to push everything&lt;br/&gt;back to the master repository!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-7528547404356258666?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/7528547404356258666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/10/mercurial-tip-checking-in-regularly.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7528547404356258666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/7528547404356258666'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/10/mercurial-tip-checking-in-regularly.html' title='Mercurial Tip: Checking in regularly with uncommitted changes in your clone'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtC6v1mSI/AAAAAAAAA3g/mM6nqEgXtDg/s72-c/clones.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-1544052509957063231</id><published>2008-09-09T09:22:00.000-07:00</published><updated>2010-09-17T13:49:12.341-07:00</updated><title type='text'>Find Memory Leaks!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I'm back!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I'm sorry I've been quiet on this blog, but I've just taken a long vacation. It's been a few years since my last long vacation, so I really enjoyed it. On top of that, we bought a house, moved and made some home improvements, and that turned out to be a lot of work. Anyway, I've been back several weeks now and I'm back in full swing. There are a lot of things going on. I'm doing various performance and stability fixes for NetBeans 6.5, I've done some updates in the Ruby support, and I'm also working on Python support. I'll definitely be saying more about that here, soon, but I'm not quite ready yet.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;While I was on vacation, a high priority bug came in that I had to look at. It was basically complaining about a big memory leak, and my code looked like the culprit. So I used our memory analyzer. I hadn't used it before, but it was unbelievably easy and powerful, so I thought I'd show a couple of pictures of how to use it here, in case any of you have worried about your own memory leaks or how to fix them.&lt;br/&gt;I'll show the actual bug I tracked down, so this isn't a made up fake example.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;First, get a heap dump. In my case, the submitter had produced it - but if not, with Java 6 you can just run a &lt;code&gt;jmap&lt;/code&gt; command to generate it from a running VM (&lt;a href="http://blogs.sun.com/alanb/entry/heap_dumps_are_back_with"&gt;more info&lt;/a&gt;).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Then, go to the Profiler menu in NetBeans and invoke Load Heapdump:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuKtSX4FI/AAAAAAAABBE/8ul2_OMTNxQ/heap-load.jpg"&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;After NetBeans has loaded in the dump file, you can switch to the Classes view to see a sorted view of your memory usage.&lt;br/&gt;There's a filter to let you search for specific classes, but you'll typically want to go for the classes near the top anyway&lt;br/&gt;since that's where you're going to get bang for your buck.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOs9gB0xzI/AAAAAAAABXY/ozztNfZm6Kk/heap-classes.jpg"&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;Here I'm concerned with the javascript TokenStream.LexingState objects. So I have picked a class to focus on, and then I&lt;br/&gt;ask NetBeans to show all the instances of my class in the heap:&lt;br/&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuSu-UaiI/AAAAAAAABCA/CDqvSUh9ZbU/heap-show-instances.jpg"&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;You can now pick among the various instances in the left hand window and find one you don't believe should still&lt;br/&gt;be in memory. Once you select it, NetBeans will search the heap to find the referenes which point to this instance.&lt;br/&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtMK_RZtI/AAAAAAAABX4/tYny2ZFZiWQ/heap-instances.jpg"&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;So, you can look at all the objects in the heap of this class, and then you can follow references within the&lt;br/&gt;objects to other objects, or in the References view (on the bottom), you can follow references backwards to see&lt;br/&gt;who is pointing to this object, recursively!&lt;br/&gt;&lt;br/&gt;Now, the really good part. I'm wondering why so many of these objects are still live - how are they referenced&lt;br/&gt;from the top? I can right click on the object and ask it to show me:&lt;br/&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtknl78kI/AAAAAAAAA8k/Hz_21sHGeT8/heap-find-gc.jpg"&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;NetBeans will search for a while, and then show a complete path from a GC root down to my object. Now I just&lt;br/&gt;need to walk back from the GC root and examine each object to decide if it's justified in holding this&lt;br/&gt;reference. In this screenshot I've selected the item which was the problem. As the little red badge&lt;br/&gt;shows (also described in the legend at the bottom of the window), this is a &lt;i&gt;static&lt;/i&gt; reference.&lt;br/&gt;This class had created a static map which eventually end up holding a lot of context which should have&lt;br/&gt;been freed up. Best of all, in this case, the culprit wasn't mine so I was able to dispatch the&lt;br/&gt;bug to another developer and go back to my vacation :)&lt;br/&gt;&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOs-BvMUaI/AAAAAAAABXg/ZLmoBWTmXcs/heap-gc-path.jpg"&gt;&lt;br&gt;&lt;br/&gt;&lt;br/&gt;In C, you can have true memory leaks where you've allocated memory and you no longer have a reference to it,&lt;br/&gt;so the memory is truly lost. In Java, with garbage collection, there's no true leak, only "unintentonally held memory".&lt;br/&gt;In other words, this feature isn't just for those of you with memory leaks (where you're running out of memory).&lt;br/&gt;You can use this feature to find out if you're holding more references than you're intending to. Freeing things&lt;br/&gt;up can improve your application's performance and definitely reduce its resource requirements. So please give&lt;br/&gt;it a try!   I know there are other tools that can help track down memory issues - I've used some in the past - but&lt;br/&gt;this was unbelievably simple (and by being integrated in my IDE, the Go To Source action on references made it&lt;br/&gt;really tricky to figure out WHY there were references as I was checking each reference back from the GC root).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-1544052509957063231?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/1544052509957063231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/09/find-memory-leaks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1544052509957063231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1544052509957063231'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/09/find-memory-leaks.html' title='Find Memory Leaks!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuKtSX4FI/AAAAAAAABBE/8ul2_OMTNxQ/s72-c/heap-load.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5195966522327843823</id><published>2008-07-26T02:52:00.000-07:00</published><updated>2010-09-17T13:49:12.329-07:00</updated><title type='text'>Screenshot of the Week #31: Python, Groovy</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;In my &lt;a href="http://blogs.sun.com/tor/entry/multilingual_netbeans"&gt;language support blog entry&lt;/a&gt; last week I talked briefly about the PHP, Python and Scala work going into 6.5. That's not an exclusive list. We're also adding Groovy support, and it's making great progress. &lt;a href="http://martin.adamek.sk"&gt;Martin Adamek&lt;/a&gt; is posting status updates on his blog; here's Groovy instant rename in action:&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtbg9UCbI/AAAAAAAAA7E/sjG8bHgM8O4/groovy.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The Python work is making good progress too. Here's code completion now for methods and classes, with integrated documentation support:&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsMy757AI/AAAAAAAAAwA/BuxJurHTZLk/python-completion.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's another screenshot: Python quickfixes:&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtOdqgjBI/AAAAAAAABX8/6MBIAdsVR9s/python-quickfixes.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Anyway, I'm going on "vacation" now for a few weeks. I put that in quotes because I'm moving, and honestly, packing, cleaning and moving is hard work. Coding, now that's fun. I can't wait for my real vacation to start when I get back to work.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5195966522327843823?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5195966522327843823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/07/screenshot-of-week-31-python-groovy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5195966522327843823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5195966522327843823'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/07/screenshot-of-week-31-python-groovy.html' title='Screenshot of the Week #31: Python, Groovy'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtbg9UCbI/AAAAAAAAA7E/sjG8bHgM8O4/s72-c/groovy.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6940915508193182865</id><published>2008-07-15T03:30:00.000-07:00</published><updated>2010-09-17T13:49:12.321-07:00</updated><title type='text'>Multilingual NetBeans: PHP, Python, Scala</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I've mostly been writing about Ruby and JavaScript on this blog, but NetBeans is getting strong language support in other languages as well!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;First, take a look at the PHP support. Petr Pisl, Tomas Slota, Radek Matous, Tomas Mysik and others have been posting screenshots and&lt;br/&gt;feature descriptions regularly on their team &lt;a href="http://blogs.sun.com/netbeansphp/"&gt;NetBeans PHP blog&lt;/a&gt;. Check it out - code completion,&lt;br/&gt;quick fixes, semantic highlighting - we're going to have a fantastic PHP IDE!  Here's a screenshot - look at the unused method detection for example:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOui6q8coI/AAAAAAAABD0/molZv00PojU/php.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The &lt;a href="https://nbpython.dev.java.net/"&gt;Python support&lt;/a&gt; is starting to shape up too - here's a screenshot of code folding, semantic highlighting and instant rename refactoring.&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuXzZHZDI/AAAAAAAABCo/mScRS0p25HE/python.jpg"&gt;&lt;br/&gt;&lt;br&gt;Coming soon - code completion and other editing goodies.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;And I just now noticed a &lt;a href="http://blogtrader.net/page/dcaoyuan/entry/employ_scala_s_native_compiler"&gt;post from Caoyuan Deng&lt;/a&gt;&lt;br/&gt;that his Scala support for NetBeans is now built on top of the native scala compiler. His editing support is already feature packed (take a look at his blog for some of the past entries) and now that he has 100% language parity things are looking very very good!&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrvVK9GPI/AAAAAAAABUM/jdeHeb06qpA/scala.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Last but not least: InfoWorld has &lt;a href="http://www.infoworld.com/article/08/07/07/28TC-ruby-ides_1.html"&gt;reviewed 9 Ruby IDEs&lt;/a&gt;,&lt;br/&gt;and NetBeans came out on top!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6940915508193182865?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6940915508193182865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/07/multilingual-netbeans-php-python-scala.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6940915508193182865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6940915508193182865'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/07/multilingual-netbeans-php-python-scala.html' title='Multilingual NetBeans: PHP, Python, Scala'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOui6q8coI/AAAAAAAABD0/molZv00PojU/s72-c/php.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-1923248929261270845</id><published>2008-07-06T15:11:00.000-07:00</published><updated>2010-09-17T13:49:12.310-07:00</updated><title type='text'>Ruby Screenshot of the Week #30: New YAML Editor</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;As part of our Ruby and Rails support, we've had a YAML editor in NetBeans for a couple of releases now.  However, the support was primitive. Only the most basic editing features were there, and more problematically, many common, valid YAML constructs were not supported. You'd get various wrong error messages from the parser if you tried to go outside the normal simple syntax of the &lt;code&gt;database.yml&lt;/code&gt; file in Rails.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In the latest dev builds however, there's a brand new implementation of a YAML editor. Let's start with a screenshot:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuesP-z4I/AAAAAAAABZ8/6kqLcjV1ofc/yaml.jpg"&gt;&lt;br/&gt;&lt;br&gt;There are several things going on here. First, note that the editor now understands more complicated YAML constructs - such as the &amp;lt;&amp;lt; key mapping merge operator. In this file, we've shared the definition of the "createdon" attribute. And in the navigator, as we drill down you can see this attribute showing up properly inlined in both places the reference was used.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Notice also how we have embedded Ruby code here (the green fragment inside &amp;lt;% %&amp;gt;). This is pretty important for another Rails usage of YAML: Fixtures.  Just like in ERb/RHTML files, the YAML Ruby embedding support should be complete; quickfixes should work, go to declaration, smart indent and formatting, and so on - including code completion:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsugOHo5I/AAAAAAAAA0k/3V6OsHuDXe0/rubyyamlcompletion.jpg"&gt;&lt;br/&gt;&lt;br&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finally, if you're a bit rusty on YAML and can't remember all the various escapes to do collections, aliases, documents, tags and so on, you can invoke normal code completion to see the various special characters - along with the YAML quick reference document in the documentation popup:&lt;br/&gt;&lt;br&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsxXYfLSI/AAAAAAAAA1A/Pwm-86Z_X8Y/yamlcompletion.jpg"&gt;&lt;br/&gt;&lt;br&gt;There are a few other things in there as well; AST based selection (Command-Shift-Dot or Comma), slightly better smart indent, and so on. One thing which is still missing is code folding. I disabled it since there were a few issues with it still.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I have to pause here and add a big Thank You to &lt;a href="http://ola-bini.blogspot.com/"&gt;Ola Bini&lt;/a&gt; from the JRuby team!   A few weeks ago, yet another bug report was filed by somebody complaining about a false error in the YAML support, and I decided to look into rewriting it from scratch using the same editor infrastructure that we have for Ruby, JavaScript, etc.  The first thing I would need however is a YAML parser. I know JRuby had a good one, so I tried using it - but realized I would need to customize it a bit for IDE purposes. For example, I would need AST offset information. I thought of ways I could subclass parts of the YAML parser to achieve this, and I sent an e-mail to Ola asking if he thought this was feasible. I immediately got a response - and not only did he say it was possible, he offered to personally do it, by adding proper offset support into the parser.  And just a couple of days later he released a new version of the parser with full offset support. It worked perfectly. With the parser in hand, implementing the above editing functionality was easy. So a lot of the credit for the new editor goes to Ola. Thank you!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As always with new functionality, please take it for a spin and report back any issues you find (using the normal &lt;a href="http://wiki.netbeans.org/RubyFeedback"&gt;feedback channels&lt;/a&gt;).  NOTE - you do need the latest dev builds for this - even 6.5 Milestone 1 is too old. Some of this was checked in today so won't even be in the current nightly build (depending on when you read this).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-1923248929261270845?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/1923248929261270845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/07/ruby-screenshot-of-week-30-new-yaml.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1923248929261270845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1923248929261270845'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/07/ruby-screenshot-of-week-30-new-yaml.html' title='Ruby Screenshot of the Week #30: New YAML Editor'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuesP-z4I/AAAAAAAABZ8/6kqLcjV1ofc/s72-c/yaml.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-367588783231328654</id><published>2008-06-24T05:20:00.000-07:00</published><updated>2010-09-17T13:49:12.302-07:00</updated><title type='text'>Ruby Screenshot of the Week #29: Test Navigator for RSpec</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Let's start with the screenshot:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOu6lC8DoI/AAAAAAAABaw/ir_BFLm2rt8/test-navigator.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The thing to notice here is that we have a number of RSpec do-blocks in this file.  Until now, only classes, methods, fields and attributes were showing up in the navigator. But in the latest daily builds, rspec do blocks like these are shown in the navigator (bottom left corner), along with the string summary (if any) such that you can quickly navigate between them.  Placing the caret in one of these blocks will highlight the corresponding item in the navigator.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Adding a better navigator outline for spec files has been on the TODO list for a while, but apparently in the latest Rails builds regular tests are also switching away from using test methods to using test blocks (according to &lt;a href="http://www.netbeans.org/issues/show_bug.cgi?id=137925"&gt;issue 137925&lt;/a&gt;, thanks James). So it seemed high time to do something about this.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The other thing to notice is that these blocks are also folded, so you can use Command-Shift-+ and - to collapse/expand all blocks quickly.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;By the way, another old issue was fixed in NetBeans recently, which makes it easy to configure filetypes. In the past, if you wanted say .mab files to get Ruby treatment in the IDE, you'd file an issue and I'd modify the Ruby mimetype resolver to include it.  The list is already pretty long -- .rb, .rake, .rxml, .rjs, .rbw, .rbx, .mab, .builder, .gemspec, and so on.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Now you can add any extra types you want yourself, using the Options | Miscellaneous | File Associations. Add any extensions you want, and bind them to the Ruby mime type and all the various Ruby editing machinery should kick in for files of that type.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtbUXThDI/AAAAAAAAA7A/V-A6xUmuLOQ/file-associations.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;NetBeans 6.5 Milestone 1 is about to be released and there are a lot of goodies there - both in the Ruby specific featureset as well as generic IDE support (such as the new Quick Search functionality). I'll look into that for another entry. And apologies for the long delay since my last entry - I blame it on a combination of having been sick, having taken some time off and having been busy with work...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-367588783231328654?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/367588783231328654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/06/ruby-screenshot-of-week-29-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/367588783231328654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/367588783231328654'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/06/ruby-screenshot-of-week-29-test.html' title='Ruby Screenshot of the Week #29: Test Navigator for RSpec'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOu6lC8DoI/AAAAAAAABaw/ir_BFLm2rt8/s72-c/test-navigator.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8818229838047584993</id><published>2008-05-29T14:06:00.000-07:00</published><updated>2010-09-17T13:49:12.291-07:00</updated><title type='text'>Ruby Screenshot of the Week #28: Unit Testing, and Color Themes</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;NetBeans 6.1 has been out for a while, so we're working full steam ahead on NetBeans 6.5. There are a number of new features in the trunk, and I'll show a couple of them in this post.  First of all though - if you have found ERB or RHTML file editing slow in NetBeans 6.1, please try NetBeans 6.5. There was a performance bug where if you have a lot of JavaScript files in your public/javascript folder, RHTML editing gets really slow. A fix for this will be released, but it didn't make it into Patch 1 so it will be addressed in patch 2.  But the daily builds of NetBeans 6.5 has the fix, so if this bug is affecting you, please try the dailies instead. And as a side benefit, you'll be able to access the following features:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;h3&gt;&lt;br/&gt;New Unit Test Runner!&lt;br/&gt;&lt;/h3&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Erno Mononen has &lt;a href="http://blogs.sun.com/emononen/entry/new_test_runner_ui"&gt;written a new Test Runner UI&lt;/a&gt;. In 6.1, unit tests were just run and the normal output shown in the Output Window with some hyperlinks.  In the new dedicated test runner, you get something similar to the JUnit window we've had for a file for Java.  (Click on image for full size)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;a href="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrmSnhPnI/AAAAAAAABTk/9RyatZndPmY/testrunner.jpg"&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtgz2el-I/AAAAAAAAA78/LPsNdBBu5CY/testrunner-small.jpg" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Be sure to run your test classes &lt;b&gt;as tests&lt;/b&gt; (e.g. use Ctrl/Command F6 rather than Shift F6) such that the IDE will run your classes under the testing GUI. This works not just for Test::Unit but for RSpec as well. You can get more details about this in &lt;a href="http://blogs.sun.com/emononen/entry/new_test_runner_ui"&gt;Erno's blog entry&lt;/a&gt;, and if you run into issues, please &lt;a href="http://wiki.netbeans.org/RubyFeedback"&gt;let us know&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;h3&gt;&lt;br/&gt;The Aloha Color Theme&lt;br/&gt;&lt;/h3&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Mike McKinney has created a really nice dark color theme for NetBeans, called Aloha. I've taken his theme and have integrated it into our "Extra Color Themes" plugin which is available from the Daily Update Center (and soon, the Stable Update Center). To install it, get the plugin, and then go to the Options dialog and choose Aloha under the Fonts &amp;amp; Colors category. You can see more screenshots of Mike's theme in his &lt;a href="http://blog.huikau.com/2008/04/28/aloha-color-theme-for-netbeans-61/"&gt;blog entry&lt;/a&gt;. In previous releases we had some problems with CSS and JavaScript colors not being customizeable, but that is not a problem as of NetBeans 6.1 so hopefully all the file types look great. We still need to make the version control diffbar and the debugger breakpoint and current pc lines respect the current theme; hopefully we'll get to that in NetBeans 6.5.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOth0RmrqI/AAAAAAAABYU/95JqxjHd6O4/aloha.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;By the way, you may notice that you only see the editor here. When you press Shift-Escape, the current window with focus gets maximized. I do that while editing a lot. You can press Shift-Escape to toggle it back - and you can also temporarily open the other windows (which you can see slide to the edges) by just hovering the mouse over them.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finally, one minor feature which can come in handy in NetBeans 6.5 is that "Mark Occurrences" now has a keyboard shortcut for navigating between the references. Thus, if you put your caret on some symbol, you've probably noticed that it gets highlighted - along with other occurrences of that symbol in the same file. You can now use Control-Up and Control-Down to jump between these references. Pretty handy.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Oh, and one more thing - JRuby 1.1.2 was released a few days ago and NetBeans now bundled it - along with RSpec 1.1.4.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8818229838047584993?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8818229838047584993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/05/ruby-screenshot-of-week-28-unit-testing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8818229838047584993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8818229838047584993'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/05/ruby-screenshot-of-week-28-unit-testing.html' title='Ruby Screenshot of the Week #28: Unit Testing, and Color Themes'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtgz2el-I/AAAAAAAAA78/LPsNdBBu5CY/s72-c/testrunner-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2547747924801196128</id><published>2008-05-11T12:56:00.000-07:00</published><updated>2010-09-17T13:49:12.281-07:00</updated><title type='text'>JavaOne 2008</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;img align="left" style="margin-right: 5px; margin-bottom: 5px" src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuUmKT0YI/AAAAAAAABCQ/CwlqBRW3g0M/JavaOne2008DF_414.1600x1200-small.jpg" /&gt; JavaOne 2008 is over. As usual, it was a great event, but with the stress and hard work leading up to the conference, it's a huge relief that it's all over. For my part, it was another extremely busy JavaOne, with two keynote demos, a technical session, a panel discussion, a BOF, as well as three presentations at CommunityOne the day before.  If you add to that the prep time for these (keynote software setup and rehearsals, slide planning etc.) there was barely time for anything else, so despite my best intentions I didn't get to meet up with a lot of the out-of-towners visiting JavaOne that I had planned to. I only made it to three technical sessions - and in all three I learned something. Hopefully the rest of the sessions that I missed had the same high level of quality.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;a href="http://www.amazon.com/Secrets-Rock-Star-Programmers-Riding/dp/0071490833"&gt;&lt;img border="0" align="right" style="margin-left: 5px; margin-bottom: 5px" src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOukOiFpeI/AAAAAAAABEA/aTYDHku5DfM/rockstar-cover.jpg" /&gt;&lt;/a&gt; I was interviewed by the JavaOne paper on Wednesday; the online interview is &lt;a href="http://java.sun.com/javaone/sf/2008/articles/rockstar_tornorbye.jsp"&gt;here&lt;/a&gt;. If you read my blog you might find it interesting.  However, in the paper version of the interview, something went horribly wrong... Some of the questions and answers attributed to me were from a previous interview! In particular, I'm found endorsing the Flex SDK, as well as talking about my "math background". Those parts were from the previous day's interview with Chet Haase!&lt;br/&gt;If you're wondering why I'm referred to as a "Rock Star" in the interview, that's a JavaOne thing. The top 20 highest rated talks each year (as determined by the speaker survey forms collected for all talks) earn their speakers a lifetime "Rockstar" title at JavaOne. And speaking of Rockstars, I've got independent verification that I am one (wink, wink) since Ed Burns also interviewed me (and the other JavaPosse guys) for his &lt;a href="http://www.amazon.com/Secrets-Rock-Star-Programmers-Riding/dp/0071490833"&gt;Secrets of Rock Star Programmers&lt;/a&gt; book. The interview was conducted a year ago, but the book is out now. I've read some of the chapters already and really enjoyed it.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;It's always exciting to be part of the keynote demos. It's a huge production with over 10,000 people in the keynote hall. A lot of work goes into it. There's a control room in the back, NASA ground-control style. Arun Gupta snapped a few pictures during rehearsals this year and posted them  &lt;a href="http://weblogs.java.net/blog/arungupta/archive/2008/05/take_1_pictures_1.html"&gt;here&lt;/a&gt;. The 10th picture gives a sense of the size of the hall. &lt;img align="left" style="margin-right: 5px; margin-bottom: 5px" src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtVkn85lI/AAAAAAAAA6Q/5qSf0a2zE4o/javaone-small.jpg" /&gt; On the left is a drawing one of my kids drew of how she imagined my keynote demo - it would be nice if we actually had chairs to sit on. I guess when you're a kid you wouldn't imagine standing up while doing things on a computer!   Anyway, you can see the webcasts from the keynotes - they are all available &lt;a href="http://java.sun.com/javaone/sf/sessions/general/index.jsp"&gt;here&lt;/a&gt;. In particular, you can see our Tic Tac Toe demo &lt;a href="http://java.sun.com/javaone/sf/media_shell.jsp?id=FRdamp267556"&gt;here&lt;/a&gt; (about 2:20 into it), and the JavaScript editing demo &lt;a href="http://java.sun.com/javaone/sf/media_shell.jsp?id=sgs4"&gt;here&lt;/a&gt; (about 19:45 into it).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;a href="http://javaposse.com"&gt;&lt;img align="right" style="margin-left: 5px; margin-bottom: 5px" src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsC9ucl0I/AAAAAAAAAuU/L2slAqWeGoE/posse-small.jpg" /&gt;&lt;/a&gt; The &lt;a href="http://javaposse.com/index.php?post_id=337675"&gt;Java Posse BOF&lt;/a&gt; was another highlight for me. We had a short appearance at CommunityOne, but with just 20 minutes we didn't quite get into the groove. Thursday night for our BOF however, and with beer, we had a great atmosphere. We had feared a really low turnout since our BOF was scheduled smack in the middle of the Smashmouth concert - but that turned out not to be a problem, either because it was cold outside, or because a lot of people hadn't heard of Smashmouth (think the movie soundtrack from Shrek), or perhaps because we have really loyal listeners! If so, thank you!!   A contingent of Norwegian listeners came up and handed us a lot of Norwegian chocolate! I didn't catch your names - but thank you very much! My local gym also thanks you...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;My brother (who also works at Sun and has his own &lt;a href="http://blogs.sun.com/trond/"&gt;blog&lt;/a&gt;) has been staying with us for the last month - first for the MySQL conference in April, then JavaOne. It's been great having him here. We tried to get him on the air in one of our podcasts, but he refused - so instead we embarassed him during our BOF with a dedicated slide and tribute! He headed back to Norway this morning; Trond, it's been great to have you here and welcome back.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I'm taking a few days off now to catch up on sleep and chores!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2547747924801196128?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2547747924801196128/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/05/javaone-2008.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2547747924801196128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2547747924801196128'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/05/javaone-2008.html' title='JavaOne 2008'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuUmKT0YI/AAAAAAAABCQ/CwlqBRW3g0M/s72-c/JavaOne2008DF_414.1600x1200-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-3596162159682775864</id><published>2008-04-29T07:03:00.000-07:00</published><updated>2010-09-17T13:49:12.271-07:00</updated><title type='text'>JavaScript Type Inference in NetBeans</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Roman Strobl has just&lt;br/&gt;&lt;a href="http://www.netbeans.org/download/flash/js/javascript_demo.html"&gt;published a screencast&lt;/a&gt; of the new JavaScript editor in NetBeans 6.1. The demo is around 5 minutes and highlights many of the editing features.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I'd like to dwell on the type inference part a bit. Around four minutes into the demo, Roman shows that NetBeans figures out the types of expressions, including those involving function calls. In his example, all the types happened to be Strings so it may look like a lucky coincidence. It's not! Here's some code fragments showing in more detail what's going on. Let's start with a jQuery expression in an HTML file - in my&lt;br/&gt;&lt;a href="http://blogs.sun.com/tor/entry/netbeans_javascript_ruby"&gt;last entry&lt;/a&gt;&lt;br/&gt;I showed how code completion already&lt;br/&gt;helps you fill in the strings inside the jQuery dollar function. NetBeans knows the return type of the dollar function so we're only presented with jQuery methods here:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOreYdY25I/AAAAAAAAAos/Brny1vl2jXs/types1.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;jQuery methods return the jQuery object itself as the return value, so we can chain calls into jQuery. We'll do that here by calling a function on the return value from &lt;code&gt;addClass&lt;/code&gt;:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOumyo5JvI/AAAAAAAABEY/ACrbPlRR7ls/types2.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As you can see, when NetBeans knows the return type of a function, it's shown in code completion item separated by a colon. Here I want to call the &lt;code&gt;queue()&lt;/code&gt; method which returns an array of functions.  Let's see what happens if we just call functions on the result object:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuBPnUNnI/AAAAAAAABZQ/CBXcv305OSI/types3.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As you can see - we're getting methods on the Array class, since we're getting an array back. Let's pick a specific element in the array instead, and see what code completion gets us:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuBoi2mkI/AAAAAAAABAE/0e60rkvyvBE/types4.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As you can see it knows that this must be a Function, so we get for example the &lt;code&gt;apply&lt;/code&gt; method suggested. (Put another way, we're tracking internally the type of the elements within the array.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;At this point you may wonder where these types come from. JavaScript is not a statically typed language, so what gives?  It turns out that while JavaScript isn't typed, a lot of code is written with specific types in mind, and in fact there are a lot of documentation conventions for declaring the intended types not just of function return values, but of parameters and properties as well. NetBeans understands many of these - such as &lt;code&gt;@param {Type}&lt;/code&gt;, &lt;code&gt;@return {Type}&lt;/code&gt;, and &lt;code&gt;@type&lt;/code&gt;.   Here's a new function we've added in the editor which declares a return type:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuyH_sNAI/AAAAAAAABF4/O_yJvOsfu1s/types-specified.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As you can see, when we try to invoke code completion on the return value of this function, it's using the return type we specified - the &lt;code&gt;Date&lt;/code&gt; class.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;However, it doesn't end there. In many cases, NetBeans can also figure out the type without it needing to be explicitly specified. Here's a function without a type declaration, yet NetBeans knows what to do with the return value:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOs4i1E9LI/AAAAAAAAA2A/x0RnTd7afIo/types-inferred.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This is an area where the type handling in NetBeans is currently better for JavaScript than for Ruby.  Ruby doesn't have the same convention of documenting types for libraries. In fact, many Rubyists feel that this would be counter to what Ruby is all about: Methods shouldn't know what the types of the parameters are - all that matters is what the objects respond to the required method names used by the function.   However, for people who -want- IDE help, improved type documentation could certainly help. And NetBeans understands some Ruby type assertions for parameters:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsWvK5ruI/AAAAAAAAAxM/0csby_a7kO0/ruby-types.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There are several efforts to allow type hints for Ruby. For example, Charlie Nutter's &lt;a href="http://headius.blogspot.com/2008/03/duby-type-inferred-ruby-like-jvm.html"&gt;Duby&lt;/a&gt; project uses type hints to generate more efficient bytecode for Ruby execution - and the same hints could be interpreted by the IDE to assist with code completion, go to declaration, etc.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finally, as the last JavaScript screenshot shows, there are many cases where it's easy to figure out what the return type will actually be for the current implementation of the method. That's an area I want to look into next, such that I can apply the principles I've applied for JavaScript to Ruby as well. Fun times ahead!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Let me finally apologize for my tardiness in responding to e-mail, blog comments, newsgroup posts etc. We're just a week away from JavaOne, so work is extremely hectic at the moment. But it's going to be a blast as always!  I hope to see many of you there - please say hi!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. I've been fixing quite a few bugs in the JavaScript support since the 6.1. code freeze. I'm hoping to get it all rolled into an AutoUpdate patch. If you're running into problems with 6.1, please give the daily builds a try!  By the way, Martin Krauskopf just integrated (into the daily build) a new &lt;a href="http://wiki.netbeans.org/RubyRake"&gt;Rake Runner&lt;/a&gt; for Ruby!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-3596162159682775864?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/3596162159682775864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/04/javascript-type-inference-in-netbeans.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3596162159682775864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3596162159682775864'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/04/javascript-type-inference-in-netbeans.html' title='JavaScript Type Inference in NetBeans'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOreYdY25I/AAAAAAAAAos/Brny1vl2jXs/s72-c/types1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-1702371767264080019</id><published>2008-04-04T07:55:00.000-07:00</published><updated>2010-09-17T13:49:12.255-07:00</updated><title type='text'>Screenshot of the Week #28:  NetBeans + JavaScript = True!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Apologies for my low activity on this blog recently. I've been swamped during the NetBeans 6.1 development cycle.&lt;br/&gt;The main reason is that I've been completely consumed reimplementing the JavaScript support in NetBeans. It is&lt;br/&gt;now built on the same infrastructure as the Ruby editor. It's been quite a sprint to get it done, but we're&lt;br/&gt;about to freeze NetBeans 6.1, and it's in. And I think NetBeans now compares quite favorably against other JavaScript&lt;br/&gt;IDEs and editors.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Does this mean I've moved on from Ruby, and the NetBeans Ruby support is now in maintenance mode?&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Far from it!  Not only did we double the size of the NetBeans Ruby team from 6.0 (when Martin Krauskopf and myself&lt;br/&gt;were the team); in 6.1 Erno Mononen and Peter Williams joined us. And I'm still in charge of and working on the&lt;br/&gt;Ruby editor - which in 6.1 adds complete Rails 2.0 support (and Rails 2.1 - I just yesterday integrated support&lt;br/&gt;for the new &lt;a href="http://dev.rubyonrails.org/ticket/11458"&gt;UTC timestamp migrations&lt;/a&gt;), as well as&lt;br/&gt;a bunch of new &lt;a href="http://wiki.netbeans.org/RubyHints"&gt;quickfixes&lt;/a&gt;, and tasklist integration, etc.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;However, a lot of the work I've been doing has been on the editing infrastructure, which benefits&lt;br/&gt;Ruby directly. For example, in NetBeans 6.1, the long file indexing process which would happen on every IDE startup&lt;br/&gt;now happens only on the first startup. And more importantly, we're much more robust now in handling complicated&lt;br/&gt;embedding scenarios in ERb/RHTML files. Where in 6.0 we had a lot of custom code to handle ERb specifically,&lt;br/&gt;the generic language embedding support we have now means that most Ruby (and JavaScript!) editing features work&lt;br/&gt;automatically and correctly in ERb files as well. So features like mark occurrences and semantic highlighting&lt;br/&gt;which were not available in 6.0 now work in ERb files as well for Ruby.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;My main motivation for working on the JavaScript editor was that we often got the feedback&lt;br/&gt;from NetBeans Ruby users along the lines of "I love your Ruby editor, but my Rails application also needs JavaScript,&lt;br/&gt;and I go to other tools for that". We want NetBeans to be a complete editing solution, and JavaScript is obviously&lt;br/&gt;vital for any web framework, including Rails.  Therefore, to be a top notch Ruby IDE, we have to have top notch JavaScript&lt;br/&gt;editing as well.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;So what are the new compelling JavaScript features in NetBeans 6.1? I'm not going to show everything here, but here's&lt;br/&gt;a Rails-focused introduction to some of the features.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;First, let's create a new Rails project. Then I open the &lt;code&gt;public/javascripts/prototype.js&lt;/code&gt; file that ships with Rails (click for full size):&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;a href="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsS9gA_LI/AAAAAAAABVs/yhKZtkUAeNw/javascript-prototype.jpg"&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOssNO8BUI/AAAAAAAAA0Q/QCIFYAB9_5Y/javascript-prototype-small.jpg" border="0" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;First, take a look at the semantic highlighting.  Prototype-style method definitions are bolded. As with Ruby, unused local variables, parameters and catch scope variables etc. will be detected and underlined. And NetBeans figures out the scope of variables and shows you global variables in a different color (green, but that is obviously configurable). This helps you find cases where you perhaps have a typo so instead of referencing a local variable, you're accidentally trying to read a nonexistent global variable.  Or, as is the case in this screenshot, they were probably accidentally declaring a global variable:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrkJNL2OI/AAAAAAAAApo/8p_9M_lAhBk/prototype-globals.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I doubt that the intention for this function was to leak out a new variable named position; the intention was probably to have included a &lt;code&gt;var&lt;/code&gt; keyword here to make the loop variable local like this:&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOs1NdQvkI/AAAAAAAAA1k/U38BRhFaS4o/prototype-locals.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Let's move on to the quickfixes. Take a look at the vertical scrollbar on the right - here it is again (flipped horizontally) :&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsWA4bmhI/AAAAAAAAAxI/xe1gqrcwqzE/prototype-scrollbar.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Each little yellow mark corresponds to a quickfix warning NetBeans has added at roughly that position in the source file. The tasklist view lists these such that you can sort by type. (This isn't some doctored up testcase file to exercise the quickfixes - this is the standard &lt;code&gt;prototype.js&lt;/code&gt; file.)&lt;br/&gt;Every quickfix type can be disabled - and they also offer links to more information about the error. Here's the warning for multiple return values:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuwaqgQJI/AAAAAAAABFo/wgDQjL4W0PQ/prototype-returnvalues.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The mark occurrences feature lists all the exit points of a function when you place the caret on top of the corresponding &lt;code&gt;function&lt;/code&gt; keyword. Here you can see that we have both a plain &lt;code&gt;return;&lt;/code&gt; with no return value, as well as another return with a value. How would a caller of this function treat the return value of this function?&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There are a lot more detectors, which I will describe in a future blog post.  Now, let's open the default &lt;code&gt;index.html&lt;/code&gt; file that ships with Rails. Here's code completion on the Prototype &lt;code&gt;$()&lt;/code&gt; function:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOshTpDNYI/AAAAAAAAAyo/MyTmS-6i2GE/prototype-dollar.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As you can see, it uses the HTML parse information (this is part of the language infrastructure I talked about earlier) to locate all the element ids in the document and offers those as completion. As you can see it includes those ids that were accessed by Rails' own &lt;code&gt;$&lt;/code&gt;-calls for the lines above.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Code completion also works with the Prototype &lt;code&gt;$$()&lt;/code&gt; function, which performs CSS selections. First, show the used element types in the document:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuWviO1rI/AAAAAAAABCg/pkn7s-4LonM/prototype-tag-completion.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Then filter on the HTML element classes in the document:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrawpK8vI/AAAAAAAAAoQ/R43k42hejNQ/prototype-classes.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There's just one - from a few lines later:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsDH11ubI/AAAAAAAAAuY/H7mxaaqx1as/prototype-classes-origin.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;We can also filter on the many CSS pseudo classes:&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr8g-Xs8I/AAAAAAAAAtU/3R2NxOwzKrg/prototype-css.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This post is already getting long so I won't get into all the JavaScript features now.&lt;br/&gt;&lt;a href="http://marxsoftware.blogspot.com/2008/03/netbeans-61-javascript-ide.html"&gt;Here's a blog entry&lt;/a&gt; somebody&lt;br/&gt;else wrote with some more features and screenshots.  The main point of this blog entry was to explain why&lt;br/&gt;I've been so busy, what's in store for NetBeans 6.1, and to reassure you that NetBeans Ruby and JavaScript support&lt;br/&gt;is going to continue developing at rapid clip.  Code editing is a top priority for NetBeans!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-1702371767264080019?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/1702371767264080019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/04/screenshot-of-week-28-netbeans.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1702371767264080019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1702371767264080019'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/04/screenshot-of-week-28-netbeans.html' title='Screenshot of the Week #28:  NetBeans + JavaScript = True!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOssNO8BUI/AAAAAAAAA0Q/QCIFYAB9_5Y/s72-c/javascript-prototype-small.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2915831343500403492</id><published>2008-03-13T02:17:00.000-07:00</published><updated>2010-09-17T13:49:12.237-07:00</updated><title type='text'>Feature Comparisons</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Aptana RadRails just shipped their 1.0 release. Congratulations!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;One thing that spoiled things a bit for me is the&lt;br/&gt;&lt;a href="http://www.aptana.com/rails#features"&gt;Feature Comparison matrix&lt;/a&gt; they posted on their website. Along with the predictable green column for RadRails, they have red X's next to a lot of features in the NetBeans column. Features that definitely are there in NetBeans (and in some cases I would argue more so than in Aptana).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you're going to post a feature comparison I think it's a bit irresponsible to do so without actually checking what the competition offers. NetBeans is free (and no registration is even required), so it's easy to download to check, and if you don't even want to do that, just google "NetBeans Ruby" which will point right to our &lt;a href="http://wiki.netbeans.org/Ruby"&gt;Wiki&lt;/a&gt; which has extensive feature lists listed right on the front page.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;(&lt;b&gt;Update&lt;/b&gt;: Their feature matrix has been updated, and now recognizes that NetBeans does in fact offer RHTML editing, YAML editing, and XML editing.) There are however a number of errors remaining. Here are some of them.&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; Yes, we have a JSON editor (and ours is free)&lt;br/&gt;&lt;li&gt; Yes, we also have TextMate templates (templates for &lt;a href="http://ruby.netbeans.org/codetemplates-ruby.html"&gt;Ruby&lt;/a&gt;,&lt;br/&gt;&lt;a href="http://ruby.netbeans.org/codetemplates-rhtml.html"&gt;RHTML&lt;/a&gt;)&lt;br/&gt;&lt;li&gt; Yes, we have Extract Method (&lt;a href="http://wiki.netbeans.org/RubyHints#section-RubyHints-ExtractMethod"&gt;Details&lt;/a&gt;)&lt;br/&gt;&lt;li&gt; Yes, we have Extract Constant (and we have Extract Variable and Extract Field as well, plus a number of other refactorings tied to the caret, listed in the RubyHints wiki page.)  (&lt;a href="http://wiki.netbeans.org/RubyHints#section-RubyHints-IntroduceFieldIntroduceConstantIntroduceVariable"&gt;Details&lt;/a&gt;)&lt;br/&gt;&lt;li&gt; Yes, we have RHTML code completion. (&lt;a href="http://wiki.netbeans.org/NewAndNoteWorthyMilestone10#section-NewAndNoteWorthyMilestone10-Ruby"&gt;Details&lt;/a&gt;)&lt;br/&gt;&lt;li&gt; (This isn't really for the feature comparison since we don't ship it by default, but a regular expression tester is available for NetBeans as well - see &lt;a href="http://www.netbeans.tv/screencasts/Regular-Expressions-Plugin-306/"&gt;this video&lt;/a&gt; for a tour.)&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;A green checkmark versus a red x seems a bit simplistic; not all feature implementations are equal. For code completion for example, there are factors such as how complete it is, how good the documentation markup is, parameter tooltips, whether completion helps you with hash keys, whether you get active record database field completion, and so on.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I'll forward this to their feedback alias so hopefully the page can be corrected. I'm trying to make the point to anyone else out there who is planning to make a competitive matrix: If you haven't actually checked, use a question mark rather than a red x for features from the competition.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Well, with that out of the way I don't want to rain on their parade; it's great that we have competition in the Ruby and Rails toolspace, and a 1.0 is a big accomplishment. Congratulations!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2915831343500403492?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2915831343500403492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/03/feature-comparisons.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2915831343500403492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2915831343500403492'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/03/feature-comparisons.html' title='Feature Comparisons'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2041646974777410671</id><published>2008-03-07T01:52:00.000-08:00</published><updated>2010-09-17T13:49:12.224-07:00</updated><title type='text'>Roundup Roundup</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;a href="http://joeracer.blogspot.com/2008/03/openspace-conferences.html"&gt;&lt;br/&gt;&lt;img border="0" align="right" src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtfknm9xI/AAAAAAAAA7w/DqM4Kyz7dCA/roundup4.jpg"&lt;br/&gt;style="margin-left: 5px; margin-bottom: 5px" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;It's Friday morning and I've spent whole the week in beautiful Crested Butte in the Rocky Mountains, Colorado.  Today is the last day of the&lt;br/&gt;&lt;a href="http://www.mindviewinc.com/Conferences/JavaPosseRoundup/"&gt;Java Posse Roundup 2008&lt;/a&gt;, the second time we're hosting this open space conference. It has been a blast!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The format is 4 hours of open-space discussions every morning, then skiing in the afternoon, and then we have "lightning talks" in the evenings - 5 minute quick presentations that are short enough that the speaker is forced to be concise so the presentations are always interesting.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Last night we also passed around the microphone and recorded conference impressions. Dick has already mixed it and uploaded it as the latest episode -&lt;br/&gt;&lt;a href="http://javaposse.com/index.php?post_id=314840"&gt;Episode 168&lt;/a&gt;.  We've obviously&lt;br/&gt;recorded all the technical sessions as well and those will be posted to the normal Java Posse podcast feed over the next couple of months.  I believe Joe and Dianne also recorded the lightning talks with a little video camera and those will be posted to our new&lt;br/&gt;&lt;a href="http://youtube.com/javaposse"&gt;YouTube channel&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Just like last year, a huge part of the success is due to the great set of participants. With so many different points of view and insights, every single session I've attended this week have been stimulating. While most of the participants came from the US, we even had 4-5 people attending from Europe! Stephan Janssen from the Belgian JUG has posted his pictures&lt;br/&gt;&lt;a href="http://picasaweb.google.com/JavaPolis.com/JavaPosse2008"&gt;here&lt;/a&gt; - the following picture is his. Notice the amount of snow we had!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrkyHM5DI/AAAAAAAAApw/2j7_Xbd60Vs/roundup.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The following photo (by Matt Zimmer) is from one of the lightning talks:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtfbvbmII/AAAAAAAAA7s/t6cbbb_IFI8/roundup3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Again notice the snow outside the windows. The lightning talks might be my favorite - 15-20 quick presentations back to back on subjects ranging from techy things like&lt;br/&gt;literate programming plugins for OpenOffice, Scala refactoring and JavaFX and Flex demos, Quantom Gravity and quantum cryptography, to Anime,&lt;br/&gt;to Stephan showing us the Java Polis artwork (which I've talked about&lt;br/&gt;&lt;a href="http://blogs.sun.com/tor/entry/spoona_sutra_another_java_conference"&gt;before&lt;/a&gt;), and not just the ones that made it -- the ones that were rejected as well!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Some other coverage from O'Reilly's Chris Adamson&lt;br/&gt;&lt;a href="http://weblogs.java.net/blog/editors/archives/2008/03/strange_town.html"&gt;here&lt;/a&gt;&lt;br/&gt;and &lt;a href="http://weblogs.java.net/blog/editors/archives/2008/03/absolute_beginn.html"&gt;here&lt;/a&gt;,&lt;br/&gt;Ido Green&lt;br/&gt;&lt;a href="http://idojava.blogspot.com/2008/03/javaposse-roundup-2008-day-1.html"&gt;here&lt;/a&gt;&lt;br/&gt;and&lt;br/&gt;&lt;a href="http://idojava.blogspot.com/2008/03/javaposse-roundup-2008-day-2.html"&gt;here&lt;/a&gt;,&lt;br/&gt;&lt;a href="http://joeracer.blogspot.com/2008/03/openspace-conferences.html"&gt;Joe Nuxoll&lt;/a&gt;, and&lt;br/&gt;&lt;a href="http://cmaki.blogspot.com/"&gt;Chris Maki&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2041646974777410671?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2041646974777410671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/03/roundup-roundup.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2041646974777410671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2041646974777410671'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/03/roundup-roundup.html' title='Roundup Roundup'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtfknm9xI/AAAAAAAAA7w/DqM4Kyz7dCA/s72-c/roundup4.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8352973928420200461</id><published>2008-02-01T04:59:00.000-08:00</published><updated>2010-09-17T13:49:12.198-07:00</updated><title type='text'>Why Your JavaOne Submission Was Rejected</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;img align="right" src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOvh7o9ECI/AAAAAAAABL0/u1DbzgFO8HE/javaone_logo.jpg" style="margin-left: 5px; margin-bottom:5 px" /&gt;&lt;br/&gt;JavaOne submission acceptance letters - and rejection letters - starting going out last night. This year, I was on the review committee for one of the tracks, so I got to see the proposals as well as the reasons for rejecting many of them. I thought I'd write these up, both to explain to the many submitters what might have gone wrong, as well as to give some tips for how to improve your chances next year. I'll probably link back to this post around the time submissions for JavaOne 2009 open up later this year.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;&lt;b&gt;Not Enough Details!&lt;/b&gt;  There were a number of submissions that sounded interesting, but didn't include enough details for us to judge whether there is enough technical meat behind the promises. If you're promising insights or "lessons learned", tell us what those lessons are, such that we can judge whether your presentation will be worthwhile (and in particular, whether to choose your submission over the handful of other similar submissions in the same topic area).&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt; &lt;b&gt;Wrong category!&lt;/b&gt;  I was on the Tools and Languages track. You wouldn't believe how many submissions to our track&lt;br/&gt;were not related to tools and languages. &lt;i&gt;Framework&lt;/i&gt;, &lt;i&gt;Practices&lt;/i&gt;, &lt;i&gt;Process&lt;/i&gt; or &lt;i&gt;Methodology&lt;/i&gt;: If any of these words are in your title, make sure you're really explaining how this is going to be tool related or language related.&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;So why can't we just reassign them to the right track? Well, each committee works independently, and if we were to suddenly have to accept "new" proposals that were miscategorized earlier that would increase the work a lot - we've already gone through and picked our top candidates for each subject area and so on.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;&lt;b&gt;Not of General Interest!&lt;/b&gt;  If you're submitting for a technical session, rather than a BOF, the talk will be offered in a room seating hundreds and sometimes thousands of attendees. The subject needs to be interesting to more than 20-50 people. If you're proposing a talk on a subject that is extremely narrow or a tool or language that doesn't have a lot of traction yet, you'll have better odds submitting the talk as a BOF.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt;&lt;b&gt;Crowded Topic!&lt;/b&gt;  Some topics are extremely popular. We received a large number of submissions for Groovy and Ruby for example. This means that if you submitted talks in one of these areas, even a perfect abstract wasn't enough and the choice for the committee was very difficult.&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;br&gt;&lt;br/&gt;&lt;li&gt;&lt;b&gt;Strong Competition!&lt;/b&gt;  At the end of the day, we only had about 20 technical sessions to hand out. We had more than ten times that number of submissions. We had roughly 10 talks for tools, and 10 talks for languages. Let's take languages - there's Groovy, Scala, Ruby, Jython, Java, ... as you can see there's not room for more than one or at most two talks in any one topic area.&lt;br&gt;&lt;br/&gt;The good news is that this hopefully means we'll have very high quality for the technical sessions!&lt;br/&gt;&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finally, work one &lt;b&gt;one&lt;/b&gt; strong submission rather than submitting 5-10 half-baked ones; just adding lots of abstracts does not help your odds given my points above about the low number of available slots; each submission has to be fantastic.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8352973928420200461?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8352973928420200461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/02/why-your-javaone-submission-was.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8352973928420200461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8352973928420200461'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/02/why-your-javaone-submission-was.html' title='Why Your JavaOne Submission Was Rejected'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOvh7o9ECI/AAAAAAAABL0/u1DbzgFO8HE/s72-c/javaone_logo.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2003026597812764059</id><published>2008-01-18T10:03:00.000-08:00</published><updated>2010-09-17T13:49:12.178-07:00</updated><title type='text'>Ruby Screenshot of the Week #27: Task List</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I've posted a number of blog entries showing NetBeans quickfixes for Ruby.  This helps you detect problems in code you happen to be working on, since it shows a yellow rather than green file status if there are warnings in the file. (The file status is shown on the right hand side of the editor pane, next to the vertical scrollbar).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Unfortunately, this doesn't give you an easy way to audit your code. If you want to find &lt;b&gt;all&lt;/b&gt; potential problems in your code, you'd have to open each and every file and look for yellow editor annotations... Not a tempting task for projects with hundreds of source files.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;No more. As of the latest NetBeans 6.1 development builds, the Ruby hints and quickfix functionality is integrated with the tasklist. All you need to do is open the tasklist window (Ctrl/Command-6 - the number, not F6, or find it in the Windows menu).  The tasklist will scan the entire project - or indeed all open projects - or even just the currently edited file. The tasklist scope can be chosen by the toggle buttons on the left hand side of the window.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOueBVRIbI/AAAAAAAABZ0/-c9V8_4ZMLA/tasklist1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;When you're working your way through the results, note that the tasklist responds to the Navigate | Next Error action (default bound to Ctrl/Command-Period). This will also warp the caret right to the editor location for the error, which means you can press Alt-Enter immediately to show the rule quickfixes, if any.  One such quickfix is to disable a particular hint type, so if you don't like a particular warning you can suppress it by just turning off the rule.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I personally don't like the Output window occupying the entire IDE width. Luckily configuring the window layout is very easy - just drag the windows around to where you want them.   In my preferred configuration, I  drag the output-windows into the editor bottom such that you end up with a layout like this:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;a href="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtgSz1yDI/AAAAAAAABYM/QWw6ttR__VY/tasklist-ide.jpg"&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtHJPdHpI/AAAAAAAAA4Q/3OQQue8jaIo/tasklist-ide-small.jpg" border="0" /&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Note also that the tasklist isn't only hooked up to the quickfixes; it's hooked up to the error functionality too and any parsing errors in your project will be listed there, at the top of the list (since errors have a higher priority than hints and warnings).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsEss53HI/AAAAAAAABVI/H91t3F69-Eg/tasklist2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Although you can disable hints as I've described above, you cannot turn off compiler warnings yet (such as the one about ambiguous parameters).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Anyway, I hope this will be helpful. Even if you're not a NetBeans user, perhaps you can try a quick audit of your source code with it. Get a 6.1 dev build &lt;a href="http://deadlock.netbeans.org/hudson/job/ruby/"&gt;here&lt;/a&gt;, open the IDE, choose "New Project", and then choose either a Ruby or a Rails project &lt;b&gt;with existing sources&lt;/b&gt;. Point to your sources, hit Finish, and then open the tasklist and let it churn away. Send bug reports and other feedback &lt;a href="http://wiki.netbeans.org/wiki/view/RubyFeedback"&gt;here&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2003026597812764059?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2003026597812764059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/01/ruby-screenshot-of-week-27-task-list.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2003026597812764059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2003026597812764059'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/01/ruby-screenshot-of-week-27-task-list.html' title='Ruby Screenshot of the Week #27: Task List'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOueBVRIbI/AAAAAAAABZ0/-c9V8_4ZMLA/s72-c/tasklist1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2731734638183917083</id><published>2008-01-05T04:36:00.000-08:00</published><updated>2010-09-17T13:49:12.159-07:00</updated><title type='text'>Ruby Screenshot of the Week #26: Ruby 1.9 Changes - hashes and case statements</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Ruby 1.9 has been &lt;a href="http://www.ruby-lang.org/en/news/2007/12/25/ruby-1-9-0-released/"&gt;released&lt;/a&gt;. It's a "development" version meaning that you wouldn't want to use it in production, but now is a good time to learn the new ways of doing things such that migrating to Ruby 2.0 will be easier.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Via &lt;a href="http://www.rubyinside.com/getting-code-ready-for-ruby-19-686.html"&gt;Ruby Inside&lt;/a&gt;, I read&lt;br/&gt;James Edward Gray's &lt;a href="http://blog.grayproductions.net/articles/getting_code_ready_for_ruby_19"&gt;recent blog entry&lt;/a&gt;&lt;br/&gt;detailing the work he did to update his library to 1.9 - and a number of people leaving comments are also pointing out language changes.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;One such change mentioned is case/when statements not allowing colon as a separator. (I don't see this in &lt;a href="http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9"&gt;Ruby Changes Wiki&lt;/a&gt; - does anyone have a source for this?). Seems like a a good candidate for a Ruby quickfix:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsbU70n1I/AAAAAAAAAxs/g7VozYsPjO0/when1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There are a couple of available fixes:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOty4bwEEI/AAAAAAAAA-c/il6Ky8jBdFM/when2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The first one is just replacing the colon with a &lt;code&gt;then&lt;/code&gt;:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuoHZ4daI/AAAAAAAABEk/tLNWtk07PDo/when4.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The second fix is instead putting the statement on a separate indented line:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOun9XerRI/AAAAAAAABEg/dipq_xJFQcE/when3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Another language change I found in &lt;a href="http://intertwingly.net/blog/2007/12/31/Porting-REXML-to-Ruby-1-9"&gt;Sam Ruby's post&lt;/a&gt; is that you cannot write hashes as lists anymore. Here's a quickfix for that - first the code, this is from webrick's &lt;code&gt;httpstatus&lt;/code&gt; class:&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOt402KsLI/AAAAAAAAA_E/cVYM4mcdPx4/hashes1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The quickfix is attached to the first list entry in the hash:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOr26njLkI/AAAAAAAAAsk/GKk-xLfXCCY/hashes2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;And previewing the fix shows the following proposed edit:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOs9P9wwlI/AAAAAAAAA2Y/0hCAwk0-QEo/hashes3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;As usual, the NetBeans Ruby forums can be accessed via Nabble &lt;a href="http://www.nabble.com/NetBeans-Ruby-f27019.html"&gt;here&lt;/a&gt; and Gmane newsreaders &lt;a href="http://dir.gmane.org/gmane.comp.java.netbeans.modules.ruby.devel"&gt;here&lt;/a&gt; (other feedback channels &lt;a href="http://wiki.netbeans.org/wiki/view/RubyFeedback"&gt;here&lt;/a&gt;).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2731734638183917083?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2731734638183917083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2008/01/ruby-screenshot-of-week-26-ruby-19.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2731734638183917083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2731734638183917083'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2008/01/ruby-screenshot-of-week-26-ruby-19.html' title='Ruby Screenshot of the Week #26: Ruby 1.9 Changes - hashes and case statements'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsbU70n1I/AAAAAAAAAxs/g7VozYsPjO0/s72-c/when1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6236870848754350063</id><published>2007-12-20T04:17:00.000-08:00</published><updated>2010-09-17T13:49:12.128-07:00</updated><title type='text'>Ruby Screenshot of the Week #25: require_gem</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;There have been a number of releases lately.  Rails 2.0 shipped. NetBeans 6.0 mostly supports it. There were a couple of changes, such as the scaffold generator's parameters changing meaning, and the new shorthand migration syntax, which affected NetBeans. I've committed changes to 6.1 to support these, so grab the latest if you're wanting complete Rails 2.0 support. However, note that we're in early 6.1 development so there's some big potentially destabilizing changes, such as a new platform manager which lets you choose per project ruby interpreters, configure separate gem repositories and so on. I'll post more about this when it's done. You don't need to upgrade if you're just wanting to use Rails 2.0 - nearly everything in NetBeans 6.0 works just fine.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;JRuby 1.0.3 also recently&lt;br/&gt;&lt;a href="http://archive.jruby.codehaus.org/user/21ef583e0712151535m6ea3730ch4ea9e72b1e9ed473@mail.gmail.com"&gt;shipped&lt;/a&gt;, and I've just updated NetBeans 6.1 to use it. JRuby 1.0.3 lets you run Rails 2.0 without needing to install the optional jruby-openssl gem.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I &lt;i&gt;just&lt;/i&gt; noticed that RubyGems 1.0 has&lt;br/&gt;&lt;a href="http://blog.segment7.net/articles/2007/12/20/rubygems-1-0-0"&gt;shipped&lt;/a&gt;. One of the changes in RubyGems is that the &lt;code&gt;require_gem&lt;/code&gt; method, which has been deprecated for a while, is now gone - so you &lt;i&gt;have&lt;/i&gt; to update your code appropriately. &lt;code&gt;require_gem&lt;/code&gt; was used by previous versions of Rails, so many &lt;code&gt;boot.rb&lt;/code&gt; files still reference it.&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I just added a checker for this:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtYV2W9CI/AAAAAAAAA6o/fwxnyLvKgP4/requiregem1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;It's not just a warning - it's a quickfix:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOs_M0_KwI/AAAAAAAAA2w/BaVq81gm2oc/requiregem2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The "Show More information" fix opens the browser on the release page for RubyGems 1.0 which briefly mentions the &lt;code&gt;require_gem&lt;/code&gt; removal. If anyone has a better URL to an official and mostly permanent page (e.g. preferably not somebody's blog) discussing this change, I'd appreciate the link.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Ruby 1.9 is getting closer. &lt;a href="http://headius.blogspot.com/"&gt;Charlie&lt;/a&gt; recently&lt;br/&gt;pointed out to me that they recently&lt;br/&gt;&lt;a href="http://groups.google.com/group/ruby-talk-google/msg/747820a230d688a1"&gt;decided&lt;/a&gt; that &lt;code&gt;retry&lt;/code&gt; statements will as of Ruby 1.9 only be allowed inside&lt;br/&gt;&lt;code&gt;rescue&lt;/code&gt; blocks. Thus, we now have a hint to look for problems of this sort.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOs_cG_cEI/AAAAAAAAA20/cfcSVnmA7kg/retry.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;If anyone has&lt;br/&gt;any ideas for other Ruby 1.9 migration issues, please&lt;br/&gt;&lt;a href="http://wiki.netbeans.org/wiki/view/RubyFeedback"&gt;let us know&lt;/a&gt;!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finally, let me end with a couple of links.  The "Off The Line" blog has posted&lt;br/&gt;&lt;a href="http://offtheline.net/2007/12/11/netbeans-6-0-cheat-sheet"&gt;cheatsheets&lt;/a&gt; for the NetBeans Ruby support, PDFs that summarize key shortcuts and other hints.  And Michael Slater, one of the early adopters of the NetBeans Ruby support, will be offering a &lt;a href="http://www.buildingwebapps.com/seminar"&gt;Rails Seminar&lt;/a&gt; in a couple of months, which is going to be using NetBeans. W00t!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;b&gt;Updated a few hours later&lt;/b&gt;:  &lt;a href="http://drnicwilliams.com/"&gt;Dr. Nic&lt;/a&gt; pointed out that &lt;code&gt;require_gem&lt;/code&gt; can't&lt;br/&gt;just be replaced by &lt;code&gt;gem&lt;/code&gt; and showed me how the code needs to be morphed. I've updated the&lt;br/&gt;quickfix to do The Right Thing now - thanks Dr. Nic!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOr9aQNPRI/AAAAAAAABUY/9-IBINjMbEY/requiregem3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6236870848754350063?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6236870848754350063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/12/ruby-screenshot-of-week-25-requiregem.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6236870848754350063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6236870848754350063'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/12/ruby-screenshot-of-week-25-requiregem.html' title='Ruby Screenshot of the Week #25: require_gem'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtYV2W9CI/AAAAAAAAA6o/fwxnyLvKgP4/s72-c/requiregem1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-9222542185848486065</id><published>2007-12-03T03:21:00.000-08:00</published><updated>2010-09-17T13:49:12.109-07:00</updated><title type='text'>Ruby Screenshot of the Week #24: Quick Fix Previews</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;a href="http://download.netbeans.org/netbeans/6.0/final/"&gt;&lt;br/&gt;&lt;img border="0" align="right" src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOwWpLazvI/AAAAAAAABR8/SByGcYFtTbM/110x32_dl2.jpg" style="margin-left: 5px; martin-right: 3px" /&gt;&lt;/a&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;br/&gt;First of all, NetBeans 6.0 (final) was released this morning. Go get it!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;So let's talk about 6.1 :)   I just updated the quickfix infrastructure such that we can automatically generate previews for how the hints will modify the source.  I've also added some new hints.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Let's start looking at the &lt;code&gt;user.rb&lt;/code&gt; file in the sample Depot application. If I place the caret inside one of the if blocks, a lightbulb appears:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrof0adDI/AAAAAAAAAqY/jrNsR-ReIH4/iffix1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;NetBeans offers to replace this if-block with one where the "if" is a statement modifier. This idea came from the excellent "Exploring Beautiful Languages"&lt;br/&gt;&lt;a href="http://langexplr.blogspot.com/2007/11/creating-netbeans-ruby-hints-with-scala_24.html"&gt;blog&lt;/a&gt;&lt;br/&gt;by Luis Diego Fallas, where he implements NetBeans Ruby hints -- in Scala!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOut-mgc2I/AAAAAAAABFU/qZS5UJU8PCM/iffix2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's the new preview functionality in action; instead of just applying the fix I invoke the Preview and get the following dialog which shows what the fix will do:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtlJ3Yj8I/AAAAAAAABYc/PQHcgDo2mBs/iffix3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Preview is particularly useful for larger source changes like &lt;a href="http://blogs.sun.com/tor/entry/extract_method_introduce_variable_introduce"&gt;Extract Method&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's another method from the same file:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtlWiN91I/AAAAAAAAA8s/TBbk7KaLI9o/iffix4.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Obviously, we can apply the same "convert to statement modifier" here, but look at the first suggested fix:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuubBU5qI/AAAAAAAABFY/3gWzNHo19qk/iffix5.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;NetBeans will convert "if negative condition" to "unless", and "unless negative condition" to "if" to make the code more readable. This was also shown by Luis in his blog entry. Here's the proposed fix:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOro9I-tgI/AAAAAAAABTw/uSuX8awLjCU/iffix6.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;and we can apply the other conditional cleanup as well to end up with a much simpler statement:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsIudE3II/AAAAAAAABVc/0upoq9K7ROI/iffix7.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There is one more recently added hint: Check for accidental assignments.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtzbW6qZI/AAAAAAAAA-g/dOLqrfzZwhA/accidental-assignment.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;At first I got a lot of false positives for this hint, since many Ruby programmers seem to like to intentionally assign in their conditions. But then I updated the rule to only complain if the variable being assigned to had already been seen in this scope, and that seems to do the trick perfectly. Newly assigned variables are intentional side effects of the assignment, and assignments to existing variables are likely bugs and should be avoided.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-9222542185848486065?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/9222542185848486065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/12/ruby-screenshot-of-week-24-quick-fix.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/9222542185848486065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/9222542185848486065'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/12/ruby-screenshot-of-week-24-quick-fix.html' title='Ruby Screenshot of the Week #24: Quick Fix Previews'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOwWpLazvI/AAAAAAAABR8/SByGcYFtTbM/s72-c/110x32_dl2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5493256881761943192</id><published>2007-11-21T08:14:00.000-08:00</published><updated>2010-09-17T13:49:12.080-07:00</updated><title type='text'>Quick Hi</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;No screenshot-of-the-week this time; I'm taking the week off since the kids are out of school for whole the week. I'm having a lot of fun!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Meanwhile, Cindy Church has been busy creating more demo videos on netbeans.tv:&lt;br/&gt;First, there's the classical&lt;br/&gt;&lt;a href="http://netbeans.tv/screencasts/Tor-Norbye-Uses-NetBeans-Ruby-Support-to-Create-a-Weblog-231/"&gt;&lt;br/&gt;weblog tutorial&lt;/a&gt;,&lt;br/&gt;and then there's showing how to&lt;br/&gt;&lt;a href="http://netbeans.tv/screencasts/Tor-Norbye-Writes-Unit-Tests-Using-the-NetBeans-Ruby-Support-246/"&gt;&lt;br/&gt;write and run unit tests&lt;/a&gt; in the IDE (where I'm incidentally also&lt;br/&gt;using the Dark Pastels color theme I've discussed previously on this blog).  We recently met and&lt;br/&gt;recorded more material, so there are more screencasts in the pipeline.  P.S.: Both screencasts are also available in higher definition as downloadable Quicktime files - see the "QuickTime format of this screencast" hyperlinks near the bottom.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Ok, back to vacation!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5493256881761943192?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5493256881761943192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/11/quick-hi.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5493256881761943192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5493256881761943192'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/11/quick-hi.html' title='Quick Hi'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-1002607925911477036</id><published>2007-11-12T04:15:00.000-08:00</published><updated>2010-09-17T13:49:12.049-07:00</updated><title type='text'>Ruby Screenshot of the Week #23: Extract Method and More Refactorings!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Last week I promised to catch up on my e-mail, but I had been missing feature work too much during the bug phase so I put it off for a week... to implement some more quickfix refactorings:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;Extract Method&lt;/li&gt;&lt;br/&gt;&lt;li&gt;Introduce Variable&lt;/li&gt;&lt;br/&gt;&lt;li&gt;Introduce Constant&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's how it works. Let's start with "Extract Method". You're looking at some code like this:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrhJf6FoI/AAAAAAAAApE/Zgahclx3JXM/extract_method1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;You decide there's too much going on in this method, and you want to pull the middle section into&lt;br/&gt;its own method. Select it, and notice the lightbulb which shows up on the left:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuhd8kseI/AAAAAAAABDk/zzt-dXIzY40/extract_method2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Press Alt-Enter to show the quick fix alternatives:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtqdGHADI/AAAAAAAAA9c/0trtvgCnCZ8/extract_method3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Select Extract Method, and the IDE will pop up a dialog asking you for the name of the new method you want to extract from the selected code fragment:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtqjcMiaI/AAAAAAAAA9g/-mobhixja-U/extract_method4.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Press OK (or just hit Enter), and the code will mutate into the following:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOuhiBLGkI/AAAAAAAABDo/1TVfGk53AMA/extract_method5.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There's a lot to notice here. First, there's a new method, and the active selection and caret is on a comment for that method (so you can just type to replace it). The new method is added below the one you extracted code from. And the most important part about this refactoring is that the IDE figures out which variables to pass in to the method, and which variables to pass back out:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;a, b and d are accessed from within the fragment, so they are passed in.&lt;br/&gt;&lt;li&gt;c is reassigned in the fragment without reading the previous value, so&lt;br/&gt;doesn't need to be passed in.&lt;br/&gt;&lt;li&gt; f and h are assigned locally inside the extracted fragment, but are not read&lt;br/&gt;outside of it, so do not need to be passed back out&lt;br/&gt;&lt;li&gt; g is assigned inside the fragment, and read later outside, so it is returned&lt;br/&gt;from the new method but not passed in&lt;br/&gt;&lt;li&gt; h is assigned inside the fragment, and is read later, but it is assigned&lt;br/&gt;before this read access so the value doesn't need to be passed back&lt;br/&gt;&lt;li&gt; i is also assigned inside the fragment, and -may- be read after the fragment,&lt;br/&gt;so it too is passed back out&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Ruby's multiple return values makes this refactoring much cleaner than in Java where you have&lt;br/&gt;to jump through some hoops to extract code fragments that modify multiple local variables...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Now let's take a look at Introduce Constant. Let's say you're looking at code like this (unlike the above contrived example from one of my unit tests for Extract Method, the following is from&lt;br/&gt;the standard Ruby Library's Date class):&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtMgJt6eI/AAAAAAAAA5I/4vfQ8H5b6bk/introduce1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There are a lot of "magic" numbers here. I honestly don't know what some of them are - but I recognize 365.25 as the number of days per year. Let's make that clearer - select that constant. (Tip - just move the caret to it and press Ctrl-Shift-Dot, which selects progressively larger logical elements around the caret). This produces the above lightbulb, so let's press Alt Enter again:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsrMJJMhI/AAAAAAAAA0E/7m9Ag0ahnsI/introduce2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I can now choose to either introduce a field, or a variable, or a constant. A constant is most natural here. (You won't be offered constant if the selected code fragment is not a constant expression.) So choose Introduce Constant:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsAygbi1I/AAAAAAAAAt8/PsfF_10N88k/introduce3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In the dialog asking for the name of the new constant, notice that it also detected some duplicates of this constant in the same class (3 of them to be exact), and asks if you want to replace all of them. I do - so I select the checkbox and press Ok:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsBUrQVFI/AAAAAAAAAuA/1nTOYW6_moI/introduce4.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The IDE has inserted a new constant at the top of the class, and has warped to it to let me edit a comment for the constant. I can also scroll down and see that the constants below were updated:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsrSZxznI/AAAAAAAAA0I/3rv800_k4Bo/introduce5.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The search for duplicates only looks for single constants at the moment, not more complicated expressions - it will do that soon. As always, please report any bugs you encounter. This is in the daily 6.1 trunk builds, although I've deliberately kept the code 6.0 compatible such that I can put this out on the update center for 6.0 as well.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-1002607925911477036?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/1002607925911477036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/11/ruby-screenshot-of-week-23-extract.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1002607925911477036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1002607925911477036'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/11/ruby-screenshot-of-week-23-extract.html' title='Ruby Screenshot of the Week #23: Extract Method and More Refactorings!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrhJf6FoI/AAAAAAAAApE/Zgahclx3JXM/s72-c/extract_method1.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2619974436333025137</id><published>2007-11-05T08:29:00.000-08:00</published><updated>2010-09-17T13:49:12.006-07:00</updated><title type='text'>Ruby Screenshot of the Week #23: Open Type and Open Method</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;img align="left" style="margin-right:5px" src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrT0qCi5I/AAAAAAAAAm8/THv183OojW4/beach_work.jpg" /&gt;&lt;br/&gt;&lt;img align="right" style="margin-left:5px" src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtBbNCVrI/AAAAAAAAA3M/0oHfIF9ExTg/unread-mail.jpg" /&gt;&lt;br/&gt;As of 20 minutes ago, NetBeans 6.0 entered high resistance, meaning that from this point on, only critical "showstopper" bugs will be addressed. We're spinning a release candidate in a a week, and after repeating that once or twice, NetBeans 6.0 will be done!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;It's been a long sprint getting to this point, including last minute bug fixing. We took the kids to the waterfront in Berkeley yesterday where they had a blast with bugs while I blasted bugs (see picture on the left).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;My e-mail inbox has been suffering the last couple of months.  On the right is a snapshot of the sidebar in my Mail tool - the numbers listed next to each folder is the number of &lt;i&gt;unread&lt;/i&gt; mail in that folder...  As you can see, the number of unread mails addressed directly to &lt;i&gt;me&lt;/i&gt; is a lot lower than in other categories (such as commit bug report mails) but even there I'm a bit behind.&lt;br/&gt;Now that 6.0 is winding down I can hopefully catch up on some of it - and apologies to those of you with e-mails in that pile. At least you know it's not a personal insult!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Let's get to some Ruby screenshots. One thing I fixed this week was some bugs around the "Open Type" dialog (Ctrl-O, or Command-O on the Mac).  I finally made "CamelCase" navigation work properly not just for classes but for module qualifiers as well, so if you for example want to open &lt;code&gt;ActionController::Base&lt;/code&gt;, just type &lt;code&gt;AC::B&lt;/code&gt;:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuNvr0NNI/AAAAAAAABBU/pWwApCt8k5k/actioncontrollerbase.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you had typed &lt;code&gt;A&lt;b&gt;V&lt;/b&gt;&lt;/code&gt; instead it would have shown &lt;code&gt;ActionView&lt;/code&gt; instead of &lt;code&gt;ActionController&lt;/code&gt;, and so on.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Another thing I fixed is the ability to specify a specific method in a class - just use "&lt;code&gt;#&lt;/code&gt;" as in rdoc to specify &lt;code&gt;Class#method&lt;/code&gt;, or omit the class to search across all classes. Let's jump to methods starting with &lt;code&gt;rend&lt;/code&gt; such as Rails' &lt;code&gt;render&lt;/code&gt;:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtn439EOI/AAAAAAAAA9A/7yWEcWEaGJM/render.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Or how about the to_xml methods - but only in modules that start with "A":&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOuLyj4WOI/AAAAAAAABBM/ARjy7hyLhb0/toxml.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;You can also use wildcards. Here's all methods that contain &lt;code&gt;load&lt;/code&gt; somewhere in the name:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOt6vtjacI/AAAAAAAAA_Q/HJeLeKf7X6A/load.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. There are still some bugs around being able to use camel case and regexps when filtering methods - I'll address those in the first update release.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2619974436333025137?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2619974436333025137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/11/ruby-screenshot-of-week-23-open-type.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2619974436333025137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2619974436333025137'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/11/ruby-screenshot-of-week-23-open-type.html' title='Ruby Screenshot of the Week #23: Open Type and Open Method'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrT0qCi5I/AAAAAAAAAm8/THv183OojW4/s72-c/beach_work.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-1762568996192431580</id><published>2007-10-26T10:16:00.000-07:00</published><updated>2010-09-17T13:49:11.985-07:00</updated><title type='text'>Ruby Screenshot of the Week #22: Go To Specific Location</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;It's bugfixing all the way these days - I apologize for being behind on my e-mail. We're freezing 6.0 pretty soon (in eight days), so I'd really like to get some help testing the last minute fixes. More about that shortly. But first, some screenshots.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;One longstanding bug we've had is that our "Go To Declaration" (holding the Ctrl or Command key down while clicking on classes or methods) would jump to a different place than you were intending. With Ruby's open classes, there are many definitions for a class, so if you want to jump to say the &lt;code&gt;File&lt;/code&gt; class, did you want the one in &lt;code&gt;ftools.rb&lt;/code&gt;? Or perhaps in &lt;code&gt;pp.rb&lt;/code&gt;?  We have some heuristics which pick which reference is "best" - it involves looking at things like whether each declaration has documentation, whether it's directly loaded by your file using &lt;code&gt;require&lt;/code&gt; statements, and so on. But this can never be perfect. So, to solve this problem, Go To Declaration clicks (or Ctrl/Command-B) will now pop up a dialog when there are multiple possibilities. As before, one item is NetBeans' best guess - and it's shown first and in bold. All you have to do is press Enter or click on it to jump as before. But other matches are shown too, in a sorted order.  First are the documented entries, and at the very end, &lt;code&gt;:nodoc:&lt;/code&gt; entries (shown with&lt;br/&gt;a strikethrough font effect).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's how this look if you for example try to jump to &lt;code&gt;TestCase&lt;/code&gt;:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrhp2mqLI/AAAAAAAAApM/biq7UewaBHI/goto-decl.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you don't like this behavior, you can always turn it off by running NetBeans with&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;-J-Dgsf.&lt;b&gt;im_feeling_lucky&lt;/b&gt;=true&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This was added just this week. Something related which has been there for a while is documentation&lt;br/&gt;tooltips. If you're holding the hyperlink-modifier key (Ctrl/Command) and hover over methods and&lt;br/&gt;classes, it will display a tooltip with the type of the symbol and its documentation. For example,&lt;br/&gt;in a Rails controller test, here's what I got:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrg_K1TII/AAAAAAAAApA/wRCwQxmQgfI/doc-tooltip.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I just (a few hours ago) checked in a bunch of changes to clean up how NetBeans handles the gem load&lt;br/&gt;path. It should now finally handle &lt;code&gt;$GEM_HOME&lt;/code&gt; properly, as well as &lt;code&gt;vendor&lt;/code&gt; gems and in particular, &lt;code&gt;vendor/rails&lt;/code&gt;. Thus, the active record completion I showed last week&lt;br/&gt;should now work with Rails 2 and edgerails. NetBeans should properly pick gems both from the current project as well as the current gem root (based on which gem version is higher). However, all of these changes were a bit involved... So I would &lt;i&gt;really&lt;/i&gt; appreciate if people could grab the current bits (build 4866 or later from &lt;a href="http://deadlock.netbeans.org/hudson/job/ruby/"&gt;http://deadlock.netbeans.org/hudson/job/ruby/&lt;/a&gt;) and take it for a quick spin. Make sure that code completion etc. picks up your gems as before. You may have to wipe out the cached indices (&lt;i&gt;userdir&lt;/i&gt;/var/cache/) if you have any problems. Don't worry, it's always safe to wipe out stuff inside &lt;code&gt;var/cache&lt;/code&gt;.)  If there any problems, please let me know now since we're about to freeze for 6.0.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S.  Beta 2 was released this week - &lt;a href="http://download.netbeans.org/netbeans/6.0/beta2/"&gt;download&lt;/a&gt;,&lt;br/&gt;&lt;a href="http://wiki.netbeans.org/wiki/view/NewAndNoteWorthyBeta2"&gt;New And Noteworthy&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-1762568996192431580?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/1762568996192431580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/10/ruby-screenshot-of-week-22-go-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1762568996192431580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1762568996192431580'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/10/ruby-screenshot-of-week-22-go-to.html' title='Ruby Screenshot of the Week #22: Go To Specific Location'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrhp2mqLI/AAAAAAAAApM/biq7UewaBHI/s72-c/goto-decl.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-4263608371149164704</id><published>2007-10-16T09:42:00.000-07:00</published><updated>2010-09-17T13:49:11.964-07:00</updated><title type='text'>Ruby Screenshot of the Week #21: ActiveRecord Completion</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Let's jump to the good stuff right away:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsmt16xGI/AAAAAAAAAzY/KDGYruEuROY/activerecord6.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Okay, now let's motivate it. Let's say you're writing a migration:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsmIqxyuI/AAAAAAAAAzU/qbVJiGJqMg0/activerecord1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Hmm, what's the second parameter to the &lt;code&gt;column&lt;/code&gt; method again?&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtIyZKgSI/AAAAAAAAA4c/1_QCRu7jFs0/activerecord2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Ah yes, the column type. Notice how the RDoc for the method call surrounding&lt;br/&gt;the completion point is shown above - and perhaps more importantly, the symbol alternatives for&lt;br/&gt;the current parameter are also&lt;br/&gt;proposed below. Let's choose one.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOuFZQZ30I/AAAAAAAABAg/SHvv49GIRgU/activerecord3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Ah yes, the third parameter - the options. Again the documentation is&lt;br/&gt;shown above (I've cropped it in this image) where you can read the details -&lt;br/&gt;but many of the alternatives are listed here.  Let's choose the &lt;code&gt;:null&lt;/code&gt; hash key.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOuGCanx6I/AAAAAAAABAk/-W7ZfHp_D4w/activerecord4.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The parameter completion support I've shown here isn't specific to ActiveRecord. Let's say you're in&lt;br/&gt;an ERB file and calling into say the NumberHelpers:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtJEw5Z7I/AAAAAAAAA4g/peWM7mQBfcg/activerecord5.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Anyway, we're done editing the migration. Now let's jump over to a controller file and reference the &lt;code&gt;Product&lt;/code&gt; model that is using the database table for this migration. Let's ask for completion on the &lt;code&gt;@product&lt;/code&gt; field that was just populated with a Product object:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsmt16xGI/AAAAAAAAAzY/KDGYruEuROY/activerecord6.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The icon should make it really clear that these attributes are coming from the database as opposed to some dedicated attribute code in the Product implementation. Notice how NetBeans also shows the &lt;i&gt;type&lt;/i&gt; for each of the columns. Completion also works for the dynamic finders that Rails generates. Let's ask for completion on &lt;code&gt;find_by&lt;/code&gt; (this also works for &lt;code&gt;find_all_by&lt;/code&gt;):&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOr-ejlVbI/AAAAAAAAAtk/dSjvLfgfYAY/activerecord7.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;NetBeans offers code completion for models by examining the migration files. Let's go create another one. Here's&lt;br/&gt;completion again, this time completing on the table name argument to &lt;code&gt;rename_column&lt;/code&gt;:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsm7ckNHI/AAAAAAAAAzc/bw60viOJGLU/activerecord8.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Let's say we rename the &lt;code&gt;description&lt;/code&gt; column to &lt;code&gt;desc&lt;/code&gt;:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsE9KQoeI/AAAAAAAAAus/5Q70iTdIMRM/activerecord9.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If we now invoke code completion in the controller again, notice how the &lt;code&gt;Product&lt;/code&gt; attributes correctly&lt;br/&gt;reflect the result of combining the migrations:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuOE2gatI/AAAAAAAABBY/-Z7tlsS7QzI/activerecord10.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;NetBeans will also use the &lt;code&gt;schema.rb&lt;/code&gt; file that Rails will automatically generate if you run the &lt;code&gt;db:schema:dump&lt;/code&gt; Rake target. This is useful if your migrations are doing creative things that NetBeans can't figure out, or if you're renaming tables (which NetBeans doesn't model right in this release.)  With a schema dump file, not only does NetBeans have to do less work to figure out your migrations, its format is predictable such that the code completion should be completely accurate.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. This doesn't work right if you freeze Rails into your project; you need to be using Rails via Rubygems. I'll fix that soonish.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-4263608371149164704?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/4263608371149164704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/10/ruby-screenshot-of-week-21-activerecord.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4263608371149164704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4263608371149164704'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/10/ruby-screenshot-of-week-21-activerecord.html' title='Ruby Screenshot of the Week #21: ActiveRecord Completion'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsmt16xGI/AAAAAAAAAzY/KDGYruEuROY/s72-c/activerecord6.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-584009670130209602</id><published>2007-10-08T07:05:00.000-07:00</published><updated>2010-09-17T13:49:11.948-07:00</updated><title type='text'>Ruby Screenshot of the Week #20: Purdy Colors!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;A lot of people have asked for a "dark color theme" for NetBeans, possibly because there are several attractive dark color schemes for TextMate, a favorite editor among many Ruby developers.  &lt;a href="http://nullcreations.net/"&gt;Jerrett Taylor&lt;/a&gt; has designed and contributed a great dark color theme for NetBeans, "Dark Pastels". I've wrapped it up as a plugin. As of today, it's prebundled with the continuous builds on &lt;a href="http://deadlock.netbeans.org/hudson/job/ruby/"&gt;http://deadlock.netbeans.org/hudson/job/ruby/&lt;/a&gt;, but for other versions such as beta1 and the upcoming beta2, you can download the plugin from &lt;a href="http://mediacast.sun.com/share/tor/org-netbeans-modules-ruby-themes.nbm"&gt;here&lt;/a&gt; and install via Tools | Plugins (go to the Downloaded tab). It should hopefully also appear on the Auto Update center pretty soon.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;To switch to this color theme after installing the plugin, open the options dialog, go to "Fonts and Colors" and choose the "Dark Pastels" color theme.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Let's get on to the screenshots! Here's a Ruby file:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsy5i8UEI/AAAAAAAAA1M/EZrUSRKKBdE/dark-pastels-ruby.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;...and here's an RHTML file:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOs6GcLp2I/AAAAAAAAA2M/9ybFoO8ZBl8/dark-pastels-rhtml.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Note that the plugin only replaces the editor colors. Other windows such as the navigator and project views keep the general look and feel of the whole application, so you can either slide these off to the side, or install a custom look and feel with colors more to your liking.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's what the plugin looks like in the Plugin Manager. As you can see I've named it "Extra Themes" such that it can hold several optional themes, so if you've got a color scheme to share, please do!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOuIyTllPI/AAAAAAAABZk/tvE6rbrMQNU/dark-pastels-plugin.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;A huge thanks to Jerrett!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. The theme the font to "Monaco", which is available on the Mac. If you're on a different platform you may want to go a tweak the default font to one that looks good on your system.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-584009670130209602?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/584009670130209602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/10/ruby-screenshot-of-week-20-purdy-colors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/584009670130209602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/584009670130209602'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/10/ruby-screenshot-of-week-20-purdy-colors.html' title='Ruby Screenshot of the Week #20: Purdy Colors!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOsy5i8UEI/AAAAAAAAA1M/EZrUSRKKBdE/s72-c/dark-pastels-ruby.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6062127285683194992</id><published>2007-10-02T02:09:00.000-07:00</published><updated>2010-09-17T13:49:11.939-07:00</updated><title type='text'>Disable Crashing...</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;If you're on OSX, and you've experienced NetBeans 6.0 beta crashing on you, read on...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Right before beta1, we tweaked some of the Java VM startup flags NetBeans uses. In particular, we switched to the "Concurrent Mark Sweep" (CMS) garbage collector, which has a nice performance profile for IDE usage, since collection happens mostly in parallel so you don't get noticeable pauses.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Unfortunately, it turns out that these flags cause a lot of problems on OSX. In particular, they cause frequent virtual machine crashes!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Knowing this, for beta2 we've turned off those flags when running NetBeans on OSX. But that doesn't help you if you're trying to run beta1... Luckily, it's easy to fix it yourself, since the VM parameters are specified in a text configuration file.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;First, open the &lt;code&gt;netbeans.conf&lt;/code&gt; file. On my Mac, I installed NetBeans in Applications under NetBeans, so the file is&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;/Applications/NetBeans/NetBeans\ 6.0\ Beta\ 1.app/Contents/Resources/NetBeans/etc/netbeans.conf&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;The file contains this:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;# Options used by NetBeans launcher by default, can be overridden by explicit&lt;br/&gt;# command line switches:&lt;br/&gt;netbeans_default_options="-J-client -J-Xms32m -J-XX:PermSize=32m -J-XX:MaxPermSize=200m&lt;br/&gt;-J-Dapple.laf.useScreenMenuBar=true &lt;b&gt;-J-XX:+UseConcMarkSweepGC -J-XX:+CMSClassUnloadingEnabled&lt;br/&gt;-J-XX:+CMSPermGenSweepingEnabled&lt;/b&gt;"&lt;br/&gt;# (Note that a default -Xmx is selected for you automatically.)&lt;br/&gt;&lt;br/&gt;# For JVMs which does not support Concurrent Mark &amp; Sweep garbage collection&lt;br/&gt;# algorithm remove "-J-XX:+UseConcMarkSweepGC -J-XX:+CMSClassUnloadingEnabled&lt;br/&gt;# -J-XX:+CMSPermGenSweepingEnabled" part of options&lt;br/&gt;# (see http://wiki.netbeans.org/wiki/view/FaqGCPauses)&lt;br/&gt;&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Remove the bold section above; in other words, remove these 3 flags:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;-J-XX:+UseConcMarkSweepGC -J-XX:+CMSClassUnloadingEnabled -J-XX:+CMSPermGenSweepingEnabled&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;Now when you restart the IDE should behave better.&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6062127285683194992?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6062127285683194992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/10/disable-crashing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6062127285683194992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6062127285683194992'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/10/disable-crashing.html' title='Disable Crashing...'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-2510805887285463435</id><published>2007-09-26T06:53:00.000-07:00</published><updated>2010-09-17T13:49:11.929-07:00</updated><title type='text'>Ruby Screenshot of the Week #19: Comment Reformatting</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I've been working on beefing up the RHTML support this week, but since I'm not done yet I'll talk about that next week. Instead I'll show you a feature that's actually in beta1, but you may not be aware of.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Let's say you have this code:&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrhRX57BI/AAAAAAAAApI/77xDwaGoRK8/formatting-before.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Have you ever wondered what the vertical faint red line on the right hand side of the editor is? It's the soft text limit line. It's telling you that beyond this line, you're going over 80 characters. There's nothing magical about 80 - you can configure it to something else, as I have done here, but more on that later.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Anyway, this comment is obviously not pretty since I've pasted in some text with long lines. This happens to my comments all the time after I edit them, removing a sentence here or adding another there.&lt;br/&gt;But let's get to the point. Place the caret somewhere in the comment (as I have done). Now press Ctrl-Shift-P (on OSX, Command-Shift-P). Voila - the paragraph gets reformatted:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOr1Cv2oqI/AAAAAAAAAsQ/7tS4gSnDEQg/formatting-after.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Notice that the IDE understands RDoc conventions. It has left preformatted code alone, and has recognized the numbered list and has formatted it appropriately. (There's also a hidden mode you can enable such that it reflows the current paragraph automatically as you edit comments.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;You can configure the text limit line in the general editor options - it's called "right margin":&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrn9EXS_I/AAAAAAAAAqQ/Kw7a4kS9d2g/formatting-options1.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;One other interesting thing you can do with comments is view how RDoc will format them. Just use the normal "show documentation" gesture (Ctrl-Shift-Space, or Command-Shift-Space, to show the documentation for the symbol under the caret). This normally shows the documentation for a class or method that your caret is pointing to, but inside a comment, this will show the comment itself rendered rdocily:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtppPBDHI/AAAAAAAAA9Q/2fYfQlGrz3M/comment-docs.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;That can be handy to check your docs as you're editing them (although this wasn't working properly in beta1, so get a daily build). The above example doesn't contain a lot of interesting rdoc markup, but let's say you brought this up on for example the form_tag method, you'd see something like this:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrzgpjZAI/AAAAAAAAAr8/fOlI1_VQ7Ww/comment-docs2.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Notice how some of the code fragments are syntax highlighted as well - this is taking advantage of the enhanced rdoc rendering I've &lt;a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week11"&gt;described earlier&lt;/a&gt;.  And when tweaking your documentation, don't forget &lt;a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week16"&gt;spell checking&lt;/a&gt;!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finally, the above comment screenshots are a bit boring. Inline use of rdoc tags are also syntax highlighted. We were just discussing the meanings of the various colors on&lt;br/&gt;&lt;a href="http://www.nabble.com/NetBeans-Ruby---Dev-f27020.html"&gt;dev@ruby.netbeans.org&lt;/a&gt;, and the following screenshot shows the meanings of the various syntactic constructs. Notice how rdoc tokens like &lt;code&gt;:nodoc:&lt;/code&gt; and words surrounded by underscores are highlighted:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtivgV4BI/AAAAAAAAA8Q/gTLZQG2vaV4/colorchart.jpg"&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-2510805887285463435?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/2510805887285463435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/09/ruby-screenshot-of-week-19-comment.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2510805887285463435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/2510805887285463435'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/09/ruby-screenshot-of-week-19-comment.html' title='Ruby Screenshot of the Week #19: Comment Reformatting'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrhRX57BI/AAAAAAAAApI/77xDwaGoRK8/s72-c/formatting-before.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-3698473004662720365</id><published>2007-09-20T06:50:00.000-07:00</published><updated>2010-09-17T13:49:11.916-07:00</updated><title type='text'>Ruby Screenshot of the Week #18: Errors and Snippets</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Tim Bray &lt;a href="http://www.tbray.org/ongoing/When/200x/2007/09/20/Error-Message"&gt;just wrote&lt;/a&gt; about error messages and their occasional difficulty for users. I ran into the same issue myself a couple of weeks ago when somebody filed a bug that NetBeans didn't correctly handle Ruby documentation markers. When looking at the user's source, I realized the error was right in the user's source file - but the parser message hadn't been particularly helpful: Syntax error, unexpected =.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This of course seems like an area where the IDE can help. So, as of the latest builds, there are some error rule handlers (in the experimental hints plugin) to help with this. Suppose you try to add in a documentation block like this:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOthFRo5YI/AAAAAAAAA8A/9maXH_154ag/wrong-documentation.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The lightbulb on top of the stop sign tells you there's an associated suggestion. Press Alt-Enter to see the error message and suggested fix:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtW7aKTcI/AAAAAAAAA6c/qCeZ09DNlFo/move-documentation.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Applying the fix will obviously correct the indentation of &lt;code&gt;=begin&lt;/code&gt; and &lt;code&gt;=end&lt;/code&gt;. Here's another example - opening a file with ambiguous parameters:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtwVNjGzI/AAAAAAAAA-I/lPNEFcfaGAI/parenthesize.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I would really like your ideas on other common error patterns I can detect and better yet, fix.  (See&lt;br/&gt;&lt;a href="http://wiki.netbeans.org/wiki/view/RubyFeedback"&gt;RubyFeedback&lt;/a&gt; or leave comments here.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;While we're on the topic of quick fixes, the experimental hints also include some new suggestions for converting between brace blocks and do/end blocks. If you place the caret within the first line of a do-block or a {}-block, a little lightbulb will appear in the left margin. If you press Alt-Enter, you'll see some applicable fixes:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrndEGY-I/AAAAAAAAAqM/LdwVK6dbX0o/expand-block.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The exact list of choices shown obviously depends on the block. If you do this from a do/end block, the conversion goes in the opposite direction. And if you're looking at a multi-line block rather than a single line block, it will offer to collapse the block into a single line rather than expanding it as shown here. (It only offers this if it can fit the statements on a single line within the right-hand side margin, as shown by the faint red line in the editor.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Unsurprisingly, applying the first fix gives us this source code for the block:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOuRR0u1_I/AAAAAAAABB0/_PzLfATzVzM/expanded-block.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;(This operation will sometimes also insert parentheses around the previous argument list when necessary, since {}-blocks have different precedence than do-end blocks.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Finally, I just fixed some bugs in the code template handling code. If you invoke code completion you should now see the possible code snippets that match your input - along with their tab trigger names on the right and the full code template in the documentation popup:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrgUDs1GI/AAAAAAAAAo8/-z_mMcuOaSY/codetemplate-completion.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;That's it for now. Don't forget that NetBeans 6.0 Beta 1 was just &lt;a href="http://bits.nbextras.org/download/6.0/milestones/latest/"&gt;released&lt;/a&gt;. The&lt;br/&gt;&lt;a href="http://wiki.netbeans.info/wiki/view/NewAndNoteWorthyBeta1"&gt;New And Noteworthy&lt;/a&gt; document has the rundown on the new features included since Milestone 10. (Most of the things I've described in this blog entry were checked in after the beta cut off but beta is more stable for regular use.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. Rails creator David Heinemeier Hansson had some &lt;a href="http://www.loudthinking.com/posts/11-sun-surprises-at-railsconf-europe-2007"&gt;nice things to say&lt;/a&gt; about Sun's Ruby and Rails efforts. There's no evil plan, I promise!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-3698473004662720365?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/3698473004662720365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/09/ruby-screenshot-of-week-18-errors-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3698473004662720365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/3698473004662720365'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/09/ruby-screenshot-of-week-18-errors-and.html' title='Ruby Screenshot of the Week #18: Errors and Snippets'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOthFRo5YI/AAAAAAAAA8A/9maXH_154ag/s72-c/wrong-documentation.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-4357049410906137676</id><published>2007-09-07T09:34:00.000-07:00</published><updated>2010-09-17T13:49:11.908-07:00</updated><title type='text'>Hello World!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;The "Java Posse Hello World Tour 2007" is about to kick off :-) Carl, Dick and I are heading to Norway next week for &lt;a href="http://www4.java.no/web/show.do?page=153;252"&gt;JavaZone&lt;/a&gt;, where we'll do a live session as well as hopefully get some great interviews and just have fun.  I'm also doing a talk on &lt;a href="http://www4.java.no/web/show.do?page=92&amp;articleid=5532"&gt;Ruby Tooling&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Joe can't make it - he works on the web store at Apple, and apparently they're busy selling &lt;a href="http://www.apple.com/ipodtouch/guidedtour/"&gt;stuff&lt;/a&gt;!  We're also going to &lt;a href="http://www.javapolis.com/confluence/display/JP07/Home"&gt;JavaPolis&lt;/a&gt; in Belgium in December. I'm not sure if I'll be able to go yet, but the other three guys are confirmed.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If any of you will be at JavaZone next week, please say hi!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's our world tour poster, courtesy of &lt;a href="http://geekandpoke.typepad.com/geekandpoke/2007/07/the-java-posse-.html"&gt;Oliver Widder&lt;/a&gt;:&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;a href="http://geekandpoke.typepad.com/.shared/image.html?/photos/uncategorized/2007/07/30/wt2.jpg"&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOriJNd5hI/AAAAAAAAApQ/fDN7o0cBbGw/helloworldtour.jpg" border="0"&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-4357049410906137676?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/4357049410906137676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/09/hello-world.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4357049410906137676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4357049410906137676'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/09/hello-world.html' title='Hello World!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOriJNd5hI/AAAAAAAAApQ/fDN7o0cBbGw/s72-c/helloworldtour.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-4024948911541310661</id><published>2007-09-07T03:22:00.000-07:00</published><updated>2010-09-17T13:49:11.896-07:00</updated><title type='text'>New Demo Screencasts Available</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOu31dl25I/AAAAAAAABGY/fpWKLYwDqeQ/netbeans_tv-200x62.jpg" align="right" style="margin-left: 5px" /&gt;&lt;br/&gt;&lt;a href="http://netbeans.tv/"&gt;NetBeans.tv&lt;/a&gt; was recently launched. It's a community site where you can view, upload and rate videos related to NetBeans, such as demos and tutorials, interviews, and so on.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Cindy Church has recorded and edited together three demos where I show NetBeans and the Ruby support.&lt;br/&gt;&lt;ol&gt;&lt;br/&gt;&lt;br/&gt;&lt;li&gt;&lt;br/&gt;&lt;a href="http://mediacast.sun.com/share/cindo/Tor-Norbye-RubyJavaScreencast%20.mov"&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOt8XIHvaI/AAAAAAAAA_c/LenEBXzQsiw/netbeanstv-small.jpg" border="0" align="right" style="margin-left: 5px" /&gt;&lt;/a&gt;&lt;br/&gt;&lt;a href="http://netbeans.tv/interviews/Tor-Norbye-mixes-Ruby-and-Java-development-using-NetBeans-151/&lt;br/&gt;"&gt;The JavaOne Demo&lt;/a&gt; (9 minutes). This is roughly the same outline I followed for the demo in James Gosling's keynote at JavaOne this year. It's a demo which shows both Java and Ruby editing capabilities as I create some JPA entity classes in Java, and then proceed to access these from a Rails application using JRuby.&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; You can download a higher resolution version of the video &lt;a href="http://mediacast.sun.com/share/cindo/Tor-Norbye-RubyJavaScreencast%20.mov"&gt;here&lt;/a&gt; (120Mb).&lt;br/&gt;&lt;li&gt; The demo script is available &lt;a href="http://wiki.netbeans.org/wiki/view/RubyJavaOne2007Demo"&gt;here&lt;/a&gt;.&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;li&gt; &lt;a href="http://netbeans.tv/technologies/Tor-Norbye-uses-NetBeans-Ruby-Editor-Code-Completion-167/"&gt;Code completion&lt;/a&gt; (2 minutes). In this brief demo I show some simple code completion scenarios for Ruby. You can also download a &lt;a href="http://mediacast.sun.com/share/cindo/TorNorbye-RubyCodeCompletion.mov"&gt;higher resolution version&lt;/a&gt; (27 Mb) of the video.  I was winging this demo (without a script) so I didn't spend much time on the various types of code completion, but take a look at &lt;a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week9"&gt;this blog entry&lt;/a&gt; where I get into a bit more detail. Also note that the code completion documentation has some additional smarts to it above what rdoc gives you, &lt;a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week11"&gt;described here&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;li&gt; &lt;a href="http://netbeans.tv/technologies/Tor-Norbye-uses-hints-and-quick-fixes-in-NetBeans-Ruby-Editor-168/"&gt;&lt;br/&gt;Quick Fixes&lt;/a&gt; (3&amp;frac12; minutes).  In this demo I show some of the quick fixes available for Ruby. Some additional hints were added after the demos were recorded - take a look at&lt;br/&gt;&lt;a href="http://wiki.netbeans.org/wiki/view/RubyHints"&gt;this wiki page&lt;/a&gt; for an up to date list.&lt;br/&gt;You can also download a &lt;a href="http://mediacast.sun.com/share/cindo/TorNorbye-RubyHints.mov"&gt;higher resolution version&lt;/a&gt; (44 Mb) of the video.&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Seeing myself on the video screen makes me super happy that &lt;a href="http://www.javaposse.com/"&gt;Java Posse&lt;/a&gt; is an audio-only podcast!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;A big thanks to Cindy Church and Mike Quillman who did all the hard work on these demos.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-4024948911541310661?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/4024948911541310661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/09/new-demo-screencasts-available.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4024948911541310661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/4024948911541310661'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/09/new-demo-screencasts-available.html' title='New Demo Screencasts Available'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOu31dl25I/AAAAAAAABGY/fpWKLYwDqeQ/s72-c/netbeans_tv-200x62.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-725651772607308415</id><published>2007-08-26T08:26:00.000-07:00</published><updated>2010-09-17T13:49:11.878-07:00</updated><title type='text'>Ruby Screnshot of the Weeek #17: Spelll Checkinng</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;One of my &lt;a href="http://blogs.sun.com/tor/entry/netbeans_plugins_i_use_part2"&gt;favorite&lt;/a&gt; plugins for NetBeans 5.5 was &lt;a href="http://blogs.sun.com/jlahoda/entry/spellchecker_for_netbeans_ide"&gt;Jan Lahoda's spell checker&lt;/a&gt;.&lt;br/&gt;It turns out Jan has updated it to work with NetBeans 6.0, so I wrote some bindings for it to work with Ruby as well.&lt;br/&gt;Briefly, it highlights spelling errors in comments and documentation (=begin/=end) sections. This also works in&lt;br/&gt;embedded Ruby code in RHTML files, and in RHTML files it also spell checks the text content. Ok, screenshots:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtJRUZwsI/AAAAAAAAA4k/yXoRH2YX9Sc/base_typos.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The above is the documentation for Rails' &lt;code&gt;url_for&lt;/code&gt; method. As you can see there are a couple of typos.&lt;br/&gt;If you place the caret on one of the words a lightbulb will appear in the left side gutter; press Alt-Enter&lt;br/&gt;to see the possible fixes:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOtQ0ugZEI/AAAAAAAAA5s/u4EGlRZt1Z8/base_typos2.jpg" /&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As you can see, you can very easily add known words that aren't in the default dictionary to your own private list.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's an RHTML/ERB file:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOr9v43wsI/AAAAAAAAAtc/dD0eWYckU-w/rhtml_typos.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Since this is a file in one of my own projects, NetBeans offers to add this word to a project-specific dictionary. This wasn't available for the above Rails source file since it's in a library outside of my projects.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOs3CxGUzI/AAAAAAAAA10/ySWTRodVp4s/rhtml_typos2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The Ruby spell checker currently skips words in comments that look like Ruby identifiers, such as&lt;br/&gt;CamelCase words, method_name words, and :symbols. Single-character words are also skipped. Finally, it skips&lt;br/&gt;rdoc preformatted text (indented comment content) since that typically contains code fragments which contain&lt;br/&gt;lots of unrecognized words. It might be an interesting improvement to try to help with typos in actual&lt;br/&gt;class and method names, such as a "Controler", but I've gotta figure out a way to avoid generating tons of false positives here (what's a Scanf? :-)&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I've uploaded a version which should work with NetBeans 6.0 &lt;a href="http://mediacast.sun.com/share/tor/spellchecker-nbms.zip"&gt;here&lt;/a&gt;. Unzip it, then go to the Tools | Plugin Manager, open the "Downloaded" tab and install the individual nbm files. (You may have to restart the IDE.) The zip includes an English dictionary. This is the dictionary from ispell (unzip the dictionary.nbm file and you'll see it). You can add other languages in the Options dialog; these should be &lt;a href="http://ficus-www.cs.ucla.edu/geoff/ispell-dictionaries.html"&gt;ispell dictionaries&lt;/a&gt;. You can also change the text locale in the Options dialog; when I opened some files in the RSpec distribution it immediately complained about the British spelling "behaviour" instead of the American spelling, "behavior". I presume this would be fixed by switching from en_US to en_GB (both are included).&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S. Somebody asked me for 6.0-compatible versions of the strip-whitespace and &lt;a href="http://blogs.sun.com/tor/entry/tabs_are_evil_part_2"&gt;highlight-tabs&lt;/a&gt; modules; here&lt;br/&gt;&lt;a href="http://mediacast.sun.com/share/tor/org-netbeans-modules-stripwhitespace.nbm"&gt;they&lt;/a&gt;&lt;br/&gt;&lt;a href="http://mediacast.sun.com/share/tor/org-netbeans-modules-fixtabs.nbm"&gt;are&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;P.S.2. The spell checker modules obviously work for Java too; if you've been looking for NetBeans 6.0 spell checking, grab the same .zip but skip installing the ruby-bindings .nbm file.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-725651772607308415?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/725651772607308415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/08/ruby-screnshot-of-weeek-17-spelll.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/725651772607308415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/725651772607308415'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/08/ruby-screnshot-of-weeek-17-spelll.html' title='Ruby Screnshot of the Weeek #17: Spelll Checkinng'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtJRUZwsI/AAAAAAAAA4k/yXoRH2YX9Sc/s72-c/base_typos.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-5094074028705762525</id><published>2007-08-17T13:45:00.000-07:00</published><updated>2010-09-17T13:49:11.857-07:00</updated><title type='text'>Back from vacation</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;I just came back from a wonderful week in Hawaii, on the big island. The highlight was obviously our wedding. We had planned to get married on August 14th, on the beach at sunset, but because of &lt;a href="http://www.usatoday.com/weather/storms/hurricanes/2007-08-12-flossie-hawaii_N.htm"&gt;Hurricane Flossie&lt;/a&gt; most beaches were scheduled to close. It didn't turn out to be a problem - we just got married a day earlier. It was a wonderful moment and we were thrilled to have our children there to be part of it.  And obviously the rest of the vacation was great too - how can you go wrong with volcanoes (both the world's most active volcano, Kilauea, and the world's largest volano, Mauna Loa), waterfalls, snorkeling over coral reefs with turtles and tropical fish, and ....&lt;br/&gt;&lt;a href="http://blogs.sun.com/tor/entry/page_fragments_entities_and_characters"&gt;pi&amp;ntilde;a coladas&lt;/a&gt; ?&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;It will take me a few days to get the sand out of my shoes, the tropical air out of my sun hat and get through my huge inbox. Apologies to those of you waiting for some sort of response from me!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;a href="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrTsznmnI/AAAAAAAAAm4/ttEsBw_WAKQ/IMG_2536.JPG"&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrTMZsMkI/AAAAAAAAAm0/3Dxen1YY6zY/IMG_2536-small.JPG"&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;a href="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrSDOm86I/AAAAAAAAAmo/m2sx73I-nJk/IMG_2468.JPG"&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOrRs3wz_I/AAAAAAAAAmk/G9UEHPYy6g8/IMG_2468-small.JPG"&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;a href="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOrSp9dtrI/AAAAAAAAAmw/kGFsG-i6vqg/IMG_2477.JPG"&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOrSUxwkFI/AAAAAAAAAms/5ph-tQQ6K_Y/IMG_2477-small.JPG"&gt;&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOsa_K5_5I/AAAAAAAAAxo/F6Cn3ZbDir4/wedding-2-small.jpg" /&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOsaAXKXaI/AAAAAAAAAxk/wCdJzUBRJtk/wedding-1-small.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-5094074028705762525?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/5094074028705762525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/08/back-from-vacation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5094074028705762525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/5094074028705762525'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/08/back-from-vacation.html' title='Back from vacation'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOrTMZsMkI/AAAAAAAAAm0/3Dxen1YY6zY/s72-c/IMG_2536-small.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-1284277421909531837</id><published>2007-08-09T06:36:00.000-07:00</published><updated>2010-09-17T13:49:11.838-07:00</updated><title type='text'>Ruby Screenshot of the Week #15: More Hints and Quick Fixes!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Ola Bini just &lt;a href="http://ola-bini.blogspot.com/2007/08/ruby-is-hard.html"&gt;posted a blog entry&lt;/a&gt; entitled "Ruby Is Hard". In the blog entry he shows a short code snippet which does not do what you might think upon reading it.  This immediately reminded me of a dog-eared page in my worn-out copy of "Programming Ruby", specifically page 167, in the "But It Doesn't Work" section. The book covers the same problem and explains what the problem is and how to fix it.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I had marked the page for myself because when I first read it, I thought "that's something the IDE should be able to detect and warn you about!". So when I came across Ola's blog entry yesterday I figured I really should do something about it - and I had the perfect opportunity: A Java Posse recording session at Dick's new house last night. I've claimed before that writing quick fixes for Ruby in NetBeans is easy, and it really is - I completed this one as a background activity while having fun with the rest of the Posse.  We are however past feature freeze for NetBeans 6, so when I'm adding fun features like this I put it into the "Experimental Hints" module, which is not part of NetBeans 6. It -is- however included in the continuous "Ruby IDE" builds you can get &lt;a href="http://deadlock.netbeans.org/hudson/job/ruby/"&gt;here&lt;/a&gt; - and you can also install it using the Plugin Manager in standard NetBeans.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;So without further ado, here's what you get when you now open up Ola's example and the "Programming Ruby" example in NetBeans with the new hints:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsycQQmpI/AAAAAAAAA1I/6VGJn_0zMKg/attribute-hint1.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;As you can see, it's detecting the case there are local variable name assignments that match a writable attribute in the current class. If you hover over the warning it will tell you so:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_PkzBdpmSG-Y/TJOtQnQM0SI/AAAAAAAAA5o/FW25mIJdigw/attribute-hint2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;If you hit Alt-Enter, you can see the possible fixes:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOt1VJmQoI/AAAAAAAAA-s/B8rbj0KCmV0/attribute-hint3.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;These should be pretty self-explanatory. At first you may go "Huh?" and jumping to the relevant attribute may help you figure it out. The second fix will simply change the assignment to the recommended form, and the third fix will let you rename the local variable to avoid any confusion.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In order to avoid any false positives I ran this hint over a large code base (all the Ruby libraries and Rails libraries) and it came up with a handful of warnings. These probably aren't bugs, but it's at least potentially confusing; here's &lt;code&gt;baseData.rb&lt;/code&gt; from Ruby's SOAP library:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh4.ggpht.com/_PkzBdpmSG-Y/TJOtJhRSgfI/AAAAAAAAA4o/J812NwIqlW4/baseData.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;There are some other experimental hints too, in particular, a hint which detects actions in your controllers that don't have associated view files and offers to create them (using the Rails code generator), as well as various name warnings.  Here's a warning which detects un-Ruby-like method names and local variable names (camelCase instead of not_camel_case) - this one from a Rails test case:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_PkzBdpmSG-Y/TJOuVQPiu9I/AAAAAAAABCY/mAtb8lsIoGE/localvarname-hint.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here's the current customizer. Some of the hints are not enabled by default, so you should inspect these yourself and enable those you are interested in. One hint I definitely didn't want to enable by default is the "constant name" warning. I was under the impression that constants should use all upper-case letters separated by underscores, and this is indeed the case in lots and lots of Ruby code. But there are quite a few exceptions, where constants are just capitalized - so this seems like a warning that may need some tweaking or is an individual preference. Here's the customizer:&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOtUd4MOWI/AAAAAAAAA6E/6IvceVfk1Zw/experimental-hints.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;In other news, a lot of bug fixing is happening so stay up to date with the builds :)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-1284277421909531837?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/1284277421909531837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/08/ruby-screenshot-of-week-15-more-hints.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1284277421909531837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/1284277421909531837'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/08/ruby-screenshot-of-week-15-more-hints.html' title='Ruby Screenshot of the Week #15: More Hints and Quick Fixes!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOsycQQmpI/AAAAAAAAA1I/6VGJn_0zMKg/s72-c/attribute-hint1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-8558741857578986034</id><published>2007-07-24T05:45:00.000-07:00</published><updated>2010-09-17T13:49:11.824-07:00</updated><title type='text'>Code Advice #15: Name getters properly!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;(See &lt;a href="http://blogs.sun.com/roller/page/tor?entry=code_advice"&gt;intro&lt;/a&gt; for a background and caveats on these coding advice blog entries.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;It's been a while since I've posted Java-coding opinions. But I couldn't resist on this one. The tip itself is straightforward:&lt;br/&gt;&lt;blockquote&gt;&lt;br/&gt;A getter method's name should not sound like an action method.&lt;br&gt;&lt;br/&gt;Getter methods and setter methods should not have the same name.&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I'm speaking from bitter experience since I &lt;b&gt;just&lt;/b&gt; fixed a bug where my code had accidentally been calling a getter method, when I thought I was calling a setter method.&lt;br/&gt;The method in question is &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ProcessBuilder.html#redirectErrorStream()"&gt;java.lang.ProcessBuilder#redirectErrorStream&lt;/a&gt;. If you're launching a process, and you want to read its output, you may want to redirect its error output to its standard output such that you only have to read the input from a single source (assuming you don't care to distinguish between output and error.)&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Well, my code was initializing the &lt;code&gt;ProcessBuilder&lt;/code&gt;:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;ProcessBuilder pb = new ProcessBuilder(args);&lt;br/&gt;pb.directory(pwd);&lt;br/&gt;pb.redirectErrorStream();&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The problem here is that &lt;code&gt;redirectErrorStream()&lt;/code&gt; does NOT redirect the error stream! It just returns &lt;code&gt;false&lt;/code&gt; to tell me that it's not yet planning to redirect the error stream. The correct way to do this is&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;ProcessBuilder pb = new ProcessBuilder(args);&lt;br/&gt;pb.directory(pwd);&lt;br/&gt;pb.redirectErrorStream(&lt;b&gt;true&lt;/b&gt;);&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;That's right - the setter and the getter are overloaded!   Ewwwww!!!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;This is the kind of thing a bug detection tool like &lt;a href="http://findbugs.sourceforge.net/"&gt;findbugs&lt;/a&gt; could detect. It already warns if it sees you doing something similar, like calling &lt;code&gt;String.trim()&lt;/code&gt; without storing the return value. Unfortunately, it didn't warn me about this case - so I &lt;a href="https://sourceforge.net/tracker/?func=detail&amp;atid=614693&amp;aid=1759836&amp;group_id=96405"&gt;filed a request&lt;/a&gt;. But this was a great reminder to run findbugs on my code again, which turned up some other interesting things to look at...&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-8558741857578986034?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/8558741857578986034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/07/code-advice-15-name-getters-properly.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8558741857578986034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/8558741857578986034'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/07/code-advice-15-name-getters-properly.html' title='Code Advice #15: Name getters properly!'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-6051822032144500668</id><published>2007-07-24T05:43:00.000-07:00</published><updated>2010-09-17T13:49:11.809-07:00</updated><title type='text'>NetBeans Ruby support interview</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;Roman and Gregg &lt;a href="http://blogs.sun.com/roumen/entry/netbeans_podcast_episode_32_interview"&gt;interviewed me&lt;/a&gt; in the latest episode of the NetBeans podcast.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here are the shownotes from Roman's blog:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt;0:00 Introduction and Tor's podcasting, he's also a podcaster at the &lt;a href="javaposse.com"&gt;Javaposse&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;2:30 What Tor has worked on at Sun: &lt;a href="http://developers.sun.com/jscreator/"&gt;Java Studio Creator&lt;/a&gt;,&lt;br/&gt;&lt;a href="http://en.wikipedia.org/wiki/Project_Semplice"&gt;Project Semplice&lt;/a&gt;,&lt;br/&gt;and the &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt;&lt;br/&gt;&lt;a href="http://www.ruby-lang.org/en/"&gt;tools&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;5:00 Overview of Ruby features in the&lt;br/&gt;&lt;a href="http://www.netbeans.org/servlets/NewsItemView?newsItemID=1073"&gt;NetBeans IDE&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;7:25 Debugging Ruby&lt;/li&gt;&lt;br/&gt;&lt;li&gt;9:50 &lt;a href="http://www.rubyonrails.org/"&gt;Rails&lt;/a&gt; support&lt;/li&gt;&lt;br/&gt;&lt;li&gt;10:51 Switching between Ruby implementations&lt;/li&gt;&lt;br/&gt;&lt;li&gt;11:49 Implementation of the type inference and code completion logic&lt;/li&gt;&lt;br/&gt;&lt;li&gt;17:10 Implementation of refactoring features&lt;/li&gt;&lt;br/&gt;&lt;li&gt;18:54 Features Tor wants to implement next&lt;/li&gt;&lt;br/&gt;&lt;li&gt;21:33 Community feedback&lt;/li&gt;&lt;br/&gt;&lt;li&gt;23:17 Why should Java developers look at Ruby?&lt;/li&gt;&lt;br/&gt;&lt;li&gt;26:38 Other Ruby development tools&lt;/li&gt;&lt;br/&gt;&lt;li&gt;29:49 A version of NetBeans IDE that just has Ruby support?&lt;br/&gt;Check out &lt;a href="http://deadlock.netbeans.org/hudson/job/ruby/"&gt;this page on deadlock&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&lt;li&gt;32:16 Opportunities for contributors and cool features; check out the&lt;br/&gt;&lt;a href="http://wiki.netbeans.org/wiki/view/Ruby"&gt; wiki page&lt;/a&gt;.&lt;/li&gt;&lt;br/&gt;&lt;li&gt;34:55 Support for other dynamic languages.&lt;br/&gt;&lt;a href="http://blogtrader.net/page/dcaoyuan?entry=erlybird_0_11_2_released"&gt;Erlang IDE&lt;/a&gt; based&lt;br/&gt;on Tor's code.&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;The episode is &lt;a href="http://roumen.name/blog/podcast/nb_podcast_32.mp3"&gt;here&lt;/a&gt;, subscription is &lt;a href="http://feeds.feedburner.com/netbeanspod"&gt;here&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3283609923804350642-6051822032144500668?l=tornorbye.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tornorbye.blogspot.com/feeds/6051822032144500668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tornorbye.blogspot.com/2007/07/netbeans-ruby-support-interview.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6051822032144500668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3283609923804350642/posts/default/6051822032144500668'/><link rel='alternate' type='text/html' href='http://tornorbye.blogspot.com/2007/07/netbeans-ruby-support-interview.html' title='NetBeans Ruby support interview'/><author><name>Tor Norbye</name><uri>http://www.blogger.com/profile/00746799716822637466</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3283609923804350642.post-1678547760495284338</id><published>2007-07-18T05:44:00.000-07:00</published><updated>2010-09-17T13:49:11.794-07:00</updated><title type='text'>Jump In - The Water's Warm!</title><content type='html'>&lt;p&gt;&lt;b&gt;WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;img src="http://lh5.ggpht.com/_PkzBdpmSG-Y/TJOroIOxOTI/AAAAAAAAAqU/8CCE-p2ckjA/hintsoptions2.jpg" /&gt;&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;My &lt;a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week14"&gt;previous blog entry&lt;/a&gt; discussed the new Quick Fix feature for Ruby in NetBeans.&lt;br/&gt;Today, I'd like to invite you all to jump in and add your own quick fixes!&lt;br/&gt;Nothing (with some notable exceptions...) could be more fun! Writing a quickfix is easy, fairly self-contained (so it's easy to get started), and the resulting feature has high user visibility and utility. Thus, I think it's a great way to join an open source project and have some fun. Besides, working on tools is extra rewarding since at the end of the day, as a programmer you get to use the stuff you're building in your day-to-day work!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I've written a bunch of "Getting Started" documentation for how to write your own hints.  The main starting point is is the &lt;a href="http://wiki.netbeans.org/wiki/view/RubyAddHints"&gt;How to Write a Hint&lt;/a&gt; document, which tells you everything you need to know. Look it over and see if you get inspired!  If so, follow these steps:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;&lt;li&gt; Check out the code and build the IDE (as &lt;a href="http://wiki.netbeans.org/wiki/view/RubyBuildInstructions"&gt;described here&lt;/a&gt;).&lt;br/&gt;&lt;li&gt; Read more information on &lt;a href="http://wiki.netbeans.org/wiki/view/RubyParticipation"&gt;how to join the project&lt;/a&gt; (license requirements etc.)&lt;br/&gt;&lt;li&gt; If you want to write other code than just hints, check out the &lt;a href="http://wiki.netbeans.org/wiki/view/RubyCodeIdeas"&gt;code ideas document&lt;/a&gt;.&lt;br/&gt;&lt;li&gt; If some of the documentation is not clear, please let me know or ask on &lt;a href="mailtop:dev@ruby.netbeans.org"&gt;dev@ruby.netbeans.org&lt;/a&gt; - or if you know how to improve it, edit it directly!&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;Even if you don't want to code on the project, I'd love to have your active mailing list participation. Please &lt;a href="http://wiki.netbeans.org/wiki/view/RubyParticipation"&gt;join the mailinglists&lt;/a&gt; (or read it with a newsreader or web interface).  Also feel free to edit the wiki pages and add your own quickfix requests.&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;I hope to see some of you on &lt;a href="mailtop:dev@ruby.netbeans.org"&gt;dev@ruby.netbeans.org&lt;/a&gt; soon!&lt;br/&gt;&lt;/p&gt;&lt;br/&gt;&lt;p&gt;&lt;br/&gt;Here are some hint ideas to get you started (a more up to date list is in the hint-howto wiki page):&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;li&gt; Offer to replace a { } block with a do-end and vice versa (unless it's a single-line block where braces are most common)&lt;br/&gt;&lt;/li&gt;&lt;li&gt; Look for typos: incorrect spelling of "initialize", or perhaps an assignment to a variable that is close in spelling to another symbol&lt;br/&gt;&lt;/li&gt;&lt;li&gt; Offer to add parentheses to a code construct where the lack of parentheses results in ambiguity (such as nested method calls without parentheses)&lt;br/&gt;&lt;/li&gt;&lt;li&gt; Offer to remove parentheses where that's okay (some developers prefer not to use them)&lt;br/&gt;&lt;/li&gt;&lt;li&gt; Offer non-Railsy deprecations:  Use fileutils instead of ftools, cgi instead of cgi-lib, avoid importenv, ... Anything else?&lt;br/&gt;&lt;/li&gt;&lt;li&gt; Offer to remove unused variables (the left hand side of the assignment, or if the right hand side is known not to&lt;br/&gt;have side effects, the entire statement)&lt;br/&gt;&lt;/li&gt;&lt;li&gt; Style warnings: Using method names containing uppercase/camelcase names, or constants containing lowercase characters&lt;br/&g
