0

I'm having some trouble with Jline and not quite understanding how to work it properly, everything seems to work from the examples but when i attempt to move it into my console application things go weird.

I've come across two issues:

  1. When you write input into the console while something else is logging a message via System out, the written input gets broken. (View: https://i.stack.imgur.com/9nDRf.png)

  2. I attempted to sync the commands to the main thread since the reader thread will be blocking, but this time you'll find that this causes the output text to take over the commands input space. ((Green text is the input, white is output)View: https://i.stack.imgur.com/pxawJ.png)

The output i expected was for input coming from the bottom of the console to be unaffected by the output of the console, leaving a smooth input text layer at the bottom. (View: https://i.stack.imgur.com/Ll0D2.png)

Here's an example class i wrote to demonstrate the two problems I'm having:

import jline.console.ConsoleReader; 
import java.io.IOException;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.ReentrantLock;

public class Example {

    private ConsoleReader consoleReader;
    private LinkedList<Runnable> syncQueue = new LinkedList<>();

    private ReentrantLock lock = new ReentrantLock();


    public Example() {
        try {
            this.consoleReader = new ConsoleReader();
            this.consoleReader.setExpandEvents(false);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //If you enable this, Jline seems to be disrupted by the System out.
        // startStopwatch();
        setupJline();

        //Ticker, its ugly i know
        while (true) {

            lock.lock();
            try {
                while (syncQueue.size() > 0) {
                    Runnable runnable = syncQueue.poll();
                    try {
                        runnable.run();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                lock.unlock();
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    private void setupJline() {
        new Thread("Console Thread") {
            @Override
            public void run() {
                while (true) {
                    try {
                        String line = consoleReader.readLine(">");
                        if (line != null && line.trim().length() > 0) {
                            //Lets pass this on as an instruction to our program

                            //Sync seems okay, output wise
                            handleInstructionSynced(line);


                            //async seems to mess things up though, comment the handleInstructionSynced method and
                            //uncomment the Async one to see what i mean.

                            //handleInstructionAsync(line);
                        }
                        consoleReader.flush();

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    //Just a dummy example instruction handler
    private void handleInstructionAsync(String input) {
        System.out.println("You've input \"" + input + "\" as your instruction.");
    }

    private void handleInstructionSynced(String input) {
        runSync(() -> System.out.println("You've input \"" + input + "\" as your instruction."));
    }


    private void runSync(Runnable runnable) {
        lock.lock();
        try {
            syncQueue.add(runnable);
        } finally {
            lock.unlock();
        }
    }

    private void startStopwatch() {

        Timer timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            int time = 0;

            @Override
            public void run() {
                System.out.println(time + " seconds counted");

                time++;
            }
        };
        timer.scheduleAtFixedRate(timerTask, 0, 1000);
    }

    public static void main(String[] args) {
        new Example();
    }
}

Any solutions?

Jakeinzah
  • 25
  • 1
  • 6
  • maybe you should rather add an issue in their github issue tracker... – tkruse Feb 13 '18 at 02:58
  • I don't believe this is an issue with Jline considering that there are programs who use Jline and don't seem to recreate the same issue as below. – Jakeinzah Feb 14 '18 at 00:57

0 Answers0