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.
HelpSectionAirline 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.
HelpSectionFactoryNow 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.