Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When compiling to a native image with Graal, no colors are shown #557

Closed
helpermethod opened this issue Nov 27, 2018 · 29 comments
Closed

When compiling to a native image with Graal, no colors are shown #557

helpermethod opened this issue Nov 27, 2018 · 29 comments
Milestone

Comments

@helpermethod
Copy link

helpermethod commented Nov 27, 2018

I've managed to compile my Java-based CLI with Graal following the steps described in

https://picocli.info/picocli-on-graalvm.html

It works great, except for one thing: when the help is shown, no colors are displayed.

image

This is the same output produced by the JAR.

image

@remkop
Copy link
Owner

remkop commented Nov 27, 2018

What do you get when you invoke the native image with system property picocli.ansi to true? (It should be possible to pass system properties to the native image.)

./mock-cli -Dpicocli.ansi=true

I suspect there is a problem with picocli's logic to detect that it's safe to switch on ANSI colors.

What is the value of environment variables TERM and OSTYPE on this system?

@helpermethod
Copy link
Author

helpermethod commented Nov 28, 2018

Indeed, when calling the binary with -Dpicocli.ansi=true, colors are displayed.

The output of TERM and OSTYPE are

$ echo $TERM
xterm-256color
$ echo $OSTYPE
darwin17.5.0

So this is a Mac I'm developing on. Note that I'm also building the binary without Graals static flag because static linking is not supported on MacOS.

This is my Graal config (I'm using Palantir's Graal Gradle Plugin)

graal {
    mainClass 'de.meinestadt.mock.Cli'
    outputName project.name
    option "-H:ReflectionConfigurationFiles=${project.buildDir}/cli-reflect.json"
    option '-H:+ReportUnsupportedElementsAtRuntime'
}

nativeImage.dependsOn 'generateGraalReflectionConfig', 'generateCompletionScript'

Thank you for your help!

@remkop
Copy link
Owner

remkop commented Nov 28, 2018

Ok, I suspect that this is caused by picocli's check whether the console is a TTY. Picocli uses reflection to detect this, and this reflection is not in the configuration. Unsure why ANSI colors worked for me when I tested...

Can you try adding the below snippet to cli-reflect.json, rebuild the native image and try again?

  {
    "name" : "java.lang.System",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true,
    "methods" : [
        { "name" : "console" }
    ]
  },

@remkop
Copy link
Owner

remkop commented Nov 28, 2018

If we can confirm that colors are shown when the above snippet is included in the cli-reflect.json, I can include a fix for this in the upcoming 3.8.1 release.

@remkop remkop added this to the 3.8.1 milestone Nov 28, 2018
@remkop remkop added type: bug 🐛 theme: codegen An issue or change related to the picocli-codegen module labels Nov 28, 2018
@remkop
Copy link
Owner

remkop commented Nov 29, 2018

@helpermethod, do you think you'll be able to test the above JSON snippet this week? I'm thinking to do another release this weekend and would be great if you could confirm that this fixes the issue.

@helpermethod
Copy link
Author

Hi @remkop !

Sadly, this doesn't seem to make a difference. Added the entry but still no colors.

@remkop
Copy link
Owner

remkop commented Nov 29, 2018

@helpermethod Can you please try again with with the latest picocli built from master?
I added some debug tracing that may give us more insight into what is happening.
You can enable the tracing by running with system property -Dpicocli.trace=DEBUG

@remkop
Copy link
Owner

remkop commented Nov 29, 2018

I suspect that System.console() returns null on your system. That would cause picocli to conclude that there is no terminal attached to the process so it should not emit ANSI escape codes.

The debug tracing now in master will confirm this. You can also confirm by printing the result of calling System.console() in the application.

By the way, can you give some version information on the operating system and Java version/vendor?

@remkop remkop removed the theme: codegen An issue or change related to the picocli-codegen module label Nov 29, 2018
@helpermethod
Copy link
Author

@remkop This is the trace output

