Saturday, April 6, 2013

Bending NetBeans Code Templates to My Will

Anyone who has read any of my posts on NetBeans knows that there are numerous features of NetBeans that I really like. Recently, however, I found myself becoming increasingly irritated with a particular issue with a particular feature of NetBeans. It finally bothered me enough to motivate me to look into how to disable or alter that feature to my liking. This post looks at how I learned to bend NetBeans code templates to my will, helping me to be much happier with the template code completion.

NetBeans provides several code templates for several different manifestations of the for loop. These include automatic code completion for for loops on arrays, on collections, on iterables, on Maps, on integers to a specified maximum, and more. By default, these code templates are automatically invoked upon the typing of the appropriate abbreviation in the NetBeans code editor and pressing the space bar.

The problem I had was that the majority of the time I was simply trying to type "for (" to use the enhanced for loop on a collection, but the NetBeans code template with abbreviation "for" was kicking off and generating a for loop on an integer with ten iterations. Although historically such integer iteration for a predefined number of times was the most common use of for, the introduction of the enhanced for loop with J2SE 5 changed everything; I now use for for the enhanced for loop on collections, arrays, and maps far more than I ever use it to iterate over an integer a prescribed number of times.

The next two screen snapshots demonstrate the issue I just described. The first screen snapshot shows the NetBeans code editor when I'm about ready to start typing my for loop to iterate over the collection provided to the method I'm implementing. The second screen snapshot shows the code NetBeans automatically generates as soon as I have typed the space after "for" in the editor. It is not what I wanted and so I have to delete the majority of that generated code to adapt it to iterate over my collection.

The reason this behavior is a problem for me is because the abbreviation "for" happens to also be the Java keyword I'm trying to type. When I type the space after "for", I'm only typing in Java code, but NetBeans interprets it as me meaning that I want the code template for a for loop iterating on an integer to be generated. I almost never want this when I type "for ". One way to get around this issue is to change the NetBeans templates so that something other than space activates them. The next series of snapshots demonstrate how to do this. In this case, I'm change Shift+Space to be what activates the code template, but NetBeans also supports use of Tab or Enter as the keystroke that activates a code template for a typed in abbreviation.

With the code templates changed so that they are activated (templates are expanded on) Shift+Space rather than simply on Space, the issue bothering me goes away. This is shown in the next screen snapshot. The image shows that after I type "for" and a space, the code stays as I typed it rather than triggering the template code completion adding a "for" loop implementation I did not intend.

The solution I just demonstrated (changing Space to Space+Shift as the activation for expanding code templates) certainly gets me past the initial irritant of code completion that I rarely want when using a "for" loop. I can still use Space+Shift to get the code completion when I do want it. This last point is significant because NetBeans does offer several other "for" loop completion code templates, including one that fits my typical case when I want to use the "for" loop. The next screen snapshot shows code in NetBeans using all but two of these available "for" code templates.

As this image indicates, NetBeans supports "for" (integer iteration already shown), "forc" (iterator on collection allowing actions on iterator not allowed by enhanced for-each loop), "fore" (for-each style general collection/enumeration iteration; the one I use most often), "fori" (array iteration), "forl" (List iteration), and "form" (Map iteration) as code template abbreviations for different types of "for" loops to be automatically generated. Although not shown in the image, NetBeans also supports code template abbreviations "forst" for generating a "for" loop on a StringTokenizer and "forv" for generating a "for" loop on a Vector.

At this point, I could have stopped and simply planned to use Shift+Space after typing the appropriate NetBeans code template abbreviation when I wanted one of the different "for" loop types. However, there are some downsides to this. First, it seems that changing the keystore upon which code template generation is activated is all-or-nothing; when I apply it to the "for" template, all the templates are then only activated by Shift+Space. There are other templates that more naturally match what I desire and I like having them activated by the space rather than needing to use Shift+Space. Second, because I do use the "for" loop for the same case of iterating over a collection using the "for each" style enhanced for loop the vast majority of the time, I feel like my preference would be for that to be generated every time I type "for" followed by a space. I'd only need to "undo" that generation in the rare times that I don't want the enhanced for loop.

Fortunately, NetBeans allows me to create new code generation templates and modify existing ones. This allows me to change "for" to be the case I want (the "fore" case). I look at that approach next.

My plan was to copy the "expanded text" for the "fore" template as the expanded text for the "for" template. However, I didn't want to lose what "for" has by default for the rare times I do want that, so I want to create a new code template into which the current "for" expanded text can be copied. In my case, I'm creating a new template with abbreviation "fort" into which I will copy the existing "for" expanded template text. Then, I can copy the expanded template text for "fore" into "fore". This effectively allows NetBeans to generate the code I almost always want when I type "for" and then a space. This also allows me to change the code templates to be activated upon simply space rather than requiring Shift+Space. The next three screen snapshots demonstrate this process.

A positive side effect of my modification of the "for" NetBeans code template is that I was able to add the final keyword for the iteration variable to the template. This means I don't need to manually add the "final" modifier after the template generation when I want it there. This means, of course, that I could add in the final keyword in other templates provided by NetBeans as well.

With the "for" code template changed to be the case I typically want (iterating with for-each-style over a collection), I can it out in my method I am trying to implement. This is shown in the next screen snapshot.

This last image shows that I now get the "for" loop I most commonly want when I type a space following the "for" keyword. In the rare cases I want another type or use of the "for" loop, I can use those types code template' acronyms instead or (more likely because I probably won't remember to use these rarely used code templates) simply remove the code that doesn't apply.

Conclusion

The fact that NetBeans was "completing" my "for" loops for me in a way that I almost never want was really getting on my nerves (giving new meaning to "you complete me"). Fortunately, NetBeans presents acceptable options to remove this irritant. As demonstrated in this post, it is easy to change NetBeans code templates to be expanded based on something more obviously explicit than space (Shift+Space, Tab, or Enter). Even better, NetBeans allows one to add, revise, and remove templates, allowing greater flexibility in determining which templates apply and how they are applied. It may seem like a small thing, but I'm really much happier now that the oft-written "for" loops no longer get completed incorrectly for me.

No comments: