Introduction
The source code is available on GitHub. |
Text-IO is a library for creating Java console applications. It can be used in applications that need to read interactive input from the user.
Features
-
supports reading values with various data types.
-
allows masking the input when reading sensitive data.
-
allows selecting a value from a list.
-
allows to specify constraints on the input values (format patterns, value ranges, length constraints etc.).
-
provides different terminal implementations and offers a Service Provider Interface (SPI) for configuring additional text terminals.
By default, Text-IO tries to use text terminals backed by java.io.Console. If no console device is present (which may happen, for example, when running the application in your IDE), a Swing-based terminal is used instead.
Example
TextIO textIO = TextIoFactory.getTextIO();
String user = textIO.newStringInputReader()
.withDefaultValue("admin")
.read("Username");
String password = textIO.newStringInputReader()
.withMinLength(6)
.withInputMasking(true)
.read("Password");
int age = textIO.newIntInputReader()
.withMinVal(13)
.read("Age");
Month month = textIO.newEnumInputReader(Month.class)
.read("What month were you born in?");
TextTerminal terminal = textIO.getTextTerminal();
terminal.printf("\nUser %s is %d years old, was born in %s and has the password %s.\n",
user, age, month, password);
Click on the image below to see the output of the above example in a Swing-based terminal.
You can also use a web-based terminal, which allows you to access your application via a browser, as shown in the image below.
Demo
Download the binary distribution and unzip it into a directory of your choice.
Make sure your JAVA_HOME environment variable correctly points to a JDK 8u40 or later.
Start the demo by executing 'textio-demo' or 'textio-demo.bat' in the bin directory.
Getting Started
You need Java 8 or newer in order to use Text-IO. |
Text-IO is available in Maven Central and JCenter.
<dependency> <groupId>org.beryx</groupId> <artifactId>text-io</artifactId> <version>1.7.2</version> </dependency>
compile 'org.beryx:text-io:1.7.2'
In order to use the WebTextTerminal, you have to include the text-io-web
artifact:
<dependency> <groupId>org.beryx</groupId> <artifactId>text-io-web</artifactId> <version>1.7.2</version> </dependency>
compile 'org.beryx:text-io-web:1.7.2'
User Guide
The JavaDoc is available here. |
Text Terminals
A text terminal is an abstraction layer used by the Text-IO library in order to provide device independence. Text terminals must implement the TextTerminal interface, which requires to allow at least:
-
reading a one-line text, optionally masking the input.
-
writing a one-line text.
-
writing a line separator.
The following concrete implementations are provided by the Text-IO library:
-
JLineTextTerminal, which is backed by a JLine ReadConsole.
-
AnsiTextTerminal, which extends JLineTextTerminal by allowing to customize the appearance of the prompt messages (colors and boldness).
-
ConsoleTextTerminal, which is backed by a java.io.Console.
-
SwingTextTerminal, which uses a JTextArea inside a JFrame.
-
SystemTextTerminal, which uses System.out, System.in and Scanner. It is not capable to mask input strings, therefore not recommended when reading sensitive data.
-
WebTextTerminal, which allows accessing your application via a browser. See details below.
Using the WebTextTerminal
The WebTextTerminal works only in conjunction with a web server supporting the DataApi (such as the SparkDataServer) and a web page that contains code for accessing this API. This is typically accomplished via textterm.js, as shown in the code snippet below.
<div id="textterm">
<p class="textterm-pair">
<span class="textterm-prompt"> </span>
<span contenteditable="true" class="textterm-input"> </span>
</p>
</div>
<script src="textterm.js"></script>
<script>
var textTerm = TextTerm.init(document.getElementById("textterm"));
</script>
Run the demo application and select the Web terminal option to see a WebTextTerminal in action. Look at the source code of WebTextIoExecutor.java and web-demo.html for more usage details. |
Currently, only WebKit-based browsers (such as Chrome, Opera or Safari) are able to mask input strings. Keep this in mind when working with sensitive data.
Input Readers
Input readers are able to read values of a specific type. They are subclasses of InputReader, which offers (via methods with names of the form withXXX()) a fluent interface for configuring various settings such as:
-
input masking - useful when reading sensitive data such as passwords.
-
defaultValue - the value to be used if the user pressed Enter.
-
possible values - necessary if the value to be read must be chosen from a list of allowed values.
-
parse error messages - used to provide custom parse error messages.
-
value checkers - used to check for constraint violations.
-
property name - if configured, the name of the property to be read will appear in error messages.
See the javadoc for more configuration methods.
The following concrete implementations are available:
-
BooleanInputReader - A reader for boolean values. Allows configuring which string value should be interpreted as true and which as false.
-
ByteInputReader - A reader for byte values. Allows configuring the minimum and maximum permitted values.
-
CharInputReader - A reader for char values. Allows configuring the minimum and maximum permitted values.
-
DoubleInputReader - A reader for double values. Allows configuring the minimum and maximum permitted values.
-
EnumInputReader - A reader for enum values. It allows selecting one of the constants defined by the given enum type.
-
FloatInputReader - A reader for float values. Allows configuring the minimum and maximum permitted values.
-
GenericInputReader - A reader for values of a given type, for which a parser is passed as constructor argument.
-
IntInputReader - A reader for int values. Allows configuring the minimum and maximum permitted values.
-
LongInputReader - A reader for long values. Allows configuring the minimum and maximum permitted values.
-
ShortInputReader - A reader for short values. Allows configuring the minimum and maximum permitted values.
-
StringInputReader - A reader for string values. Allows configuring the minimum and maximum permitted length, as well as a regex pattern.
Reading values
After configuring an input reader, you can use read(String… prompt) or read(List<String> prompt) to read a single value and readList(String… prompt) or readList(List<String> prompt) to read a comma-separated list of values. These methods repeatedly prompt the user to enter a value or a comma-separated list of values, until a valid input is provided.
Look at the source code of TextIoReadSpec.groovy and TextIoReadListSpec.groovy for examples of using the input readers. |
TextIO
The TextIO class provides factory methods for creating input readers.
These methods have names of the form newXXXInputReader()
, such as
newIntInputReader().
All InputReaders created by the same TextIO instance share the same TextTerminal, which can be retrieved by calling the getTextTerminal() method.
TextIoFactory
Although you can create yourself a TextIO instance by passing the desired TextTerminal as constructor argument, it is preferable to use the TextIoFactory for this task.
The TextIoFactory takes the following steps in order to choose the TextTerminal associated with the TextIO instance to be created:
-
If the system property
org.beryx.textio.TextTerminal
is defined, then it is taken to be the fully-qualified name of a concrete TextTerminal class. The class is loaded and instantiated. If this process fails, then the next step is executed. -
A ServiceLoader loads the configured TextTerminalProviders and searches for the first one capable to provide a TextTerminal instance. If none is found, then the next step is executed.
-
A default implementation is provided as follows:
-
if System.console() is not null, and a JLine ConsoleReader can be created, then a JLineTextTerminal is provided;
-
else, if System.console() is not null, a ConsoleTextTerminal is provided;
-
else, if the system is not headless, a SwingTextTerminal is provided;
-
else, a SystemTextTerminal is provided.
-
Look at the source code of SimpleApp.java for an example of using the default TextTerminal provided by TextIofactory, and TextIoDemo.java for examples of using custom TextTerminals. |