11:22 $ ./mock-cli -Dpicocli.trace=DEBUG
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.Cli with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Create with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.config(java.lang.String,java.util.List,java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.mapping(java.lang.String,java.lang.String,java.util.Map) as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.List with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.configs() as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.mappings() as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Show with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Show.config(java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class picocli.CommandLine$AutoHelpMixin with factory picocli.CommandLine$DefaultFactory
[picocli INFO] Parsing 0 command line args []
[picocli DEBUG] Parser configuration: posixClusteredShortOptionsAllowed=true, stopAtPositional=false, stopAtUnmatched=false, separator=null, overwrittenOptionsAllowed=false, unmatchedArgumentsAllowed=false, expandAtFiles=true, atFileCommentChar=#, endOfOptionsDelimiter=--, limitSplit=false, aritySatisfiedByAttachedOptionParam=false, toggleBooleanFlags=true, unmatchedOptionsArePositionalParams=false, collectErrors=false,caseInsensitiveEnumValuesAllowed=true, trimQuotes=false, splitQuotedStrings=false
[picocli DEBUG] Set initial value for field boolean picocli.CommandLine$AutoHelpMixin.helpRequested of type boolean to false.
[picocli DEBUG] Set initial value for field boolean picocli.CommandLine$AutoHelpMixin.versionRequested of type boolean to false.
[picocli DEBUG] Initializing de.meinestadt.mock.Cli: 2 options, 0 positional parameters, 0 required, 3 subcommands.
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.Cli with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Create with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.config(java.lang.String,java.util.List,java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.mapping(java.lang.String,java.lang.String,java.util.Map) as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.List with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.configs() as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.mappings() as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Show with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Show.config(java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class picocli.CommandLine$AutoHelpMixin with factory picocli.CommandLine$DefaultFactory

@remkop
Copy link
Owner

remkop commented Nov 30, 2018

Did that show the usage help?
Could you run

 ./mock-cli -Dpicocli.trace=DEBUG --help

@helpermethod
Copy link
Author

Yes it did.

14:16 $ ./mock-cli -Dpicocli.trace=DEBUG --help
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.Cli with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Create with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.config(java.lang.String,java.util.List,java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.mapping(java.lang.String,java.lang.String,java.util.Map) as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.List with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.configs() as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.mappings() as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Show with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Show.config(java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class picocli.CommandLine$AutoHelpMixin with factory picocli.CommandLine$DefaultFactory
[picocli INFO] Parsing 1 command line args [--help]
[picocli DEBUG] Parser configuration: posixClusteredShortOptionsAllowed=true, stopAtPositional=false, stopAtUnmatched=false, separator=null, overwrittenOptionsAllowed=false, unmatchedArgumentsAllowed=false, expandAtFiles=true, atFileCommentChar=#, endOfOptionsDelimiter=--, limitSplit=false, aritySatisfiedByAttachedOptionParam=false, toggleBooleanFlags=true, unmatchedOptionsArePositionalParams=false, collectErrors=false,caseInsensitiveEnumValuesAllowed=true, trimQuotes=false, splitQuotedStrings=false
[picocli DEBUG] Set initial value for field boolean picocli.CommandLine$AutoHelpMixin.helpRequested of type boolean to false.
[picocli DEBUG] Set initial value for field boolean picocli.CommandLine$AutoHelpMixin.versionRequested of type boolean to false.
[picocli DEBUG] Initializing de.meinestadt.mock.Cli: 2 options, 0 positional parameters, 0 required, 3 subcommands.
[picocli DEBUG] Processing argument '--help'. Remainder=[]
[picocli DEBUG] '--help' cannot be separated into <option>=<option-parameter>
[picocli DEBUG] Found option named '--help': field boolean picocli.CommandLine$AutoHelpMixin.helpRequested, arity=0
[picocli INFO] field boolean picocli.CommandLine$AutoHelpMixin.helpRequested has 'usageHelp' annotation: not validating required fields
[picocli INFO] Setting field boolean picocli.CommandLine$AutoHelpMixin.helpRequested to 'true' (was 'false') for option --help
Usage: mock-cli [-hV] [COMMAND]
  -h, --help      Show this help message and exit.
  -V, --version   Print version information and exit.
Commands:
  create  creates a configuration or mapping
  list    lists available configurations or mappings
  show    displays a configuration or mapping

@remkop
Copy link
Owner

remkop commented Nov 30, 2018

Hmm... my last commit to master should introduce a DEBUG message starting with “Checking if ANSI possible: isTTY=...” but I don’t see that in the output. Did you use picocli 3.8 or the snapshot build from master?

What I’m trying to confirm is whether System.console() returns null in your environment. If it’s easier to just add some code to your application that prints the result of System.console(), then that’s fine too.

@helpermethod
Copy link
Author

Yes, used the SNAPSHOT version but with no difference. I've uploaded the project for analysis to GH

https://github.com/helpermethod/mock-cli

@helpermethod
Copy link
Author

What I've tried so far:

  • checked out picocli master (4.0.0-SNAPSHOT)

  • built my mock-cli project by performing a composite build

    ./gradlew --include-build ../picocli

After that didn't work out, I've install the 4.0.0-SNAPSHOT into my local Maven repository and let my project depend on the SNAPSHOT version.

@remkop
Copy link
Owner

remkop commented Dec 1, 2018

Picocli 4.0.0-SNAPSHOT has some additional debug tracing but if this is proving cumbersome we can do it differently.

I would like to find out if System.console() returns null when running the native graalvm image in your environment. Can we try just adding something like this to the Cli::run method:

System.out.println("System.console() returns " + System.console());

@remkop
Copy link
Owner

remkop commented Dec 1, 2018

FYI: I noticed the tracing I added on whether ANSI is available was not always shown. Probably because it was being logged from a static initializer method. I've made some improvements to the tracing (#560).

@helpermethod
Copy link
Author

Thank you! Will test out your changes on Monday (don't have my laptop at home right now, sry).

@helpermethod
Copy link
Author

The output based on your latest changes

09:19 $ ./mock-cli -Dpicocli.trace=DEBUG
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.Cli with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Create with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.config(java.lang.String,java.util.List,java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.mapping(java.lang.String,java.lang.String,java.util.Map) as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.List with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.configs() as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.mappings() as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Show with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Show.config(java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class picocli.CommandLine$AutoHelpMixin with factory picocli.CommandLine$DefaultFactory
[picocli INFO] Picocli version: 4.0.0-SNAPSHOT, JVM: 1.8.0_192 (Oracle Corporation Substrate VM null), OS: Mac OS X 10.13.4 x86_64
[picocli INFO] Parsing 0 command line args []
[picocli DEBUG] Parser configuration: posixClusteredShortOptionsAllowed=true, stopAtPositional=false, stopAtUnmatched=false, separator=null, overwrittenOptionsAllowed=false, unmatchedArgumentsAllowed=false, expandAtFiles=true, atFileCommentChar=#, endOfOptionsDelimiter=--, limitSplit=false, aritySatisfiedByAttachedOptionParam=false, toggleBooleanFlags=true, unmatchedOptionsArePositionalParams=false, collectErrors=false,caseInsensitiveEnumValuesAllowed=true, trimQuotes=false, splitQuotedStrings=false
[picocli DEBUG] (ANSI is disabled by default: TTY=false, isXTERM=true, hasOSTYPE=false, isWindows=false, JansiConsoleInstalled=false)
[picocli DEBUG] Set initial value for field boolean picocli.CommandLine$AutoHelpMixin.helpRequested of type boolean to false.
[picocli DEBUG] Set initial value for field boolean picocli.CommandLine$AutoHelpMixin.versionRequested of type boolean to false.
[picocli DEBUG] Initializing de.meinestadt.mock.Cli: 2 options, 0 positional parameters, 0 required, 3 subcommands.
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.Cli with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Create with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.config(java.lang.String,java.util.List,java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Create.mapping(java.lang.String,java.lang.String,java.util.Map) as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.List with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.configs() as command
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.List.mappings() as command
[picocli DEBUG] Creating CommandSpec for object of class de.meinestadt.mock.subcommand.Show with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for object of class java.lang.reflect.Method with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Using method public void de.meinestadt.mock.subcommand.Show.config(java.lang.String) as command
[picocli DEBUG] Creating CommandSpec for object of class picocli.CommandLine$AutoHelpMixin with factory picocli.CommandLine$DefaultFactory
Usage: mock-cli [-hV] [COMMAND]
  -h, --help      Show this help message and exit.
  -V, --version   Print version information and exit.
Commands:
  create  creates a configuration or mapping
  list    lists available configurations or mappings
  show    displays a configuration or mapping

@helpermethod
Copy link
Author

Relevant line:

(ANSI is disabled by default: TTY=false, isXTERM=true, hasOSTYPE=false, isWindows=false, JansiConsoleInstalled=false)

@remkop
Copy link
Owner

remkop commented Dec 3, 2018

Right. I'm 99% sure that this means that System.console() returns null when running the native graalvm image in your environment.

If System.console() returns null, picocli will conclude that there is no TTY and it should not emit ANSI escape sequences. I believe picocli is behaving correctly here.

The question is why System.console() returns null when running the native graalvm image in your environment. I think it makes sense to boil it down to a very small program to demonstrate the issue and submit an issue to https://github.com/oracle/graal/issues/ . What do you think?

public class WhyNoConsole {
    public static void main(String[] args) {
        System.printf("JVM: %s (%s %s %s), OS: %s %s %s%n",
                System.getProperty("java.version"), System.getProperty("java.vendor"), 
                System.getProperty("java.vm.name"), System.getProperty("java.vm.version"),
                System.getProperty("os.name"), System.getProperty("os.version"), 
                System.getProperty("os.arch"));
        System.out.println("System.console() = " + System.console());
    }
}

@helpermethod
Copy link
Author

helpermethod commented Dec 3, 2018

That doesn't seem to be the problem, System.console is in fact non-null

13:52 $ ./mock-cli
console: java.io.Console@108e8f140
Usage: mock-cli [-hV] [COMMAND]
  -h, --help      Show this help message and exit.
  -V, --version   Print version information and exit.
Commands:
  create  creates a configuration or mapping
  list    lists available configurations or mappings
  show    displays a configuration or mapping

@remkop
Copy link
Owner

remkop commented Dec 3, 2018

Really? That’s unexpected!
What about the below?

// this is how picocli checks if a console is available 
System.out.println(System.class.getDeclaredMethod(“console”).invoke(null));

@helpermethod
Copy link
Author

helpermethod commented Dec 3, 2018

This is the output

17:32 $ ./mock-cli
JVM: 1.8.0_192 (Oracle Corporation Substrate VM null), OS: Mac OS X 10.13.4 x86_64
System.console() = java.io.Console@107b90458
System.class.getDeclaredMethod("console").invoke(null) = java.io.Console@107b90458
Usage: mock-cli [-hV] [COMMAND]
  -h, --help      Show this help message and exit.
  -V, --version   Print version information and exit.
Commands:
  create  creates a configuration or mapping
  list    lists available configurations or mappings
  show    displays a configuration or mapping

Produced by the following Java snippet

    @Override
    public void run() {
        System.out.printf("JVM: %s (%s %s %s), OS: %s %s %s%n",
                System.getProperty("java.version"), System.getProperty("java.vendor"),
                System.getProperty("java.vm.name"), System.getProperty("java.vm.version"),
                System.getProperty("os.name"), System.getProperty("os.version"),
                System.getProperty("os.arch"));

        out.println("System.console() = " + System.console());

        try {
            out.println("System.class.getDeclaredMethod(\"console\").invoke(null) = " + System.class.getDeclaredMethod("console").invoke(null));
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }

        new CommandLine(this).usage(out);
    }

So both invocations seem to return a non-null object.

@remkop
Copy link
Owner

remkop commented Dec 3, 2018

Thank you very much for sticking with it to help me figure this out!
One possibility is that there is a timing problem: picocli reflects on the System.console() method when the picocli.CommandLine.Help.Ansi class is loaded. It is possible that on SubstrateVM the System.console() is not yet available when the picocli classes are loaded. (This would also explain why we did not see the DEBUG message starting with “Checking if ANSI possible: isTTY=...” in the output 3 days ago.)

I made a change to picocli master: it no longer reflects on System.console() when the Ansi class is loaded, but instead it does it the first time the Ansi.enabled() method is called.

Can you try building picocli from master again to see if it shows colors now?

We can also test my hypothesis directly in your program with this code:

public class Cli implements Runnable {
    static final Boolean TTY = calcTTY();
    
    static final boolean calcTTY() {
        try {
            TTY = System.class.getDeclaredMethod("console").invoke(null) == null;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    
    @Override
    public void run() {
        System.out.printf("JVM: %s (%s %s %s), OS: %s %s %s%n",
                System.getProperty("java.version"), System.getProperty("java.vendor"),
                System.getProperty("java.vm.name"), System.getProperty("java.vm.version"),
                System.getProperty("os.name"), System.getProperty("os.version"),
                System.getProperty("os.arch"));

        out.println("TTY in static initializer = " + TTY);
        out.println("System.console() = " + System.console());

        try {
            out.println("System.class.getDeclaredMethod(\"console\").invoke(null) = " + System.class.getDeclaredMethod("console").invoke(null));
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }

        new CommandLine(this).usage(out);
    }
}

But if possible please run it after building picocli from the latest master sources.

@helpermethod
Copy link
Author

Somehow it now works!

09:11 $ ./mock-cli
JVM: 1.8.0_192 (Oracle Corporation Substrate VM null), OS: Mac OS X 10.13.4 x86_64
TTY in static initializer = true
System.console() = java.io.Console@1066907d8
System.class.getDeclaredMethod("console").invoke(null) = java.io.Console@1066907d8
Usage: mock-cli [-hV] [COMMAND]
  -h, --help      Show this help message and exit.
  -V, --version   Print version information and exit.
Commands:
  create  creates a configuration or mapping
  list    lists available configurations or mappings
  show    displays a configuration or mapping

image

@remkop
Copy link
Owner

remkop commented Dec 4, 2018

Excellent! This is after rebuilding picocli from the latest sources in master?

@remkop
Copy link
Owner

remkop commented Dec 4, 2018

If my latest commit on master fixed the issue, I will do a 3.8.2 release for this.

@helpermethod
Copy link
Author

Yes, this was after using the latest master! Great work, thank you very much!

@remkop remkop modified the milestones: 3.8.1, 3.8.2 Dec 4, 2018
@remkop
Copy link
Owner

remkop commented Dec 4, 2018

I released v3.8.2 that includes this fix.

@remkop remkop closed this as completed Dec 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants