Using either JLine (or JLine2), is it possible to issue a call to readline on a ConsoleReader and have, in addition to the standard prompt, the buffer be pre-filled with a string of my choosing?
I have tried to do, e.g.:
reader.getCursorBuffer().write("Default");
reader.readLine("Prompt> ");
This seems to indeed write into the buffer, but the line only displays the prompt. If I press enter, readLine returns "Default" as I would expect. If I clear the screen, the buffer is redrawn and shown correctly.
My understanding is that I should somehow call reader.redrawLine() right after the call to readLine. This last one however is blocking, which makes it hard (not impossible, but it certainly feels wrong to use a second thread for that).
I ran into exactly this use case today.
It's a bit of a hack, but I was able to preload text into the JLine buffer and then let the user edit it by doing this:
String preloadReadLine(ConsoleReader reader, String prompt, String preload)
throws IOException
{
reader.resetPromptLine(prompt, preload, 0);
reader.print("\r");
return reader.readLine(prompt);
}
Yeah, the printing of \r is a hack, but it seems to make the thing work.
I'm using JLine-2.13.
I managed to do that using a thread (yes, it does feel wrong, but I found no other way).
I took inspiration from code found in JLine itself that also uses a thread for similar purposes.
In Scala:
val thr = new Thread() {
override def run() = {
reader.putString("Default")
reader.flush()
// Another way is:
// reader.getCursorBuffer.write("Default") // writes into the buffer without displaying
// out.print("D*f*ult") // here you can choose to display something different
// reader.flush()
}
}
thr.setPriority(Thread.MAX_PRIORITY)
thr.setDaemon(true)
thr.start()
I think you want either resetPromptLine or putStream if you already have the prompt set.
Not to hijack your question but I can't figure out how to simply print a line replacing the prompt (ostensibly or visually pushing the prompt down with a message above it).
Update for JLine3:
This can be accomplished with one of the existing overloads of readLine:
readLine(String prompt, Character mask, String buffer)
For example, reader.readLine("> ", null, "abc") will yield > abc where abc is part of the buffer being edited.
Related
I am trying to learn something basing on Java resource, and I want to adapt it to C++.
Source of Java has:
while( !StdIn.isEmpty())
{
//Take input from standard input, and process it...
}
In C++ the closest solution I could come up with was
while( cin >> someString)
{
//process someString...
}
However, the problem is, that cin returns state of object. There is no way I can put wrong input into std::string. This could have worked for ints, but not for string. Any equivalent function, or workarounds?
Thanks in advance.
With C++ iostreams, and also with C's stdio, you cannot tell whether a file (such as std::cin/stdin) will be empty if you were to try reading from it. The only way to find out is to actually read from the file, and then check whether the attempt succeeded.
(Yes, you could use some form of peek, but that's nowhere near as idiomatic or practical.)
So a standard method in C++ might look like this, processing entire lines of input at a time:
for (std::string line; std::getline(std::cin, line); )
{
// process "line"
}
The loop body will only execute if you succeeded at extracting one line from the input. Once the input runs out of data, the loop condition is no longer satisfied (i.e. the stream is no longer "good"), and the loop stops.
The same idea applies to C's fgets, as well as to unformatted std::istream::read() and fread, and to platform-specific functions like Posix's read(2): You always attempt to obtain input, then check whether you got any input, and only if you did do you proceed to consume the input.
I have assigment to make notepad using NetBeans Java. I already made the whole thing, I just don't know how to implement find/replace dialog, can you help me with this. I'm using jTextArea.
I will assume that you already know about Swing and how to make the appropriate dialog box (since you apparently have already made the JTextArea for the Notepad equivalent), and that you just want to know how to make it work on the back end.
What I would do is have a Scanner object go through your file to perform the find and replace.
String myAlteredText = "";
Scanner scanner = new Scanner(myText);
while(scanner.hasNext()) {
String next = scanner.next();
if(next.equals(userFindInput)) {
myAlteredText += userReplaceInput;
}
else {
myAlteredText += next;
}
myAlteredText += " ";
}
You can use .equalsIgnoreCase() if case doesn't matter. Likewise, you can tweak to adjust to your user parameters (i.e., if it doesn't have to match the whole word, use .contains() instead). There may be some nit-picky other things you need to do to maintain abnormal spacing and line breaks, but this is the general approach I would use.
You could use a JTable although this is rather unconventional. You could load each word into a new cell. This way when you need to replace 1 word you don't need to update the entire jtextarea for just 1 character unless I am mistaken. This would require a lot of work however in order to get this to work
Is there a way to dynamically change output in Java? For instance, in a terminal window if I have:
System.out.print("H")
and then I have:
System.out.print("I")
The output will be:
HI
Is there a way to assign a position to outputs that allows you to replace characters dynamically? For instance (and I know this would not output what I want, I merely want to demonstrate my thinking) this:
System.out.print("H")
Thread.sleep("1")
System.out.print("I")
And it would first print out
H
and then after a second, replace the H with an I?
I'm sure this sounds stupid, I am just interested in dynamically changing content without GUIs. Can someone point me in the direction for this technique? Thank you very much in advance.
You might want to take a look at
System.out.printf
Look at the example shown here: http://masterex.github.com/archive/2011/10/23/java-cli-progress-bar.html
edit:
printf displays formatted strings, which means you can adapt that format and change it for your needs.
for example you could do something like:
String[] planets = {"Mars", "Earth", "Jupiter"};
String format = "\r%s says Hello";
for(String planet : planets) {
System.out.printf(format, planet);
try {
Thread.sleep(1000);
}catch(Exception e) {
//... oh dear
}
}
Using the formatted string syntax found here: http://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#syntax
As the comment says this solution is only limited to a singular line however dependent on your needs this might be enough.
If you require a solution for the whole screen then a possible solution would be (although quite dirty) would be to hook the operating system using JNA and get a handle on the console window, find its height and then loop println() to "clear" the window then redraw your output.
If you would like to read more then I can answer more questions or here is a link: https://github.com/twall/jna
You can use \b to backspace and erase the previous character.
$ cat T.java
import java.lang.Thread;
public class T {
public static void main(String... args) throws Exception {
System.out.print("H");
System.out.flush();
Thread.sleep(1000);
System.out.print("\bI\n");
System.out.flush();
}
}
$ javac T.java && java T
I
It will output H, then replace it with I after one second.
Sadly, it doesn't work in Eclipse console, but in normal console it does.
This is what you need (uses carriage return '\r' to overwrite the previous output):
System.out.print("H");
Thread.sleep(1000);
System.out.print("\rI");
The C library that is usually used to do this sort of thing is called curses. (Also used from scripting languages that rely on bindings to C libraries, like Python.) You can use a Java binding to it, like JCurses. Google also tells me a pure-Java equivalent is available, called lanterna.
I need to monitor console output in Java, I have tried several different ways of retrieving the output as it is streamed, but I fell into a few pitfalls (looping the same output, only one part of output being captured, losing output) and have decided to go about it a different way.
I am developing a Java plugin for a server of the popular game, Minecraft, and I need to be able to monitor console output from other plugins.
I think a good way to do this is by redirecting console output to file, and then set up a recurring async task that checks the file, carries out anything it needs to do, and then clears the file for more input. I think I can do this with a simple use of System.setOut(PrintStream stream); and one of the many guides I can find on Google.
But there is a problem, and that is why I am asking here today. I need console output to stay on the console like normal, hence "mirroring". I cannot edit any of the plugins to output somewhere else, it needs to be from what my Java plugin can do and that only. Sure, maybe on every scheduled check on the file I could reprint it all back to the console but that would result in blocks being printed at a time, which would not be ideal. I do hope this is possible. Thank you!
EDIT: I don't think I explained fully. "plugins"'s classes are run by the program that I am developing for. I cannot change how classes are run and I cannot change how other plugins print to console.
I also do not want to direct console output to files for logging, that idea is only to keep it in a temporary place while it is parsed. Ideally, I need to pass each line of console output to a function (parseString(String line)) which carries out operations depending on the contents of the line. Also, I don't understand how I can read stream contents line-by-line properly, so if someone has any idea on how to, please let me know. :)
Capture System.out before changing it, and use TeeOutputStream:
OutputStream myCaptureStream = ...;
PrintStream original = System.out;
OutptStream outputtee = new TeeOutputStream(originalOut, myCaptureStream);
PrintStream printTee = new PrintStream(outputTee);
System.setOut(printTee);
Convert output stream (myCaptureStream) to an input stream
Use Java standard library PipedOutputStream: new PipedOutputStream; read carefully - you'll need your reader running on another thread.
Convert the input stream to a Reader,
and that to a BufferedReader.
BufferedReader gives you a readLine method.
Pseudo code:
// Feed myCaptureStream to TeeOutputStream
OutputStream myCaptureStream = new PipedOutputStream();
// Prepare to capture data being written to that output stream
InputStream myCaptureAsInputStream = new PipedInputStream(myCaptureStream);
Reader myCaptureReader = new InputStreamReader(myCaptureAsInputStream);
BufferedReader myCaptureBuffered = new BufferedReader(myCaptureReader, 1024);
// This must run on separate reader thread; in spin loop:
myCaptureBuffer.readLine
You can change the System.out and System.err to be references to your own custom PrintStreams. This solution is cross platform, unlike using a platform specific helper executable such as tee.
Documentation for System.setOut(PrintStream)
You can write your own PrintStream Subclass that looks something like:
class MirroringPrintStream extends PrintStream
{
PrintStream first, second;
public MirroringPrintStream(PrintStream first, PrintStream second)
{
// fail now rather than later
if (first == null || second == null) throw new NullPointerException();
this.first = first;
this.second = second;
}
#override
// methods go here (I do believe there are rather a lot of them, but they will all look the same)
}
You can then use System.setOut(new MirroringPrintStream(System.out, myLogStream)) where myLogStream is the PrintStream you opened to your log file. I'm not sure how this will handle appending to a file that something else periodically truncates, you might want to experiment with that a bit.
All else fails, go to irc.esper.net and ask about it in #risucraft
Assuming this is a friendly takeover of console output, why not log to your own stream
and mirror that to the console?
This has been asked before, but was not clarified to the point where I get it. Similar to the one or two other threads I've seen on this subject, I'm working on a chat client with command line inputs for logging in/off, disconnecting, etc. and I am unsure how to simulate this in a JUnit test case. Other responses indicated that I should try changing the System.in to a separate InputStream but...then what?
tl;dr: I have a method in my actual code for parsing command line input, and need a JUnit way of testing that these were entered and appropriately processed.
EDIT: It seems I misunderstood the question. I usually use the term "command line input" to refer to command line arguments given to the process to start with, rather than interactive console input. However...
Handing your real code either a different InputStream or possibly even a Reader or Scanner would indeed help - anything to separate the "getting input" part from the console. You can then fake the input all in one go pretty easily, using a String as input in your test code, and then either converting it to bytes and wrapping those bytes in a ByteArrayInputStream or wrapping the string directly in StringReader.
The downside of this is that there's no easy way of making this "pause" after one command in order to check the results.
You may want to alter the design somewhat so that the part which reads the input is separated from the part which handles the input. The reading part could be a very simple loop, on the order of:
String line;
while ((line = reader.readLine()) != null) {
handleInput(line);
}
You could then potentially leave that part untested by unit tests, or write some relatively primitive tests - but you can then test handleInput extensively, as it's now separated from the input source.
Original answer
If you've extracted the parsing code from the code which really starts the application, it's easy: run that code, and check the results. This will be easiest if you have some sort of class encapsulating the options, of course. For example, your main method might look like this:
public static void main(String[] args) {
Options options = Options.parse(args);
// Use options here
}
Then you can just test Options.parse very easily.