You can of course like most things in Airline extend the help sections system with your own custom help section.
Creating a custom help section requires you to do the following:
HelpSection
for your sectionHelpSectionFactory
that can create your help section from your annotationServiceLoader
manifest that registers your factoryFirstly we need to create an annotation that we will apply to our classes to specify our custom help section. In this example we define a @RelatedCommands
annotation:
package com.github.rvesse.airline.examples.userguide.help.sections.custom;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({ TYPE })
@Documented
public @interface RelatedCommands {
/**
* Provides a list of related commands
*
* @return Related commands
*/
String[] commands() default {};
}
This is a fairly simple annotation that simply takes in an array of commands that are related to our command.
The most important aspect here is the @Retention
annotation to specify that this annotation is retained and available at runtime. We also use the @Target
annotation to constrain where users may apply our annotation.
HelpSection
Airline provides several useful base classes to make it easier to implement custom sections. For a start the BasicSection
class provides a basic implementation of the entire interface that simply requires you to pass all the information into the constructor e.g.
package com.github.rvesse.airline.examples.userguide.help.sections.custom;
import com.github.rvesse.airline.help.sections.HelpFormat;
import com.github.rvesse.airline.help.sections.common.BasicSection;
import com.github.rvesse.airline.help.sections.common.CommonSections;
public class RelatedCommandsSection extends BasicSection {
public RelatedCommandsSection(String[] commands) {
super("Related Commands", CommonSections.ORDER_EXAMPLES + 1,
"The following related commands may also be of interest:", null, HelpFormat.LIST, commands);
}
}
Note how we only need to define a constructor here that passes all the relevant arguments to the base implementation.
For even more simplistic sections which are just textual you can likely simply extend ProseSection
instead.
HelpSectionFactory
Now we have our annotation and our section implementation we can create a factory that knows how to convert the annotation into the help section e.g.
package com.github.rvesse.airline.examples.userguide.help.sections.custom;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.List;
import com.github.rvesse.airline.help.sections.HelpSection;
import com.github.rvesse.airline.help.sections.factories.HelpSectionFactory;
public class RelatedCommandsFactory implements HelpSectionFactory {
@Override
public HelpSection createSection(Annotation annotation) {
if (annotation instanceof RelatedCommands) {
RelatedCommands related = (RelatedCommands) annotation;
return new RelatedCommandsSection(related.commands());
} else {
return null;
}
}
@Override
public List<Class<? extends Annotation>> supportedAnnotations() {
return Collections.<Class<? extends Annotation>>singletonList(RelatedCommands.class);
}
}
Here we can see that our factory declares that it supports our @RelatedCommands
annotation and creates an instance of our actual help section RelatedCommandsSection
ServiceLoader
manifestAirline detects and processes the available help sections using Java’s ServiceLoader
mechanism for dynamic loading of extension points. This requires manifest files to be placed under META-INF/services
inside your JAR files, in a typical Maven build environment you will place these under src/main/resources/META-INF/services
to ensure they are output in the correct place within the resulting JAR file.
You will need to add a manifest for the factory interfaces you are implementing. So for our example on this page we need to add the manifests com.github.rvesse.airline.help.sections.factories.HelpSectionFactory
Each line in the manifest simply is the class name of our factory implementations, so for our example we would need to add the following line to both manifests:
com.github.rvesse.airline.examples.userguide.help.sections.custom.RelatedCommandsFactory
This documentation is itself open source and lives in GitHub under the docs/ directory.
I am not a professional technical writer and as the developer of this software I can often make assumptions of
knowledge that you as a user reading this may not have. Improvements to the documentation are always welcome, if you
have suggestions for the documentation please submit pull requests to the main
branch.