When you press Enter in the Source Editor, automatically an indentation is created because an implementation of org.netbeans.modules.editor.indent.spi.IndentTask performs the indentation in the file. When the IndentTask does this, it retrieves the value of a property named "indent-shift-width" (via SimpleValueNames.INDENT_SHIFT_WIDTH). That property defines a value, which is the number of characters that the indentation should consist of, which is by default 4.

Now, the question is how does the IndentTask retrieve this property?

You can provide the location from where this property, together with many others, such as "text-limit-width", should be retrieved. Use CodeStylePreferences.Provider for this purpose, as below:

import java.util.prefs.Preferences;
import javax.swing.text.Document;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.modules.editor.indent.api.IndentUtils;
import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.util.NbPreferences;
import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = CodeStylePreferences.Provider.class)
public final class FileCodeStylePreferences implements CodeStylePreferences.Provider {
    public Preferences forDocument(Document doc, String mimeType) {
        Preferences node = null;
        FileObject fo = findFileObject(doc);
        if (fo != null) {
            Project p = FileOwnerQuery.getOwner(fo);
            if (p != null) {
                String foName = fo.getName();
                String projectName = p.getProjectDirectory().getName();
                node = NbPreferences.forModule(IndentUtils.class).node(projectName).node(foName);
        return node;
    public Preferences forFile(FileObject fo, String mimeType) {
        //not used:
        return null;
    private static FileObject findFileObject(Document doc) {
        if (doc != null) {
            Object sdp = doc.getProperty(Document.StreamDescriptionProperty);
            if (sdp instanceof DataObject) {
                return ((DataObject) sdp).getPrimaryFile();
            } else if (sdp instanceof FileObject) {
                return (FileObject) sdp;
        return null;

Here you can see that we're providing the location where codestyle preferences, such as "indent-shift-width" should be located when IndentTask (and ReformatTask and other functionality) is invoked.

Now that the location has been defined, a special unique one as can be seen above (assuming projectname-filename results in a unique string, which is a pretty big assumption, I agree), based on the name of the project and of the file where the IndentTask (and ReformatTask and whatever other codestyle related task) is performed, we need to somehow provide the values for these properties.

For this, one example is that you can add a ProjectOpenedHook to the Lookup of existing projects and, whenever needed, add a value that you retrieve from somewhere (e.g., to the location that you're already aware of because of the code above, as shown here:

@LookupProvider.Registration(projectType = {
public class EditorConfigProjectOpenedHook implements LookupProvider {
    public Lookup createAdditionalLookup(Lookup lookup) {
        final Project p = lookup.lookup(Project.class);
        return Lookups.fixed(new ProjectOpenedHook() {
            protected void projectOpened() {
                FileObject projFo = p.getProjectDirectory();

And in this way you can create file-based codestyle preferences that will automatically be picked up and used by the NetBeans codestyle-related features.


Post a Comment:
  • HTML Syntax: NOT allowed

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.


« March 2015