Read current console input before Enter - java

I'm writing a multithreaded socket chat. Is there any way to get the console input at a given time before the user has hit enter?
Let's say I'm typing a message, and while I'm typing it, the server sends a message to me. The server's message will get printed right after the message I'm currently writing.
How it looks:
Me>Hey!
Server>Heya!
Me>How are yServer>Hello!
If possible, I want to save the "How are y" string, remove it and paste it again after the server output:
Me>Hey!
Server>Heya!
Server>Hello!
Me>How are y

your problems boils down to two separate issues. number one is reading input from stdin or console character by character. this is tricky by itself, since most common approaches to reading input only do entire lines.
the second issues you're facing is going back and forth on the screenm because you have to update the current input and the new incoming messages this is quite possible, but the way to do it depends heavily on your terminal type and it's capabilities:
http://unix.stackexchange.com/questions/43945/whats-the-difference-between-various-term-variables
doing this correctly for all possible $TERM values on all OSs is rather tricky as well. you might do better using a library such as jcurses:
https://github.com/sunhong/jcurses
that abstracts this away from you.

Related

how can we simulate Ctrl+C to stop the console app from waiting for user input in java

I am trying to test a command line app that waits for the user input after every step. I am able to test the app using System Rules provided by Stefan Birkner. Currently, I provide inputs from the beginning to the end which works like a charm and I can assert the final output from system log.
However, I want to test for the negative cases before the end of the app for which I give invalid inputs in the beginning to evaluate the error message. When invalid inputs are given, the console prints an error message and keeps waiting for the user to provide a valid input. How do I send Ctrl+C using as shown below:
systemInMock.provideLines(Ctrl+C);
systemInMock.provideLines accepts only strings. Is there a way to send Ctrl+C signal?
An example of my junit test is shown below:
#Test
public void testInValidMarker() throws Exception{
systemInMock.provideLines("abc","def","1");
Main.main(new String[]{});
assertTrue(systemOutRule.getLog().contains("Invalid marker, try again"));
}
Appreciate your help!
If I'm not mistaken, when you do ctrl+c, it doesn't actually get written to console. If that's true, then in no case will your program ever be given ctrl+c, so provideLines will never be in a position where it is given ctrl+c.
For proof, open up cmd and type in a program with program arguments (in my case, I use ant). If you type ant and then ctrl+c, the cursor is moved to a new line.
There are two ways you can control termination behavior:
You can use a shutdown hook (found from this previously asked question ). Doing this will allow you to handle what happens (potentially with issues).
Or you could create your own termination argument like -q or q, which would trigger an action to end the program (maybe a System.exit(1)). This way you can mock that input.
In UNIX/Linux, when you type CTRL-C, your shell intercepts it and sends the process a SIGINT signal -- see: How does Ctrl-C terminate a child process?
Therefore the System Rules project doesn't have anything to help you -- in this situation the process doesn't receive any character input.
By default, the whole JVM shuts down when it receives SIGINT. This is obviously bad news for a running test.
The SO question Signal handling using "TERM" -- may be of use.
A side effect of Java's portability is that for some OS features, it either abstracts things away until they're unrecognisable, or doesn't expose them at all.
I suspect what you're asking for can't be achieved.
If you're allowed to change the requirements slightly, you could ask the user to close with CTRL-D -- this closes stdin with EOF.
Although it's quite the overkill, you could launch a whole new JVM running your program, using ProcessBuilder. You might imagine you'd get an API to send arbitrary signals to that process. But for portability reasons, all you can do is process.destroy(), which sends SIGTERM.
Tried this as a comment, but it didn't read right. It's not exactly an "Answer" though.
So Java is really bad at console input. It reads an entire line at once and you can't do anything about it--there is no way to trap special characters or even see any of the input before the user hits return. Also I think a ctrl-d will close your input session--(Add that test to your use case if you don't use any other suggestion here because it can put you into a state you didn't expect!)
Three suggestions:
The simplest: If you can use a GUI and aren't really looking for an ongoing input/response REPL the simplest answer is usually to use JOptionPane to throw up a quick dialog. It's a one-line solution to get some user input, but not so good for an ongoing command-driven system.
If you can't use swing (If you are running headless) then you may have little choice, but you can use the JLine library. That will give you a lot more flexibility. This is how Groovysh does it's REPL. It will let you see each character as it is typed and do things like completion where a user might type part of a file name and hit tab and you put the rest in for him.
If you don't want to use JLine but want a REPL feel there is also a more complex GUI solution--create a swing console window. A trivial solution would just be a text input box to allow typing and a text area to display results, but there are certainly libraries out there with more complete console solutions.
The point here is that using Java standard input alone is just not a good solution for anything beyond a trivial/personal script--and even then I avoid it. Perhaps not the answer you asked for, but maybe it's the one you need :)

