Last updated Feb 19, 2024

Fisheye gutter renderer plugin tutorial

This tutorial teaches you how to add extra information to annotated views of files, and to diffs

Plugin Source

We encourage you to work through this tutorial. If you want to skip ahead or check your work when you are done, you can find the plugin source code on Atlassian Bitbucket. Bitbucket serves a public Git repository containing the tutorial's code. To clone the repository, issue the following command:

1
2
$ git clone https://atlassian_tutorial@bitbucket.org/atlassian_tutorial/fecru-gutter-tutorial.git

Alternatively, you can download the source using the Downloads page here: bitbucket.org/atlassian_tutorial/fecru-gutter-tutorial

Introduction To Gutter Renderers

A gutter renderer should not be performing time-consuming analysis of code at render time - if (for instance) you wished to perform style checking of code and report issues with a gutter renderer, the analysis would be best done either in an external system (e.g. your continuous integration server) or with an Event Listener. The stored results from the analysis would be used by the gutter renderer.

A gutter renderer plugin adds an extra column in the form of a <td> tag at the left hand side of the text of annotated file views and diff views.

The plugin controls the HTML class of the td, can give it a style (to avoid the need to provide a custom CSS file) and of course provides the HTML contained by the td.

Structure of a Gutter Renderer

Writing a gutter renderer requires that you create implementations of three interfaces:

A Sample Gutter Renderer

The gutter renderer we develop in this tutorial will simply display some text on the nth line of each file whose name contains the letter 'a', where n is the number of characters in the name. It will not provide any decoration for diffs.

The GutterRenderer implementation looks like this:

1
2
public class TutorialGutterRenderer implements GutterRenderer {

    public List<LineDecorator> getAnnotationDecorators(String repository, String path, String rev) {
        String fileName = path.substring(path.lastIndexOf('/')+1);
        if (fileName.matches(".*[aA].*")) {
            return Collections.<LineDecorator>singletonList(new TutorialLineDecorator(fileName.length()));
        } else {
            return Collections.emptyList();
        }
    }

    public List<DiffLineDecorator> getAnnotationDecorators(DiffType diffType, String repository, String fromPath, String fromRev, String toPath, String toRev) {
        return Collections.emptyList();
    }
}

and the LineDecorator implementation looks like this:

1
2
public class TutorialLineDecorator implements LineDecorator {
    private final int lineToDecorate;

    public TutorialLineDecorator(int lineToDecorate) {
        this.lineToDecorate = lineToDecorate;
    }

    public int getWidth() {
        return 10; // the width required for this gutter column, in ems
    }

    public GutterRenderResult decorateLine(int i) {
        GutterRenderResult r = new GutterRenderResult();
        if (i == lineToDecorate) {
            r.setInnerHtml("Decoration!");
        }
        return r;
    }
}

Rate this page: