spring-projects / spring-shell

Spring based shell
http://projects.spring.io/spring-shell/
Apache License 2.0
724 stars 394 forks source link

Spring Shell ComponentFlow and locale #1113

Closed rugbroed closed 1 month ago

rugbroed commented 1 month ago

I can't get Spring Shell to accept non-english characters (in my case, Danish).

To be precise; when the shell starts, I can input the danish characters æøå without problems in the shell itself (not running any commands, just typing the characters in the shell). But as soon as I want to input them using a ComponentFlow or StringInput getting the input text from a context, the keypresses are ignored and are not concatenated in the resulting string.

Can someone please help me figure out if there is a problem with non-english characters for input?

You can reproduce by making a simple ShellComponent with a ShellMethod and a ComponentFlow with a withStringInput and try to enter danish characters and see if you can get it from the context like this;

@ShellComponent
public class ProductCommand {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @ShellMethod(key = "test-locale")
    public String testLocale() {
        logger.info("Terminal is not null. Charset: " + terminal.encoding().displayName());

        ComponentFlow flow = componentFlowBuilder.clone()
                .withStringInput("testString")
                .name("Test string")
                .renderer(new StringInputCustomRenderer()).and().build();

    ComponentFlowResult result = flow.run();

    return "testString = " + result.getContext().get("testString");
}

The logger output is UTF-8, but I'm not able to input 'æøå' when running the test-locale command in the Test string prompt.

OR you can use the below instead;

StringInput component = new StringInput(terminal, "Test string", "testString", new StringInputCustomRenderer());
component.setResourceLoader(resourceLoader);
component.setTemplateExecutor(templateExecutor);
StringInputContext context = component.run(StringInputContext.empty());     

return context.getResultValue();
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());
    }
}

I'm using Ubuntu 24.04, Spring Boot Starter 3.3.2 and Spring Shell 3.3.1.

Thanks.

jvalkeal commented 1 month ago

Fixed in #1115. Backported to 3.3.x and 3.2.x. You can try snapshots until there's a release.