javaui-automationjline

Is there a way to automate user input with JLine's LineReader?


When handling user input through Scanner(System.in), you can use System.setIn() to automate user input.

Like this:

package edu.ntnu.idi.idat;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Scanner;

public final class TestCode {
    private TestCode() { }
    /**
     * Test code.
     * @param args
     */
    public static void main(
        final String[] args
    ) {
        InputStream input = System.in;
        String testInputString = "test" + System.lineSeparator() + "test2";
        ByteArrayInputStream testInput
            = new ByteArrayInputStream(testInputString.getBytes());

        System.setIn(testInput);

        Scanner inputScanner = new Scanner(System.in);

        System.out.println(inputScanner.nextLine());
        System.out.println(inputScanner.nextLine());

        inputScanner.close()
    }
}

But when trying the same method for JLine's LineReader, it doesn't work:

package edu.ntnu.idi.idat;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

public final class TestCode {
    private TestCode() { }
    /**
     * Test code.
     * @param args
     * @throws IOException
     */
    public static void main(
        final String[] args
    ) throws IOException {
        InputStream input = System.in;
        String testInputString = "test" + System.lineSeparator() + "test2";
        ByteArrayInputStream testInput
            = new ByteArrayInputStream(testInputString.getBytes());

        System.setIn(testInput);

        Terminal terminal = TerminalBuilder.builder().build();
        LineReader lineReader = LineReaderBuilder
            .builder()
            .terminal(terminal)
            .build();

        System.out.println(lineReader.readLine());
        System.out.println(lineReader.readLine());

        terminal.close()
    }
}

I believe this is because inputScanner uses System.in (as can be seen when constructing it), while LineReader doesn't seem to.

My question is: is there a way to automate user input for LineReader as well?


Solution

  • you can use DumbTerminal seems like its designed for non-interactive use.

    public final class TestCode {
        private TestCode() { }
        
        public static void main(String[] args) throws IOException {
            String testInputString = "test" + System.lineSeparator() + "test2";
            ByteArrayInputStream input = 
                new ByteArrayInputStream(testInputString.getBytes(StandardCharsets.UTF_8));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
    
            // Use DumbTerminal for automated input
            Terminal terminal = new DumbTerminal(input, output);
            
            LineReader lineReader = LineReaderBuilder.builder()
                    .terminal(terminal)
                    .build();
    
            System.out.println("Read: " + lineReader.readLine());
            System.out.println("Read: " + lineReader.readLine());
    
            terminal.close();
        }
    }
    

    or Piped input & output stream:

        public static void main(String[] args) throws IOException {
            PipedInputStream in = new PipedInputStream();
            PipedOutputStream out = new PipedOutputStream(in);
            PrintWriter writer = new PrintWriter(out, true);
    
            // Write test input to the pipe
            writer.println("test");
            writer.println("test2");
    
            Terminal terminal = TerminalBuilder.builder()
                    .streams(in, System.out)
                    .build();
    
            LineReader lineReader = LineReaderBuilder.builder()
                    .terminal(terminal)
                    .build();
    
            System.out.println("Read: " + lineReader.readLine());
            System.out.println("Read: " + lineReader.readLine());
    
            writer.close();
            terminal.close();
        }