8158738: jshell tool: Save does not affect jshell if started from another editor
Reviewed-by: jlahoda
This commit is contained in:
parent
61fab7c849
commit
0b92f87233
langtools
src/jdk.jshell/share/classes/jdk/internal/jshell/tool
test/jdk/jshell
@ -34,6 +34,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.WatchKey;
|
||||
import java.nio.file.WatchService;
|
||||
import java.util.Arrays;
|
||||
import java.util.Scanner;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
|
||||
@ -46,17 +47,22 @@ import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
|
||||
public class ExternalEditor {
|
||||
private final Consumer<String> errorHandler;
|
||||
private final Consumer<String> saveHandler;
|
||||
private final Consumer<String> printHandler;
|
||||
private final IOContext input;
|
||||
private final boolean wait;
|
||||
|
||||
private WatchService watcher;
|
||||
private Thread watchedThread;
|
||||
private Path dir;
|
||||
private Path tmpfile;
|
||||
|
||||
ExternalEditor(Consumer<String> errorHandler, Consumer<String> saveHandler, IOContext input) {
|
||||
ExternalEditor(Consumer<String> errorHandler, Consumer<String> saveHandler,
|
||||
IOContext input, boolean wait, Consumer<String> printHandler) {
|
||||
this.errorHandler = errorHandler;
|
||||
this.saveHandler = saveHandler;
|
||||
this.printHandler = printHandler;
|
||||
this.input = input;
|
||||
this.wait = wait;
|
||||
}
|
||||
|
||||
private void edit(String[] cmd, String initialText) {
|
||||
@ -121,7 +127,16 @@ public class ExternalEditor {
|
||||
try {
|
||||
input.suspend();
|
||||
Process process = pb.start();
|
||||
process.waitFor();
|
||||
// wait to exit edit mode in one of these ways...
|
||||
if (wait) {
|
||||
// -wait option -- ignore process exit, wait for carriage-return
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
printHandler.accept("jshell.msg.press.return.to.leave.edit.mode");
|
||||
scanner.nextLine();
|
||||
} else {
|
||||
// wait for process to exit
|
||||
process.waitFor();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
errorHandler.accept("process IO failure: " + ex.getMessage());
|
||||
} catch (InterruptedException ex) {
|
||||
@ -148,8 +163,8 @@ public class ExternalEditor {
|
||||
}
|
||||
|
||||
static void edit(String[] cmd, Consumer<String> errorHandler, String initialText,
|
||||
Consumer<String> saveHandler, IOContext input) {
|
||||
ExternalEditor ed = new ExternalEditor(errorHandler, saveHandler, input);
|
||||
Consumer<String> saveHandler, IOContext input, boolean wait, Consumer<String> printHandler) {
|
||||
ExternalEditor ed = new ExternalEditor(errorHandler, saveHandler, input, wait, printHandler);
|
||||
ed.edit(cmd, initialText);
|
||||
}
|
||||
}
|
||||
|
@ -185,6 +185,7 @@ public class JShellTool implements MessageHandler {
|
||||
private String cmdlineClasspath = null;
|
||||
private String startup = null;
|
||||
private String[] editor = null;
|
||||
private boolean editorWait = false;
|
||||
|
||||
// Commands and snippets which should be replayed
|
||||
private List<String> replayableHistory;
|
||||
@ -481,6 +482,11 @@ public class JShellTool implements MessageHandler {
|
||||
if (editorString == null || editorString.isEmpty()) {
|
||||
editor = null;
|
||||
} else {
|
||||
char waitMarker = editorString.charAt(0);
|
||||
if (waitMarker == '-' || waitMarker == '*') {
|
||||
editorWait = waitMarker == '-';
|
||||
editorString = editorString.substring(1);
|
||||
}
|
||||
editor = editorString.split(RECORD_SEPARATOR);
|
||||
}
|
||||
|
||||
@ -1260,7 +1266,7 @@ public class JShellTool implements MessageHandler {
|
||||
// retain editor setting
|
||||
prefs.put(EDITOR_KEY, (editor == null)
|
||||
? ""
|
||||
: String.join(RECORD_SEPARATOR, editor));
|
||||
: (editorWait? "-" : "*") + String.join(RECORD_SEPARATOR, editor));
|
||||
return true;
|
||||
case "start": {
|
||||
if (!setStart(cmd, at, false)) {
|
||||
@ -1315,7 +1321,7 @@ public class JShellTool implements MessageHandler {
|
||||
|
||||
// The sub-command: /set editor <editor-command-line>>
|
||||
boolean setEditor(ArgTokenizer at, boolean argsRequired) {
|
||||
at.allowedOptions("-default");
|
||||
at.allowedOptions("-default", "-wait");
|
||||
String prog = at.next();
|
||||
List<String> ed = new ArrayList<>();
|
||||
while (at.val() != null) {
|
||||
@ -1326,14 +1332,20 @@ public class JShellTool implements MessageHandler {
|
||||
return false;
|
||||
}
|
||||
boolean defaultOption = at.hasOption("-default");
|
||||
boolean waitOption = at.hasOption("-wait");
|
||||
if (prog != null) {
|
||||
if (defaultOption) {
|
||||
errormsg("jshell.err.default.option.or.program", at.whole());
|
||||
return false;
|
||||
}
|
||||
editor = ed.toArray(new String[ed.size()]);
|
||||
editorWait = waitOption;
|
||||
fluffmsg("jshell.msg.set.editor.set", prog);
|
||||
} else if (defaultOption) {
|
||||
if (waitOption) {
|
||||
errormsg("jshell.err.wait.applies.to.external.editor", at.whole());
|
||||
return false;
|
||||
}
|
||||
editor = null;
|
||||
} else if (argsRequired) {
|
||||
errormsg("jshell.err.set.editor.arg");
|
||||
@ -1720,7 +1732,8 @@ public class JShellTool implements MessageHandler {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ExternalEditor.edit(editor, errorHandler, src, saveHandler, input);
|
||||
ExternalEditor.edit(editor, errorHandler, src, saveHandler, input,
|
||||
editorWait, this::hardrb);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -56,6 +56,8 @@ jshell.err.set.editor.arg = The ''/set editor'' command requires a path argument
|
||||
jshell.msg.set.editor.set = Editor set to: {0}
|
||||
jshell.err.cant.launch.editor = Cannot launch editor -- unexpected exception: {0}
|
||||
jshell.msg.try.set.editor = Try /set editor to use external editor.
|
||||
jshell.msg.press.return.to.leave.edit.mode = Press return to leave edit mode.
|
||||
jshell.err.wait.applies.to.external.editor = -wait applies to external editors, cannot be used with -default
|
||||
|
||||
jshell.msg.try.command.without.args = Try ''{0}'' without arguments.
|
||||
jshell.msg.no.active = There are no active definitions.
|
||||
@ -358,7 +360,7 @@ Set jshell configuration information, including:\n\
|
||||
the external editor to use, the start-up definitions to use, a new feedback mode,\n\
|
||||
the command prompt, the feedback mode to use, or the format of output.\n\
|
||||
\n\
|
||||
/set editor <command> <optional-arg>...\n\t\
|
||||
/set editor [-wait] <command> <optional-arg>...\n\t\
|
||||
Specify the command to launch for the /edit command.\n\t\
|
||||
The <command> is an operating system dependent string.\n\n\
|
||||
/set start <file>\n\t\
|
||||
@ -602,12 +604,19 @@ The continuation-prompt is used on the second and subsequent lines of a multi-li
|
||||
help.set.editor =\
|
||||
Specify the command to launch for the /edit command.\n\
|
||||
\n\t\
|
||||
/set editor <command>|-default\n\
|
||||
/set editor [-wait] <command>|-default\n\
|
||||
\n\
|
||||
The <command> is an operating system dependent string.\n\
|
||||
The <command> may include space-separated arguments (such as flags)\n\
|
||||
When /edit is used, the temporary file to edit will be appended as the last argument.\n\
|
||||
If instead the -default option is specified, the built-in default editor will be used.
|
||||
The <command> may include space-separated arguments (such as flags)\n\n\
|
||||
If the -default option is specified, the built-in default editor will be used.\n\n\
|
||||
Otherwise an external editor should be specified in <command>. When <command>\n\
|
||||
is used, the temporary file to edit will be appended as the last argument.\n\
|
||||
Normally, edit mode will last until the external editor exits. Some external editors\n\
|
||||
will exit immediately (for example, if the edit window exists) either external editor\n\
|
||||
flags should be used to prevent immediate exit, or the -wait option should be used to\n\
|
||||
prompt the user to indicate when edit mode should end.\n\n\
|
||||
Note: while in edit mode no command inputs are seen. After leaving edit mode changes\n\
|
||||
to the edited snippets are not seen.
|
||||
|
||||
help.set.start =\
|
||||
Set the start-up configuration -- a sequence of snippets and commands read at start-up.\n\
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8157395 8157393 8157517
|
||||
* @bug 8157395 8157393 8157517 8158738
|
||||
* @summary Tests of jshell comand options, and undoing operations
|
||||
* @modules jdk.jshell/jdk.internal.jshell.tool
|
||||
* @build ToolCommandOptionTest ReplToolTesting
|
||||
@ -148,6 +148,8 @@ public class ToolCommandOptionTest extends ReplToolTesting {
|
||||
"| Unknown option: -furball -mattress -- /retain editor -furball -mattress"),
|
||||
(a) -> assertCommand(a, "/retain editor -default prog",
|
||||
"| Specify -default option or program, not both -- /retain editor -default prog"),
|
||||
(a) -> assertCommand(a, "/retain editor -default -wait",
|
||||
"| -wait applies to external editors, cannot be used with -default"),
|
||||
(a) -> assertCommand(a, "/retain editor prog",
|
||||
"| Editor set to: prog"),
|
||||
(a) -> assertCommand(a, "/retain editor prog -default",
|
||||
|
Loading…
x
Reference in New Issue
Block a user