Skip to content

Commit 3f74eee

Browse files
Merge pull request #18286 from stuartwdouglas/change-arguments
Add ability to change args between restarts
2 parents 82793e9 + 3c411e4 commit 3f74eee

File tree

14 files changed

+326
-87
lines changed

14 files changed

+326
-87
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package io.quarkus.deployment;
2+
3+
import io.quarkus.runtime.annotations.ConfigItem;
4+
import io.quarkus.runtime.annotations.ConfigRoot;
5+
6+
@ConfigRoot
7+
public class ConsoleConfig {
8+
9+
/**
10+
* If test results and status should be displayed in the console.
11+
*
12+
* If this is false results can still be viewed in the dev console.
13+
*/
14+
@ConfigItem(defaultValue = "true")
15+
public boolean enabled;
16+
17+
/**
18+
* Disables the ability to enter input on the console.
19+
*
20+
*/
21+
@ConfigItem(defaultValue = "false")
22+
public boolean disableInput;
23+
/**
24+
* Disable the testing status/prompt message at the bottom of the console
25+
* and log these messages to STDOUT instead.
26+
*
27+
* Use this option if your terminal does not support ANSI escape sequences.
28+
*/
29+
@ConfigItem(defaultValue = "false")
30+
public boolean basic;
31+
32+
/**
33+
* Disable color in the testing status and prompt messages.
34+
*
35+
* Use this option if your terminal does not support color.
36+
*/
37+
@ConfigItem(defaultValue = "false")
38+
public boolean disableColor;
39+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.quarkus.deployment.dev;
2+
3+
import java.util.function.Consumer;
4+
5+
import io.quarkus.builder.item.SimpleBuildItem;
6+
7+
public final class BrowserOpenerBuildItem extends SimpleBuildItem {
8+
9+
private final Consumer<String> browserOpener;
10+
11+
public BrowserOpenerBuildItem(Consumer<String> browserOpener) {
12+
this.browserOpener = browserOpener;
13+
}
14+
15+
public Consumer<String> getBrowserOpener() {
16+
return browserOpener;
17+
}
18+
}

core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.util.function.Consumer;
2525
import java.util.function.Predicate;
2626

27+
import org.apache.maven.shared.utils.cli.CommandLineException;
28+
import org.apache.maven.shared.utils.cli.CommandLineUtils;
2729
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
2830
import org.jboss.logging.Logger;
2931

@@ -42,6 +44,7 @@
4244
import io.quarkus.deployment.CodeGenerator;
4345
import io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem;
4446
import io.quarkus.deployment.codegen.CodeGenData;
47+
import io.quarkus.deployment.dev.testing.MessageFormat;
4548
import io.quarkus.deployment.dev.testing.TestSupport;
4649
import io.quarkus.deployment.steps.ClassTransformingBuildStep;
4750
import io.quarkus.deployment.util.FSWatchUtil;
@@ -96,22 +99,58 @@ public void accept(Integer integer) {
9699
}
97100
final CountDownLatch latch = new CountDownLatch(1);
98101
QuarkusConsole.INSTANCE.pushInputHandler(new InputHandler() {
102+
ConsoleStatus promptHandler;
103+
StringBuilder reading;
104+
99105
@Override
100106
public void handleInput(int[] keys) {
107+
101108
for (int i : keys) {
102-
if (i == 'q') {
103-
System.exit(0);
109+
if (reading != null) {
110+
if (i == '\n') {
111+
try {
112+
context.setArgs(
113+
CommandLineUtils.translateCommandline(reading.toString()));
114+
reading = null;
115+
QuarkusConsole.INSTANCE.popInputHandler();
116+
latch.countDown();
117+
} catch (CommandLineException e) {
118+
log.error("Failed to parse command line", e);
119+
setRestartPrompt(promptHandler);
120+
reading = null;
121+
}
122+
} else {
123+
reading.append((char) i);
124+
}
104125
} else {
105-
QuarkusConsole.INSTANCE.popInputHandler();
106-
latch.countDown();
126+
if (i == 'q') {
127+
System.exit(0);
128+
} else if (i == 'e') {
129+
promptHandler.doReadLine();
130+
reading = new StringBuilder();
131+
break; //discard all further input
132+
} else {
133+
QuarkusConsole.INSTANCE.popInputHandler();
134+
latch.countDown();
135+
}
107136
}
108137
}
109138
}
110139

111140
@Override
112141
public void promptHandler(ConsoleStatus promptHandler) {
113-
promptHandler.setPrompt("\u001B[91mQuarkus application exited with code " + integer
114-
+ "\nPress [q] or Ctrl + C to quit, any other key to restart");
142+
this.promptHandler = promptHandler;
143+
promptHandler.setStatus("\u001B[91mQuarkus application exited with code " + integer
144+
+ MessageFormat.RESET);
145+
setRestartPrompt(promptHandler);
146+
}
147+
148+
private void setRestartPrompt(ConsoleStatus promptHandler) {
149+
promptHandler.setPrompt("Press [" + MessageFormat.BLUE + "q" + MessageFormat.RESET
150+
+ "] or Ctrl + C to quit, [" + MessageFormat.BLUE + "e" + MessageFormat.RESET
151+
+ "] to edit command line args (currently '" + MessageFormat.GREEN
152+
+ String.join(" ", context.getArgs()) + MessageFormat.RESET
153+
+ "'), or any other key to restart");
115154
}
116155
});
117156
try {

core/deployment/src/main/java/io/quarkus/deployment/dev/console/AeshConsole.java

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.util.concurrent.LinkedBlockingDeque;
44
import java.util.concurrent.locks.Lock;
55
import java.util.concurrent.locks.ReentrantLock;
6+
import java.util.regex.Matcher;
7+
import java.util.regex.Pattern;
68

79
import org.aesh.terminal.Attributes;
810
import org.aesh.terminal.Connection;
@@ -22,6 +24,8 @@ public class AeshConsole extends QuarkusConsole {
2224
private String[] messages = new String[0];
2325
private int totalStatusLines = 0;
2426
private int lastWriteCursorX;
27+
private String lastColorCode; //foreground color code, or reset
28+
private volatile boolean doingReadline;
2529
/**
2630
* if the status area has gotten big then small again
2731
* this tracks how many lines of blank space we have
@@ -45,6 +49,8 @@ protected Boolean initialValue() {
4549
}
4650
};
4751

52+
static final Pattern ESCAPE = Pattern.compile("\u001b\\[(\\d\\d?)[\\d;]*m");
53+
4854
public AeshConsole(Connection connection, boolean inputSupport) {
4955
this.inputSupport = inputSupport;
5056
INSTANCE = this;
@@ -179,6 +185,14 @@ public void run() {
179185
if (handler != null) {
180186
handler.handler.handleInput(keys);
181187
}
188+
if (doingReadline) {
189+
for (var k : keys) {
190+
if (k == '\n') {
191+
doingReadline = false;
192+
connection.enterRawMode();
193+
}
194+
}
195+
}
182196
});
183197
}
184198
conn.setCloseHandler(close -> end(conn));
@@ -235,7 +249,7 @@ private void printStatusAndPrompt(StringBuilder buffer) {
235249
}
236250

237251
private void clearStatusMessages(StringBuilder buffer) {
238-
gotoLine(buffer, size.getHeight() - totalStatusLines);
252+
gotoLine(buffer, size.getHeight() - totalStatusLines + 1);
239253
buffer.append("\033[J");
240254
}
241255

@@ -270,6 +284,19 @@ public void write(String s) {
270284
if (IN_WRITE.get()) {
271285
return;
272286
}
287+
if (lastColorCode != null) {
288+
s = lastColorCode + s;
289+
}
290+
Matcher m = ESCAPE.matcher(s);
291+
while (m.find()) {
292+
int val = Integer.parseInt(m.group(1));
293+
if (val == 0 || //reset
294+
(val >= 30 && val <= 39) || //foreground colors
295+
(val >= 90 && val <= 97)) { //bright foreground colors
296+
lastColorCode = m.group(0);
297+
}
298+
}
299+
273300
StringBuilder buffer = new StringBuilder();
274301
synchronized (this) {
275302
if (outputFilter != null) {
@@ -320,7 +347,8 @@ public void write(String s) {
320347
int appendLines = Math.max(Math.min(cursorPos > 1 ? lines - 1 : lines, totalStatusLines), 1);
321348
appendLines -= usedBlankSpace;
322349
clearStatusMessages(buffer);
323-
buffer.append("\033[").append(size.getHeight() - totalStatusLines - originalBlank).append(";").append(0)
350+
buffer.append("\033[").append(size.getHeight() - totalStatusLines - originalBlank).append(";")
351+
.append(lastWriteCursorX)
324352
.append("H");
325353
buffer.append(s);
326354
buffer.append("\033[").append(size.getHeight()).append(";").append(0).append("H");
@@ -367,8 +395,17 @@ protected void setCompileErrorMessage(String results) {
367395
@Override
368396
protected void setStatusMessage(String status) {
369397
setMessage(2, status);
370-
371398
}
372399

400+
@Override
401+
public void doReadLine() {
402+
if (!inputSupport) {
403+
return;
404+
}
405+
setPrompt("");
406+
connection.setAttributes(attributes);
407+
doingReadline = true;
408+
409+
}
373410
}
374411
}

core/deployment/src/main/java/io/quarkus/deployment/dev/console/ConsoleHelper.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,41 @@
66
import org.aesh.readline.tty.terminal.TerminalConnection;
77
import org.aesh.terminal.Connection;
88

9+
import io.quarkus.deployment.ConsoleConfig;
910
import io.quarkus.deployment.dev.testing.TestConfig;
1011
import io.quarkus.dev.console.BasicConsole;
1112
import io.quarkus.dev.console.QuarkusConsole;
1213
import io.quarkus.dev.console.RedirectPrintStream;
1314

1415
public class ConsoleHelper {
1516

16-
public static synchronized void installConsole(TestConfig config) {
17+
public static synchronized void installConsole(TestConfig config, ConsoleConfig consoleConfig) {
1718
if (QuarkusConsole.installed) {
1819
return;
1920
}
2021
QuarkusConsole.installed = true;
21-
if (config.basicConsole) {
22-
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, !config.disableConsoleInput, System.out);
22+
if (config.basicConsole.orElse(consoleConfig.basic)) {
23+
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor.orElse(consoleConfig.disableColor),
24+
!config.disableConsoleInput.orElse(consoleConfig.disableInput), System.out);
2325
} else {
2426
try {
2527
new TerminalConnection(new Consumer<Connection>() {
2628
@Override
2729
public void accept(Connection connection) {
2830
if (connection.supportsAnsi()) {
29-
QuarkusConsole.INSTANCE = new AeshConsole(connection, !config.disableConsoleInput);
31+
QuarkusConsole.INSTANCE = new AeshConsole(connection,
32+
!config.disableConsoleInput.orElse(consoleConfig.disableInput));
3033
} else {
3134
connection.close();
32-
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, !config.disableConsoleInput,
35+
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor.orElse(consoleConfig.disableColor),
36+
!config.disableConsoleInput.orElse(consoleConfig.disableInput),
3337
System.out);
3438
}
3539
}
3640
});
3741
} catch (IOException e) {
38-
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor, !config.disableConsoleInput, System.out);
42+
QuarkusConsole.INSTANCE = new BasicConsole(config.disableColor.orElse(consoleConfig.disableColor),
43+
!config.disableConsoleInput.orElse(consoleConfig.disableInput), System.out);
3944
}
4045
}
4146
RedirectPrintStream ps = new RedirectPrintStream();
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.quarkus.deployment.dev.testing;
2+
3+
public class MessageFormat {
4+
5+
public static final String RED = "\u001B[91m";
6+
public static final String GREEN = "\u001b[32m";
7+
public static final String BLUE = "\u001b[34m";
8+
public static final String RESET = "\u001b[39m";
9+
10+
private MessageFormat() {
11+
}
12+
13+
public static String statusHeader(String header) {
14+
return RESET + "==================== " + header + RESET + " ====================";
15+
}
16+
17+
public static String statusFooter(String footer) {
18+
return RESET + ">>>>>>>>>>>>>>>>>>>> " + footer + RESET + " <<<<<<<<<<<<<<<<<<<<";
19+
}
20+
21+
public static String toggleStatus(boolean enabled) {
22+
return " (" + (enabled ? GREEN + "enabled" + RESET + "" : RED + "disabled") + RESET + ")";
23+
}
24+
25+
public static String helpOption(String key, String description) {
26+
return "[" + BLUE + key + RESET + "] - " + description;
27+
}
28+
29+
public static String helpOption(String key, String description, boolean enabled) {
30+
return helpOption(key, description) + toggleStatus(enabled);
31+
}
32+
33+
}

core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConfig.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,37 +71,49 @@ public class TestConfig {
7171
*/
7272
@ConfigItem(defaultValue = ".*\\.IT[^.]+|.*IT|.*ITCase")
7373
public Optional<String> excludePattern;
74+
7475
/**
7576
* Disable the testing status/prompt message at the bottom of the console
7677
* and log these messages to STDOUT instead.
7778
*
7879
* Use this option if your terminal does not support ANSI escape sequences.
80+
*
81+
* This is deprecated, {@literal quarkus.console.basic} should be used instead.
7982
*/
80-
@ConfigItem(defaultValue = "false")
81-
public boolean basicConsole;
83+
@Deprecated
84+
@ConfigItem
85+
public Optional<Boolean> basicConsole;
8286

8387
/**
8488
* Disable color in the testing status and prompt messages.
8589
*
8690
* Use this option if your terminal does not support color.
91+
*
92+
* This is deprecated, {@literal quarkus.console.disable-color} should be used instead.
8793
*/
88-
@ConfigItem(defaultValue = "false")
89-
public boolean disableColor;
94+
@ConfigItem
95+
@Deprecated
96+
public Optional<Boolean> disableColor;
9097

9198
/**
9299
* If test results and status should be displayed in the console.
93100
*
94101
* If this is false results can still be viewed in the dev console.
102+
*
103+
* This is deprecated, {@literal quarkus.console.enabled} should be used instead.
95104
*/
96-
@ConfigItem(defaultValue = "true")
97-
public boolean console;
105+
@Deprecated
106+
@ConfigItem
107+
public Optional<Boolean> console;
98108

99109
/**
100110
* Disables the ability to enter input on the console.
101111
*
112+
* This is deprecated, {@literal quarkus.console.disable-input} should be used instead.
102113
*/
103-
@ConfigItem(defaultValue = "false")
104-
public boolean disableConsoleInput;
114+
@ConfigItem
115+
@Deprecated
116+
public Optional<Boolean> disableConsoleInput;
105117

106118
/**
107119
* Changes tests to use the 'flat' ClassPath used in Quarkus 1.x versions.

0 commit comments

Comments
 (0)