Java 从spring shell中的少量选项中进行选择
我目前正在尝试使用SpringShell制作cli应用程序 我希望用户能够快速选择2-3个选项之一。我当前的代码在eclipse中运行良好,但当我在Powershell中启动它时,我必须多次按enter键(至少3次)才能选择该选项。按enter键一次后,什么也不会发生 我目前的方法是: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
@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 + "\"";
}
}