java writing letters in console before user input

I am writing simple socket chat using console to output messages. The problem is that when one user types a message, and at the same time getting one, his input interrupted:
I: writing my input here, but
Other_user: hi! here is a message for you.
I: it splits to different lines, which is 1) very inconvenient 2) cannot see which simbols i deleted if press backspace
So, what i am asking is, how can I avoid this
(something like: if message is received, check input for symbols; if there are, remember them, delete last stroke in console, print message, and then recreate that stroke).
EDIT: attached picture
hard to tell without specific code, but an option is to use two threads, one to handle the socket input, one for output. attach these to System.in and System.out respectively. it seems like you might be using only one thread to do both.

Java CLI App - keep input from scrolling up

I get that this isn't possible to do with normal java, although if there are any libraries out this it would be very useful.
Essentially, I'm designing a console app and running into an issue that when output happens while something is typed in the input line, that input text will move up and appear before the line that just got output. Is it possible to fix this in some form so that the text you are inputting that stays at the bottom?
EX:
I'm typing something as input into my commandline app, and then the program prints something WHILE I'm typing - this causes what was originally on the input line to be scrolled up with whatever the output text was. When you are trying to type something in this can obviously be detrimental. I know it's possible to prevent this.. (Other programs have done it... EX: Minecraft Server)
(If I need to be more descriptive I can.)
You could use the help of threads. One that listens to user input, the other process the actual output. This problem is similar to basic race condition problems when multiple threads attempt to read and write to a shared resource.
Your shared resource is that console. You need to keep the Input/Output operations synchronized. Have a look at race condition.

Command-line interface in Java

I want to create a cross platform solution for providing access to the input, error and output streams of a Process in Java.
Basically, what I want to create is a text area that displays the Process' output and error streams, and allows you to supply data to the input stream. In other words, pretty much what Eclipse is already providing with its Console when you run an application.
Now, a basic implementation of this was easy, I simply send all key presses to the input stream. But, of course, I ran into trouble with pasting, backspace and arrow keys, handling ctrl-C and so on.
It seems I should wait before sending data to the Process' input stream. But wait for what? Should I send all entered (and pasted) text at each return key? Or after an interval? What about ctrl-C, ctrl-X and so on. Do I send arrow key movement to the input stream?
The easiest and most user-friendly solution is to have a "Send" button which sends the entire contents of the text area and clears it. Think instant messenger apps or SO comment editor.
You should not wait for anything, simply send - but send in a separate Thread, not your GUI-Event-thread, so the latter one does not block.
For handling the special characters, look what you would get when these signs are entered in a text console.

Why Use java.io.Console?

Just a quick one here.
What are the benefits of using java.io.Console as opposed to using a BufferedReader wrapping an InputStreamReader for System.in?
Why would I use it?
Thanks for any advice!
Because it's code that is already written for you...no need to re-invent the wheel. Chances are, you're not going to get it any better than it already is.
You can use java.io.Console to present an interactive command-line to the user. You could do all that with System.in yourself, but you would have to implement things like noticing when the input was done, or readPassword, etc.
See java.io.Console is finally here!
One of the most popular feature
requests for J2SE in recent times has
been the request to improve console
support and provide a way to enter
passwords with echo disabled.
Developers know this feature 4050435
as it has been skulking in the Top 25
RFEs list for some time.
java.io.Console only works when you start a Java program from a command line without redirecting STDIN/STDOUT.
The main advantage I see with Console over System.in is that you have the readPassword() method, which won't echo the characters typed by the user (I couldn't find a way to do this with System.in).
You also have readLine() which will present a prompt and read a single line. You don't have to create your own LineNumberReader.
But, if you want your Java program to be able to read from STDIN when it's redirected from a file or pipe, you still have to use System.in.
Another trick I'm pretty sure you won't get with Console--I created my own input and output streams and replaced System.in/out with them. My implementation of the stream appended to a log file as well as echoing to the screen.
When I turned on my poor-man's "Debug Info", I could even have it tell me what program/line the sysout came from (It was slow though. It created an exception and examined the appropriate stack entry so it was off by default)
java.io.Console is used to take and read input from the user at runtime and output are displayed after processing the input from user.
For more and detailed information visit https://www.examsmyantra.com/article/58/java/java-io---console-input-and-output

Categories