Java 从spring shell中的少量选项中进行选择

Java 从spring shell中的少量选项中进行选择,java,command-line-interface,spring-shell,Java,Command Line Interface,Spring Shell,我目前正在尝试使用SpringShell制作cli应用程序 我希望用户能够快速选择2-3个选项之一。我当前的代码在eclipse中运行良好,但当我在Powershell中启动它时,我必须多次按enter键(至少3次)才能选择该选项。按enter键一次后,什么也不会发生 我目前的方法是: @ShellMethod(key = { "setService", "select" }, value = "Choose a Speech to Text Service") public void set

我目前正在尝试使用SpringShell制作cli应用程序

我希望用户能够快速选择2-3个选项之一。我当前的代码在eclipse中运行良好,但当我在Powershell中启动它时,我必须多次按enter键(至少3次)才能选择该选项。按enter键一次后,什么也不会发生

我目前的方法是:

@ShellMethod(key = { "setService", "select" }, value = "Choose a Speech to Text Service")

public void setService() {
    boolean success = false;
    do {
        this.console.write("Please select a speech recognition service. Type in the number and press enter:");
        this.console.write("1. Google Speech API");
        this.console.write("2. Bing Speech API");

        // Get Input
        Scanner s = new Scanner(System.in);
        String input = s.nextLine();

        // Select Service
        switch (input) {
        case "1":
            /*
             * do something...
             */
            console.write("Google Speech API selected");
            success = true;
            break;
        case "2":
            /*
             * do something...
             */
            console.write("Bing Speech API selected");
            success = true;
            break;
        default:
            this.console.error("Input not valid. Please type a number and press Enter to select a Service");
            break;
        }
    } while (!success);
}

我如何解决powershell的问题,或者是否有更优雅的方法来执行此输入?

面对类似的要求,并且在JLine 3或Spring Shell 2文档中没有找到这样的例子,我做了一些实验

基本上-这些组件不是设计成这样工作的。在@ShellMethod的上下文中尝试获取额外的用户输入是不受支持的功能

您可能使用System.out或System.in执行的任何IO活动最终都会在引擎盖下由JLine进行不同的处理,具体取决于您第一次启动的shell类型,因此您观察到,从PowerShell调用应用程序与从IDE内启动应用程序时,您的尝试表现不同。如果在Windows上从GitBash启动,我能够获得所需的行为,但如果从CMD启动,则无法获得所需的行为。在一个例子中,我最终完全破坏了应用程序

然而,我确实找到了一种方法来提示输入,这种方法对GitBash和CMD都有效。此示例在普通JLine中不起作用,但在SpringShell 2.0中似乎起作用,只要您使用SpringBoot自动配置,该配置允许您访问Spring为您的Shell应用程序初始化的相同“LineReader”实例

@Autowired
LineReader reader;

public String ask(String question) {
    return this.reader.readLine("\n" + question + " > ");
}

@ShellMethod(key = { "setService", "select" }, value = "Choose a Speech to Text Service")
public void setService() {
    boolean success = false;
    do {
        String question = "Please select a speech recognition service. Type in the number and press enter:"
        + "\n 1. Google Speech API"
        + "\n 2. Bing Speech API";

        // Get Input
        String input = this.ask(question);

        // Select Service
        switch (input) {
        case "1":
            /*
             * do something...
             */
            console.write("Google Speech API selected");
            success = true;
            break;
        case "2":
            /*
             * do something...
             */
            console.write("Bing Speech API selected");
            success = true;
            break;
        default:
            this.console.error("Input not valid. Please type a number and press Enter to select a Service");
            break;
        }
    } while (!success);
}
我用它来做类似的事情。更具体地说,我在[IntInputReader][2]上使用read方法,根据其文档,该方法非常方便:

读取类型为T的值。它会反复提示用户输入该值,直到用户提供有效的输入字符串

由于我在SpringShell应用程序中多次需要此功能,以便用户从不同类型的对象中进行选择,因此我编写了一个通用方法

向用户显示给定类型{@code T}的项目列表,并提示他们选择一个或多个项目。(可选)选择完成后,将向用户显示其选择的摘要以供确认

不幸的是,StackOverflow正在破坏我的Javadoc,所以我创建了一个


弹簧壳2基于弹簧。对于少量选项,我建议使用tab completion之类的功能

它在Powershell上工作,但我从未在Eclipse控制台中获得任何选项卡完成支持

这很容易:

import java.util.List;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.terminal.Terminal;
import org.springframework.context.annotation.Lazy;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;

@ShellComponent
public class CompleterInteractionCommand {

    private final List<String> OPTIONS = List.of("create", "update", "delete");
    private final Terminal terminal;

    public CompleterInteractionCommand(@Lazy final Terminal terminal) {
        this.terminal = terminal;
    }

    @ShellMethod
    public String completeSelect() {
        LineReader lineReader = LineReaderBuilder.builder()
                .terminal(this.terminal)
                .completer(new StringsCompleter(this.OPTIONS))
                .build();
        /* Important: This allows completion on an empty buffer, rather than inserting a tab! */
        lineReader.unsetOpt(LineReader.Option.INSERT_TAB);

        String desription = "select on of this options: " + OPTIONS + "\n"
                          + " use TAB (twice) to select them\n";        
        String input = lineReader.readLine(desription + "input: ").trim();
        return "you selected \"" + input + "\"";
    }
}
  @ShellMethod(
  key = "select-something",
  value = "Select something")
public void select() {
    Instance selected = cliObjectSelector(instances, false, requireConfirmation,
        "Please select one of the " + instances.size() + " instances from the list",
        instance -> instance.getX().getName()).get(0);
  }
import java.util.List;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.terminal.Terminal;
import org.springframework.context.annotation.Lazy;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;

@ShellComponent
public class CompleterInteractionCommand {

    private final List<String> OPTIONS = List.of("create", "update", "delete");
    private final Terminal terminal;

    public CompleterInteractionCommand(@Lazy final Terminal terminal) {
        this.terminal = terminal;
    }

    @ShellMethod
    public String completeSelect() {
        LineReader lineReader = LineReaderBuilder.builder()
                .terminal(this.terminal)
                .completer(new StringsCompleter(this.OPTIONS))
                .build();
        /* Important: This allows completion on an empty buffer, rather than inserting a tab! */
        lineReader.unsetOpt(LineReader.Option.INSERT_TAB);

        String desription = "select on of this options: " + OPTIONS + "\n"
                          + " use TAB (twice) to select them\n";        
        String input = lineReader.readLine(desription + "input: ").trim();
        return "you selected \"" + input + "\"";
    }
}