8332314: Add window size configuration option to JavaShellToolBuilder interface

Reviewed-by: jlahoda
This commit is contained in:
Archie Cobbs 2024-06-21 10:44:51 +00:00 committed by Jan Lahoda
parent 711e723819
commit 08ace27da1
4 changed files with 45 additions and 11 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -121,7 +121,7 @@ class ConsoleIOContext extends IOContext {
String prefix = ""; String prefix = "";
ConsoleIOContext(JShellTool repl, InputStream cmdin, PrintStream cmdout, ConsoleIOContext(JShellTool repl, InputStream cmdin, PrintStream cmdout,
boolean interactive) throws Exception { boolean interactive, Size size) throws Exception {
this.repl = repl; this.repl = repl;
Map<String, Object> variables = new HashMap<>(); Map<String, Object> variables = new HashMap<>();
this.input = new StopDetectingInputStream(() -> repl.stop(), this.input = new StopDetectingInputStream(() -> repl.stop(),
@ -143,7 +143,6 @@ class ConsoleIOContext extends IOContext {
terminal = new TestTerminal(nonBlockingInput, cmdout); terminal = new TestTerminal(nonBlockingInput, cmdout);
enableHighlighter = Boolean.getBoolean("test.enable.highlighter"); enableHighlighter = Boolean.getBoolean("test.enable.highlighter");
} else { } else {
Size size = null;
terminal = new ProgrammaticInTerminal(nonBlockingInput, cmdout, interactive, terminal = new ProgrammaticInTerminal(nonBlockingInput, cmdout, interactive,
size); size);
if (!interactive) { if (!interactive) {
@ -1312,6 +1311,7 @@ class ConsoleIOContext extends IOContext {
private static class ProgrammaticInTerminal extends LineDisciplineTerminal { private static class ProgrammaticInTerminal extends LineDisciplineTerminal {
protected static final int DEFAULT_WIDTH = 80;
protected static final int DEFAULT_HEIGHT = 24; protected static final int DEFAULT_HEIGHT = 24;
private final NonBlockingReader inputReader; private final NonBlockingReader inputReader;
@ -1320,9 +1320,9 @@ class ConsoleIOContext extends IOContext {
public ProgrammaticInTerminal(InputStream input, OutputStream output, public ProgrammaticInTerminal(InputStream input, OutputStream output,
boolean interactive, Size size) throws Exception { boolean interactive, Size size) throws Exception {
this(input, output, interactive ? "ansi" : "dumb", this(input, output, interactive ? "ansi" : "dumb",
size != null ? size : new Size(80, DEFAULT_HEIGHT), size != null ? size : new Size(DEFAULT_WIDTH, DEFAULT_HEIGHT),
size != null ? size size != null ? size
: interactive ? new Size(80, DEFAULT_HEIGHT) : interactive ? new Size(DEFAULT_WIDTH, DEFAULT_HEIGHT)
: new Size(Integer.MAX_VALUE - 1, DEFAULT_HEIGHT)); : new Size(Integer.MAX_VALUE - 1, DEFAULT_HEIGHT));
} }
@ -1366,7 +1366,7 @@ class ConsoleIOContext extends IOContext {
} catch (Throwable ex) { } catch (Throwable ex) {
// ignore // ignore
} }
return new Size(80, h); return new Size(DEFAULT_WIDTH, h);
} }
public TestTerminal(InputStream input, OutputStream output) throws Exception { public TestTerminal(InputStream input, OutputStream output) throws Exception {
this(input, output, computeSize()); this(input, output, computeSize());

View File

@ -80,6 +80,7 @@ import java.util.stream.StreamSupport;
import jdk.internal.jshell.debug.InternalDebugControl; import jdk.internal.jshell.debug.InternalDebugControl;
import jdk.internal.jshell.tool.IOContext.InputInterruptedException; import jdk.internal.jshell.tool.IOContext.InputInterruptedException;
import jdk.internal.org.jline.terminal.Size;
import jdk.jshell.DeclarationSnippet; import jdk.jshell.DeclarationSnippet;
import jdk.jshell.Diag; import jdk.jshell.Diag;
import jdk.jshell.EvalException; import jdk.jshell.EvalException;
@ -166,6 +167,7 @@ public class JShellTool implements MessageHandler {
final Map<String, String> envvars; final Map<String, String> envvars;
final Locale locale; final Locale locale;
final boolean interactiveTerminal; final boolean interactiveTerminal;
final Size windowSize;
final Feedback feedback = new Feedback(); final Feedback feedback = new Feedback();
@ -181,12 +183,13 @@ public class JShellTool implements MessageHandler {
* @param prefs persistence implementation to use * @param prefs persistence implementation to use
* @param envvars environment variable mapping to use * @param envvars environment variable mapping to use
* @param locale locale to use * @param locale locale to use
* @param windowSize window size hint, or null
*/ */
JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr, JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr,
PrintStream console, PrintStream console,
InputStream userin, PrintStream userout, PrintStream usererr, InputStream userin, PrintStream userout, PrintStream usererr,
PersistentStorage prefs, Map<String, String> envvars, Locale locale, PersistentStorage prefs, Map<String, String> envvars, Locale locale,
boolean interactiveTerminal) { boolean interactiveTerminal, Size windowSize) {
this.cmdin = cmdin; this.cmdin = cmdin;
this.cmdout = cmdout; this.cmdout = cmdout;
this.cmderr = cmderr; this.cmderr = cmderr;
@ -203,6 +206,7 @@ public class JShellTool implements MessageHandler {
this.envvars = envvars; this.envvars = envvars;
this.locale = locale; this.locale = locale;
this.interactiveTerminal = interactiveTerminal; this.interactiveTerminal = interactiveTerminal;
this.windowSize = windowSize;
} }
private ResourceBundle versionRB = null; private ResourceBundle versionRB = null;
@ -998,7 +1002,7 @@ public class JShellTool implements MessageHandler {
}; };
Runtime.getRuntime().addShutdownHook(shutdownHook); Runtime.getRuntime().addShutdownHook(shutdownHook);
// execute from user input // execute from user input
try (IOContext in = new ConsoleIOContext(this, cmdin, console, interactiveTerminal)) { try (IOContext in = new ConsoleIOContext(this, cmdin, console, interactiveTerminal, windowSize)) {
int indent; int indent;
try { try {
String indentValue = indent(); String indentValue = indent();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -33,6 +33,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.prefs.BackingStoreException; import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import jdk.internal.org.jline.terminal.Size;
import jdk.jshell.tool.JavaShellToolBuilder; import jdk.jshell.tool.JavaShellToolBuilder;
/** /**
@ -53,6 +54,7 @@ public class JShellToolBuilder implements JavaShellToolBuilder {
private Locale locale = Locale.getDefault(); private Locale locale = Locale.getDefault();
private boolean interactiveTerminal; private boolean interactiveTerminal;
private boolean capturePrompt = false; private boolean capturePrompt = false;
private Size windowSize = null;
/** /**
* Set the input channels. * Set the input channels.
@ -215,6 +217,16 @@ public class JShellToolBuilder implements JavaShellToolBuilder {
return this; return this;
} }
@Override
public JavaShellToolBuilder windowSize(int columns, int rows) {
if (columns <= 0)
throw new IllegalArgumentException("columns = " + columns);
if (rows <= 0)
throw new IllegalArgumentException("rows = " + rows);
this.windowSize = new Size(columns, rows);
return this;
}
/** /**
* Create a tool instance for testing. Not in JavaShellToolBuilder. * Create a tool instance for testing. Not in JavaShellToolBuilder.
* *
@ -228,7 +240,7 @@ public class JShellToolBuilder implements JavaShellToolBuilder {
vars = System.getenv(); vars = System.getenv();
} }
JShellTool sh = new JShellTool(cmdIn, cmdOut, cmdErr, console, userIn, JShellTool sh = new JShellTool(cmdIn, cmdOut, cmdErr, console, userIn,
userOut, userErr, prefs, vars, locale, interactiveTerminal); userOut, userErr, prefs, vars, locale, interactiveTerminal, windowSize);
sh.testPrompt = capturePrompt; sh.testPrompt = capturePrompt;
return sh; return sh;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -209,6 +209,24 @@ public interface JavaShellToolBuilder {
return this; return this;
} }
/**
* Provide a hint of the display window's dimensions when using an interactive terminal.
*
* <p>
* When the input stream for this Java Shell is {@code System.in}, this setting is ignored.
*
* @implSpec Implementations may choose to ignore this method. The default implementation
* of this method returns {@code this}.
*
* @param columns number of displayed columns
* @param rows number of displayed rows
* @return the {@code JavaShellToolBuilder} instance
* @since 24
*/
default JavaShellToolBuilder windowSize(int columns, int rows) {
return this;
}
/** /**
* Run an instance of the Java shell tool as configured by the other methods * Run an instance of the Java shell tool as configured by the other methods
* in this interface. This call is not destructive, more than one call of * in this interface. This call is not destructive, more than one call of