Skip to content

Commit

Permalink
[GR-19220] Add pager support into Launcher (#2542)
Browse files Browse the repository at this point in the history
PullRequest: truffleruby/3361
  • Loading branch information
eregon committed May 26, 2022
2 parents b8b1e7e + 67788c8 commit 365316e
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Compatibility:
* Define `Process::{CLOCK_BOOTTIME,CLOCK_BOOTTIME_ALARM,CLOCK_REALTIME_ALARM}` (#1480, @eregon).
* Improve support of `:chomp` keyword argument in `IO` and `StringIO` methods (#2650, @andrykonchin).
* Implement specializations for immutable ruby objects for ObjectSpace methods (@bjfish).
* Use `$PAGER` for `--help` and `--help*`, similar to CRuby (#2542, @Strech).

Performance:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,10 @@ private void processArgument() throws CommandLineException {
disallowedInRubyOpts(argument);
warnInternalDebugTool(argument);
break FOR;
} else if (rubyOpts && argument.equals("--help")) {
} else if (argument.equals("--help")) {
disallowedInRubyOpts(argument);
// --help is handled by org.graalvm.launcher.Launcher#printDefaultHelp
config.getUnknownArguments().add(argument);
break FOR;
} else if (argument.equals("--version")) {
disallowedInRubyOpts(argument);
Expand Down
84 changes: 68 additions & 16 deletions src/launcher/java/org/truffleruby/launcher/RubyLauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
package org.truffleruby.launcher;

import java.io.PrintStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.lang.ProcessBuilder.Redirect;

import org.graalvm.launcher.AbstractLanguageLauncher;
import org.graalvm.nativeimage.ProcessProperties;
Expand All @@ -33,6 +35,7 @@ public class RubyLauncher extends AbstractLanguageLauncher {

private CommandLineOptions config;
private String implementationName = null;
private boolean helpOptionUsed = false; // Any --help* option

public static void main(String[] args) {
new RubyLauncher().launch(args);
Expand All @@ -54,8 +57,8 @@ protected void validateArguments(Map<String, String> polyglotOptions) {

@Override
protected void printVersion() {
System.out.println(TruffleRuby.getVersionString(getImplementationNameFromEngine()));
System.out.println();
getOutput().println(TruffleRuby.getVersionString(getImplementationNameFromEngine()));
getOutput().println();
printPolyglotVersions();
}

Expand Down Expand Up @@ -109,9 +112,9 @@ protected List<String> preprocessArguments(List<String> args, Map<String, String
}

} catch (CommandLineException commandLineException) {
System.err.println("truffleruby: " + commandLineException.getMessage());
getError().println("truffleruby: " + commandLineException.getMessage());
if (commandLineException.isUsageError()) {
printHelp(System.err);
printHelp(getError());
}
System.exit(1);
}
Expand Down Expand Up @@ -163,7 +166,7 @@ protected void collectArguments(Set<String> options) {

@Override
protected void printHelp(OptionCategory maxCategory) {
printHelp(System.out);
printHelp(getOutput());
}

@Override
Expand All @@ -173,6 +176,43 @@ protected AbortException abortUnrecognizedArgument(String argument) {
"truffleruby: invalid option " + argument + " (Use --help for usage instructions.)");
}

@Override
protected boolean parseCommonOption(String defaultOptionPrefix, Map<String, String> polyglotOptions,
boolean experimentalOptions, String arg) {
if (arg.startsWith("--help")) {
helpOptionUsed = true;
}

return super.parseCommonOption(defaultOptionPrefix, polyglotOptions, experimentalOptions, arg);
}

@Override
protected boolean runLauncherAction() {
String pager;
if (helpOptionUsed && System.console() != null && !(pager = getPagerFromEnv()).isEmpty()) {
try {
Process process = new ProcessBuilder(pager.split(" "))
.redirectOutput(Redirect.INHERIT) // set the output of the pager to the terminal and not a pipe
.redirectError(Redirect.INHERIT) // set the error of the pager to the terminal and not a pipe
.start();
PrintStream out = new PrintStream(process.getOutputStream());

setOutput(out);
boolean code = super.runLauncherAction();

out.flush();
out.close();
process.waitFor();

return code;
} catch (IOException | InterruptedException e) {
throw abort(e);
}
} else {
return super.runLauncherAction();
}
}

private int runRubyMain(Context.Builder contextBuilder, CommandLineOptions config) {
if (config.executionAction == ExecutionAction.UNSET) {
switch (config.defaultExecutionAction) {
Expand All @@ -184,7 +224,7 @@ private int runRubyMain(Context.Builder contextBuilder, CommandLineOptions confi
case IRB:
config.executionAction = ExecutionAction.PATH;
if (System.console() != null) {
System.err.println(
getError().println(
"[ruby] WARNING: truffleruby starts IRB when stdin is a TTY instead of reading from stdin, use '-' to read from stdin");
config.executionAction = ExecutionAction.PATH;
config.toExecute = "irb";
Expand All @@ -203,7 +243,7 @@ private int runRubyMain(Context.Builder contextBuilder, CommandLineOptions confi
// Apply options to run gem/bundle more efficiently
contextBuilder.option("engine.Mode", "latency");
if (Boolean.getBoolean("truffleruby.launcher.log")) {
System.err.println("[ruby] CONFIG: detected gem or bundle command, using --engine.Mode=latency");
getError().println("[ruby] CONFIG: detected gem or bundle command, using --engine.Mode=latency");
}
}

Expand Down Expand Up @@ -241,7 +281,7 @@ private int runContext(Context.Builder builder, CommandLineOptions config) {
if (file.isString()) {
config.toExecute = file.asString();
} else {
System.err
getError()
.println("truffleruby: No such file or directory -- " + config.toExecute + " (LoadError)");
return 1;
}
Expand Down Expand Up @@ -270,9 +310,9 @@ private int runContext(Context.Builder builder, CommandLineOptions config) {
return exitCode;
} catch (PolyglotException e) {
if (e.isHostException()) { // GR-22071
System.err.println("truffleruby: a host exception reached the top level:");
getError().println("truffleruby: a host exception reached the top level:");
} else {
System.err.println(
getError().println(
"truffleruby: an exception escaped out of the interpreter - this is an implementation bug");
}
e.printStackTrace();
Expand All @@ -299,24 +339,36 @@ private static List<String> getPathListFromEnvVariable(String name) {
return Collections.emptyList();
}

private static String getPagerFromEnv() {
String pager = System.getenv("RUBY_PAGER");
if (pager != null) {
return pager.strip();
}

pager = System.getenv("PAGER");
if (pager != null) {
return pager.strip();
}

return "";
}

private void printPreRunInformation(CommandLineOptions config) {
if (config.showVersion) {
System.out.println(TruffleRuby.getVersionString(getImplementationNameFromEngine()));
getOutput().println(TruffleRuby.getVersionString(getImplementationNameFromEngine()));
}

if (config.showCopyright) {
System.out.println(TruffleRuby.RUBY_COPYRIGHT);
getOutput().println(TruffleRuby.RUBY_COPYRIGHT);
}

switch (config.showHelp) {
case NONE:
break;
case SHORT:
printShortHelp(System.out);
break;
case LONG:
printHelp(System.out);
printShortHelp(getOutput());
break;
// --help is handled by org.graalvm.launcher.Launcher#printDefaultHelp
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/launcher/java/org/truffleruby/launcher/ShowHelp.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@

public enum ShowHelp {
NONE,
SHORT,
LONG
SHORT // -h
// LONG // --help is handled by org.graalvm.launcher.Launcher#printDefaultHelp
}

0 comments on commit 365316e

Please sign in to comment.