Skip to content

Commit 55abe44

Browse files
committed
Support clear screen in web console. Fix clearing screen starts new session (fixes #66)
1 parent b9eb480 commit 55abe44

File tree

8 files changed

+96
-42
lines changed

8 files changed

+96
-42
lines changed

src/javarepl/Main.java

+52-17
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package javarepl;
22

3-
import com.googlecode.totallylazy.Exceptions;
3+
import com.googlecode.totallylazy.Lists;
44
import com.googlecode.totallylazy.Option;
55
import com.googlecode.totallylazy.Sequence;
66
import com.googlecode.totallylazy.Strings;
77
import com.googlecode.totallylazy.functions.Function1;
8+
import javarepl.client.EvaluationLog;
89
import javarepl.client.EvaluationResult;
910
import javarepl.client.JavaREPLClient;
1011
import javarepl.completion.CompletionCandidate;
1112
import javarepl.completion.CompletionResult;
12-
import jline.Terminal;
13-
import jline.TerminalFactory;
1413
import jline.console.ConsoleReader;
1514
import jline.console.CursorBuffer;
1615
import jline.console.completer.CandidateListCompletionHandler;
@@ -24,8 +23,8 @@
2423
import java.nio.file.Files;
2524
import java.util.*;
2625

27-
import static com.googlecode.totallylazy.Exceptions.captureException;
2826
import static com.googlecode.totallylazy.Files.fileOption;
27+
import static com.googlecode.totallylazy.Lists.list;
2928
import static com.googlecode.totallylazy.Option.none;
3029
import static com.googlecode.totallylazy.Option.some;
3130
import static com.googlecode.totallylazy.Sequences.empty;
@@ -38,11 +37,13 @@
3837
import static com.googlecode.totallylazy.predicates.Not.not;
3938
import static java.lang.String.format;
4039
import static java.lang.System.getProperty;
41-
import static java.util.Arrays.asList;
40+
import static java.util.Collections.singletonList;
4241
import static javarepl.Utils.applicationVersion;
4342
import static javarepl.Utils.randomServerPort;
43+
import static javarepl.client.EvaluationLog.Type.CONTROL;
4444
import static javarepl.completion.CompletionResult.methods.fromJson;
4545
import static javarepl.completion.CompletionResult.methods.toJson;
46+
import static javarepl.console.commands.ClearScreen.CLEAR_SCREEN_CMD;
4647
import static javax.tools.ToolProvider.getSystemJavaCompiler;
4748

4849
public class Main {
@@ -53,9 +54,10 @@ public class Main {
5354
public static void main(String... args) throws Exception {
5455
console = new ResultPrinter(printColors(args));
5556

56-
Sequence<String> initialExpressions = initialExpressionsFromFile().join(initialExpressionsFromArgs(args));
57+
ConsoleReader consoleReader = new ConsoleReader(System.in, AnsiConsole.out);
5758
JavaREPLClient client = clientFor(hostname(args), port(args));
58-
ExpressionReader expressionReader = expressionReaderFor(client, initialExpressions);
59+
Sequence<String> initialExpressions = initialExpressionsFromFile().join(initialExpressionsFromArgs(args));
60+
ExpressionReader expressionReader = expressionReaderFor(consoleReader, client, initialExpressions);
5961

6062
Option<String> expression = none();
6163
Option<EvaluationResult> result = none();
@@ -64,17 +66,48 @@ public static void main(String... args) throws Exception {
6466

6567
if (!expression.isEmpty()) {
6668
result = client.execute(expression.get());
67-
if (!result.isEmpty())
68-
console.printEvaluationResult(result.get());
69+
if (!result.isEmpty()) {
70+
for (EvaluationLog log : result.get().logs()) {
71+
if (!handleTerminalCommand(log)) {
72+
handleTerminalMessage(log);
73+
}
74+
}
75+
}
6976
}
7077
}
7178
}
7279

73-
private static JavaREPLClient clientFor(Option<String> hostname, Option<Integer> port) throws Exception {
74-
console.printInfo(format("Welcome to JavaREPL version %s (%s, Java %s)",
80+
private static void handleTerminalMessage(EvaluationLog log) {
81+
console.printEvaluationLog(log);
82+
}
83+
84+
private static boolean handleTerminalCommand(EvaluationLog log) {
85+
if (log.type().equals(CONTROL)){
86+
switch (log.message()) {
87+
case CLEAR_SCREEN_CMD: {
88+
console.printInfo("\033c");
89+
console.printInfo(welcomeMessage());
90+
console.printInfo(welcomeInstructions());
91+
} break;
92+
93+
default: return false;
94+
}
95+
return true;
96+
}
97+
return false;
98+
}
99+
100+
101+
102+
private static String welcomeMessage() {
103+
return format("Welcome to JavaREPL version %s (%s, Java %s)",
75104
applicationVersion(),
76105
getProperty("java.vm.name"),
77-
getProperty("java.version")));
106+
getProperty("java.version"));
107+
}
108+
109+
private static JavaREPLClient clientFor(Option<String> hostname, Option<Integer> port) throws Exception {
110+
console.printInfo(welcomeMessage());
78111

79112
if (hostname.isEmpty() && port.isEmpty()) {
80113
return startNewLocalInstance("localhost", randomServerPort());
@@ -108,7 +141,7 @@ private static JavaREPLClient startNewLocalInstance(String hostname, Integer por
108141
System.exit(0);
109142
}
110143

111-
console.printInfo("Type expression to evaluate, \u001B[32m:help\u001B[0m for more options or press \u001B[32mtab\u001B[0m to auto-complete.");
144+
console.printInfo(welcomeInstructions());
112145

113146
ProcessBuilder builder = new ProcessBuilder("java", "-cp", System.getProperty("java.class.path"), Repl.class.getCanonicalName(), "--port=" + port);
114147
builder.redirectErrorStream(true);
@@ -130,6 +163,10 @@ public void run() {
130163
return replClient;
131164
}
132165

166+
private static String welcomeInstructions() {
167+
return "Type expression to evaluate, \u001B[32m:help\u001B[0m for more options or press \u001B[32mtab\u001B[0m to auto-complete.";
168+
}
169+
133170
private static boolean waitUntilInstanceStarted(JavaREPLClient client) throws Exception {
134171
for (int i = 0; i < 500; i++) {
135172
Thread.sleep(10);
@@ -169,15 +206,13 @@ private static Boolean printColors(String[] args) {
169206
return !sequence(args).contains("--noColors");
170207
}
171208

172-
private static ExpressionReader expressionReaderFor(final JavaREPLClient client, Sequence<String> initialExpressions) throws IOException {
209+
private static ExpressionReader expressionReaderFor(ConsoleReader consoleReader, final JavaREPLClient client, Sequence<String> initialExpressions) throws IOException {
173210
return new ExpressionReader(new Function1<Sequence<String>, String>() {
174211
private static final char CTRL_C = (char) 3;
175212
private static final char CTRL_D = (char) 4;
176-
private final ConsoleReader consoleReader;
177213
private Sequence<String> expressions = initialExpressions;
178214

179215
{
180-
consoleReader = new ConsoleReader(System.in, AnsiConsole.out);
181216
consoleReader.setCompletionHandler(new JlineCompletionHandler());
182217
consoleReader.setHistoryEnabled(true);
183218
consoleReader.setExpandEvents(false);
@@ -213,7 +248,7 @@ private jline.console.completer.Completer clientCompleter() {
213248
return (expression, cursor, candidates) -> {
214249
try {
215250
CompletionResult result = client.completions(expression);
216-
candidates.addAll(asList(toJson(result)));
251+
candidates.addAll(singletonList(toJson(result)));
217252
return result.candidates().isEmpty() ? -1 : result.position();
218253
} catch (Exception e) {
219254
return -1;

src/javarepl/ResultPrinter.java

-6
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@ public void printInfo(String message) {
2323
AnsiConsole.out.println(ansiColored(message));
2424
}
2525

26-
public void printEvaluationResult(EvaluationResult result) {
27-
for (EvaluationLog log : result.logs()) {
28-
printEvaluationLog(log);
29-
}
30-
}
31-
3226
public void printEvaluationLog(EvaluationLog log) {
3327
switch (log.type()) {
3428
case INFO:

src/javarepl/client/EvaluationLog.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
public class EvaluationLog {
44
public static enum Type {
5-
INFO, SUCCESS, ERROR;
5+
INFO, SUCCESS, ERROR, CONTROL;
66

77
public static Type type(String type) {
88
return valueOf(type);

src/javarepl/console/ConsoleLog.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
public class ConsoleLog {
66
public static enum Type {
7-
INFO, SUCCESS, ERROR
7+
INFO, SUCCESS, ERROR, CONTROL
88
}
99

1010
private final Type type;
@@ -15,6 +15,10 @@ private ConsoleLog(Type type, String message) {
1515
this.message = message;
1616
}
1717

18+
public static ConsoleLog control(String message) {
19+
return consoleLog(CONTROL, message);
20+
}
21+
1822
public static ConsoleLog success(String message) {
1923
return consoleLog(SUCCESS, message);
2024
}

src/javarepl/console/ConsoleLogger.java

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ public void info(String message) {
2929
log(ConsoleLog.info(message));
3030
}
3131

32+
public void control(String message) {
33+
log(ConsoleLog.control(message));
34+
}
35+
3236
public void success(String message) {
3337
log(ConsoleLog.success(message));
3438
}
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
package javarepl.console.commands;
22

3-
import javarepl.Evaluator;
43
import javarepl.completion.CommandCompleter;
54
import javarepl.console.ConsoleLogger;
65

7-
import static com.googlecode.totallylazy.predicates.Predicates.equalTo;
6+
import static com.googlecode.totallylazy.Strings.startsWith;
87

98
public final class ClearScreen extends Command {
9+
public static final String CLEAR_SCREEN_CMD = "CLEAR_SCREEN";
1010
private static final String COMMAND = ":cls";
11-
private final Evaluator evaluator;
1211
private final ConsoleLogger logger;
1312

14-
public ClearScreen(Evaluator evaluator, ConsoleLogger logger) {
15-
super(COMMAND + " - clear screen", equalTo(COMMAND).or(equalTo(null)), new CommandCompleter(COMMAND));
16-
this.evaluator = evaluator;
13+
public ClearScreen(ConsoleLogger logger) {
14+
super(COMMAND + " - clears screen", startsWith(COMMAND), new CommandCompleter(COMMAND));
1715
this.logger = logger;
1816
}
1917

2018
public void execute(String expression) {
2119
this.logger.reset();
22-
this.logger.info("\033[2J");
20+
this.logger.control(CLEAR_SCREEN_CMD);
2321
}
2422
}

src/javarepl/console/rest/RestConsoleResource.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public Map<String, Object> execute(@FormParam("expression") String expr) {
4848

4949
return emptyMap(String.class, Object.class)
5050
.insert("expression", result.expression())
51-
.insert("logs", result.logs().map(commandResultToModel()));
51+
.insert("logs", result.logs().map(toCommandResultMap()));
5252
}
5353

5454
@POST
@@ -86,7 +86,7 @@ public Map<String, Object> history() {
8686
.insert("history", console.history().items().toList());
8787
}
8888

89-
private static Function1<ConsoleLog, Map<String, Object>> commandResultToModel() {
89+
private static Function1<ConsoleLog, Map<String, Object>> toCommandResultMap() {
9090
return consoleLog -> emptyMap(String.class, Object.class)
9191
.insert("type", consoleLog.type())
9292
.insert("message", consoleLog.message());

src/javarepl/web/term.js

+27-8
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,30 @@ function echoCompletionCandidates(term, candidates) {
125125
term.echo(layoutCompletions(candidates, term.width() / 8));
126126
}
127127

128+
function handleTerminalCommand(log, term) {
129+
if (log.type == "CONTROL") {
130+
switch (log.message) {
131+
case "CLEAR_SCREEN":
132+
term.clear();
133+
term.echo(session.welcomeMessage);
134+
term.echo(' ');
135+
break;
136+
}
137+
return true;
138+
}
139+
return false;
140+
}
141+
142+
function handleTerminalMessage(log, term) {
143+
if (log.type != "CONTROL") {
144+
var style = log.type == "ERROR" ? "terminal-message-error" : "terminal-message-success";
145+
term.echo(log.message, messageStyle(style))
146+
return log.type == "ERROR";
147+
}
148+
return false;
149+
}
150+
151+
128152
$(document).ready(function () {
129153
jQuery(function ($, undefined) {
130154
createNewSession(getParam("expression"), getParam("snap"));
@@ -146,16 +170,11 @@ $(document).ready(function () {
146170
data: {id: session.clientId, expression: expression}
147171
}).done(function (data) {
148172
var hadError = false;
149-
150173
for (var i = 0; i < data.logs.length; i++) {
151-
var style = data.logs[i].type == "ERROR" ? "terminal-message-error" : "terminal-message-success";
152-
153-
if (data.logs[i].type == "ERROR") {
154-
hadError = true;
155-
174+
var log = data.logs[i];
175+
if (!handleTerminalCommand(log, term)) {
176+
hadError = handleTerminalMessage(log, term) || hadError;
156177
}
157-
158-
term.echo(data.logs[i].message, messageStyle(style))
159178
}
160179

161180
if (!hadError) {

0 commit comments

Comments
 (0)