Java: "History" for cli commands, how to make ouput "editable"? - java

I want to add a "history" function to my java programm, like known from bash etc, so pressing the arrow keys should show previous send commands.
It's no problem to write the past commands to the default output, which will in three new lines if arrow up is hit three times and in not editable output. I want the output of the programm to be written in the input field so i just have to hit enter, to resend the command.
Is this possible?
Kind Regards

Take a look at JLine, which provides command history, tab completion and line editing.

If you want to roll your own solution, this will get you started.
You want to change from using a buffered input into a direct input. You can do this by interfacing with System.in directly. You should create a thread to handle this, and have it block on a call to System.in.read() in a loop, reading one byte at a time.
Each time a byte is read, keep your own buffer updated with the current command that's being read. Every character that gets typed, add it to the buffer. If the character is a \b, delete the last character in the buffer. When you detect a \r or \n, execute the command in the buffer and clear it.
If you receive an up or down arrow, send a number of \bs to System.out equal to the length of the buffer. This will erase the local copy of any current command being entered. Then print out the new command to System.out and enter it into the buffer, replacing whatever was there. This will allow the user to delete it, add to it, or just press enter to submit it. This mimics the functionality of bash.
You can also detect a \t (tab) character and implement a tab-completion function.

Related

Java println multithreading and stdin question

i have two threads: one of them (server) is printing something to the console and the other (user) one is taking input from console. The problem occurs if the first thread prints something while user is typing into console. it looks like for example
command from usermessage from server
or if the user hasn't typed the command fully
commmessage from server
and it messes up the command from the user
is there a way to make it look like
message from server
command from user
or
message from server
comm
so to print one line above the currently typed text in the console and maintain the user input. i still want the first thread to print while the user is typing so locking this thread untill user enters the command isn't an option
[I want] to print one line above the currently typed text in the console and maintain the user input.
There are no easy answers here unfortunately. The user input being entered is actually being echoed by the terminal and not by the Java program. You have no control over the input and can't reprint it once the standard output is displayed.
The only way to do this otherwise is to turn off terminal echoing and control the user keystrokes in your program, but that makes it a lot more complicated. See: How to disable console echoing
You could also use some sort of Java dialog box and then pop the standard out message in another dialog or let it go to standard out.
i still want the first thread to print while the user is typing so locking this thread until user enters the command isn't an option
Yeah I fear that locking out the standard output messages is only way for you to do this unless you want to use a different mechanism to get your user input.

How to grab CMD input with line that updates

I'm sure some people are familiar with the concept. You run a command at the CLI and as it progresses, the one line in front of you updates with a percentage. Under the bonnet, before each line is printed, it clears the current line, so instead of 100 lines of progress updates, you just have one line which updates until it hits 100%.
I want to make an app that will echo this information out into an embeded diaplay window. I'm fairly new to Java and I'd like my app to run a Windows command (sfc /scannow to be exact), display the output to the user on-the-fly and then once complete, I want to analyse the log file and give a readable conclusion to the user.
Is there some kind of library or special way of going about doing this so that when the line is "updated" in the console window, I can simply overwrite the current line in my display window?
The line is probably updated by the program writing \r control character (carriage return) to stdout. It is the task of the receiving application to handle this. The normal terminal handles this by setting the cursor to the start of the line. Your program can intercept this character and also treat it by resetting the line.

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.

Displaying a command prompt inside an infinite loop

I've a command line application which awaits an user input. I want to display > as the prompt.
This is my code.
while(true){
System.out.print("> ")
// do stuff
}
The problem is that the > displays every time the loop iterates but the cursor blinks at the beginning of the loop, thereby making my > a part of the user input. I want the cursor to be blinking one space after the > everytime the loop iterates and also > not to be a part of the next line object(assuming I'm using a scanner to parse input). Any help appreciated.
If you really worry about "great user experience"; than anything that only uses the "java builtin" console functions ... will not meet that requirement.
So, if that matters to you, I recommend looking into the various libraries that give you "ncurses like" functionality, like charva, java curses or lanterna.
I agree with #Aaron that "> " will not be part of the user's input, you can verify this by adding the lines below just under System.out.print("> ");
String usrInput = new java.util.Scanner(System.in).next();
System.out.println("Your input was " + usrInput);
If you are just asking how to change the while loop to make it blink after the > :
System.out.print(">_");
while(true) {
Thread.sleep(400);
System.out.print("\b ");
Thread.sleep(400);
System.out.print("\b_");
}
I wouldn't recommend to handle input this way, but it will get you the visual effect you are after.
When you use System.out.print or most other output commands, you're actually putting text in stdout / System.out, which your console will check to display said text.
It will not interfere with the user input which is transmitted via the independant stdin / System.in.
The problem is that these buffers are not modifiable, only appendable : once you've written something you can't come back to erase it, so making a prompt blink is not possible this way.
Some console might handle the BACKSPACE 0x08 ascii control character to erase the previous character, but I wouldn't rely on it.
There might be other methods that would grant you a read/write access to the console text buffer, but I doubt using it would be much easier than writing a GUI. I'd recommend either implementing your program in a language specific to your console (bash, powershell, etc.) or implementing a GUI.

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.

Categories