This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Shell 3.4.0!

Component Render

You can implement component rendering in either of two ways: fully programmatically or by using a ANTLR Stringtemplate. Strictly speaking, there is a simple Function renderer interface that takes Context as an input and outputs a list of AttributedString. This lets you choose between templating and code.

Templating is a good choice if you do not need to do anything complex or you just want to slightly modify existing component layouts. Rendering through code then gives you flexibility to do whatever you need.

The programmatic way to render is to create a Function:

class StringInputCustomRenderer implements Function<StringInputContext, List<AttributedString>> {
	@Override
	public List<AttributedString> apply(StringInputContext context) {
		AttributedStringBuilder builder = new AttributedStringBuilder();
		builder.append(context.getName());
		builder.append(" ");
		if (context.getResultValue() != null) {
			builder.append(context.getResultValue());
		}
		else  {
			String input = context.getInput();
			if (StringUtils.hasText(input)) {
				builder.append(input);
			}
			else {
				builder.append("[Default " + context.getDefaultValue() + "]");
			}
		}
		return Arrays.asList(builder.toAttributedString());
	}
}

Then you can hook it to a component:

@ShellMethod(key = "component stringcustom", value = "String input", group = "Components")
public String stringInputCustom(boolean mask) {
	StringInput component = new StringInput(getTerminal(), "Enter value", "myvalue",
			new StringInputCustomRenderer());
	component.setResourceLoader(getResourceLoader());
	component.setTemplateExecutor(getTemplateExecutor());
	if (mask) {
		component.setMaskCharacter('*');
	}
	StringInputContext context = component.run(StringInputContext.empty());
	return "Got value " + context.getResultValue();
}

Components have their own context but usually share some functionality from a parent component types. The following tables show those context variables:

Table 1. TextComponentContext Template Variables
Key Description

resultValue

The value after a component renders its result.

name

The name of a component — that is, its title.

message

The possible message set for a component.

messageLevel

The level of a message — one of INFO, WARN, or ERROR.

hasMessageLevelInfo

Return true if level is INFO. Otherwise, false.

hasMessageLevelWarn

Return true if level is WARN. Otherwise, false.

hasMessageLevelError

Return true if level is ERROR. Otherwise, false.

input

The raw user input.

Table 2. SelectorComponentContext Template Variables
Key Description

name

The name of a component — that is, its title.

input

The raw user input — mostly used for filtering.

itemStates

The full list of item states.

itemStateView

The visible list of item states.

isResult

Return true if the context is in a result mode.

cursorRow

The current cursor row in a selector.

Table 3. ComponentContext Template Variables
Key Description

terminalWidth

The width of terminal, type is Integer and defaults to NULL if not set.