The reason is that Env.prompt() tries to read from Java's System.console() - but if the program is not run from a Cmd Prompt or Terminal, then there is no Console!
As these posts show, this can also be true when run from an IDE:
The suggested fix is to revert back to using System.in should System.console() be null, which works!
C:\>fan CallExample.fan
Enter Name: Slim Shady
The patch to BootEnv.fan is given below:
diff -r f5e659e8f7c7 src/sys/java/fan/sys/BootEnv.java
--- a/src/sys/java/fan/sys/BootEnv.java Wed Apr 20 14:01:49 2016 -0400
+++ b/src/sys/java/fan/sys/BootEnv.java Thu Apr 21 12:41:40 2016 +0100
@@ -11,6 +11,8 @@
import java.net.*;
import java.util.Iterator;
import java.util.HashMap;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
import fanx.emit.*;
import fanx.fcode.*;
import fanx.util.*;
@@ -148,15 +150,20 @@
public String prompt(String msg)
{
- // attempt to initilize JLine and if we can't fallback to Java API
- if (!jlineInit())
- {
- return System.console().readLine(msg);
- }
-
- // use reflection to call JLine ConsoleReader.readLine
try
{
+ // attempt to initilize JLine and if we can't fallback to Java API
+ if (!jlineInit())
+ {
+ if (System.console() != null)
+ return System.console().readLine(msg);
+
+ // revert to Std In when there is no console
+ out().print(msg).flush();
+ return new BufferedReader(new InputStreamReader(System.in)).readLine();
+ }
+
+ // use reflection to call JLine ConsoleReader.readLine
return (String)jline.getClass()
.getMethod("readLine", new Class[] { String.class })
.invoke(jline, new Object[] { msg });
@@ -169,17 +176,24 @@
public String promptPassword(String msg)
{
- // attempt to initilize JLine and if we can't fallback to Java API
- if (!jlineInit())
- {
- char[] pass = System.console().readPassword(msg);
- if (pass == null) return null;
- return new String(pass);
- }
-
- // use reflection to call JLine ConsoleReader.readLine
try
{
+ // attempt to initilize JLine and if we can't fallback to Java API
+ if (!jlineInit())
+ {
+ if (System.console() != null)
+ {
+ char[] pass = System.console().readPassword(msg);
+ if (pass == null) return null;
+ return new String(pass);
+ }
+
+ // revert to Std In when there is no console
+ out().print(msg).flush();
+ return new BufferedReader(new InputStreamReader(System.in)).readLine();
+ }
+
+ // use reflection to call JLine ConsoleReader.readLine
return (String)jline.getClass()
.getMethod("readLine", new Class[] { String.class, Character.class })
.invoke(jline, new Object[] { msg, Character.valueOf('#') });
Note that the patch doesn't interfere with JLine either.
SlimerDude Thu 21 Apr 2016
Take this tiny example that waits for the user to enter something:
And try to run it from Fantom:
Then you receive an NPE:
The reason is that
Env.prompt()
tries to read from Java'sSystem.console()
- but if the program is not run from a Cmd Prompt or Terminal, then there is no Console!As these posts show, this can also be true when run from an IDE:
The suggested fix is to revert back to using
System.in
shouldSystem.console()
be null, which works!The patch to
BootEnv.fan
is given below:Note that the patch doesn't interfere with JLine either.
brian Thu 21 Apr 2016
Thanks, I pushed a fix