Вопрос

I am in the pursuit of designing a command-shell using Java . One important feature which I had to immediately implement was "auto complete" , as facilitated by the command-shell when "tab" key is being pressed . For this , I reckoned I had to read the input-command, character-by-character in the non-blocking mode .

Unfortunately , as I have understood , none of the Java API's support non-blocking input . That is , Java API's that are meant to read the input waits (blocks) until the user hits the "Enter" key , which is highly undesirable in my case .Also ,I have made up my mind not to use any third party Java libraries ( Such as JLine ).

So , I had to resort for JNI . The native .C file appears to be this -

 JNIEXPORT jint JNICALL Java_autoComplete_IOUtils_read_1character(JNIEnv *env, jobject obj)
{

int ch = getch(); // getch() - non-blocking input and doesn't echo the characters
return (jint)ch;
}

And the corresponding Java method in which the afore-mentioned native method is invoked :

 public static String GetLine()
{

    int i = 0;
    do
    {
        char variable = (char) read_character(); // Native method is invoked here 

        System.out.println(variable); // Just printing it for my reference 

        cmdLine = new StringBuffer(cmdLine).insert(i, variable).toString(); // cmdLine is of type String
        i++;

    } while ((search(cmdLine.charAt(i - 1), interruptableCharacterArray)) == false);

    return (new String(cmdLine));

}

 //Checks if the entered character is any one of those keys in the interruptableCharacterArray . As of now , interruptableCharacterArray contains only '\t' (The tab key )


  private static boolean search(char charAt,char[] interruptableCharacterArray2)
{
    for (int i = 0; i < index; i++)
    {
        if (interruptableCharacterArray2[i] == charAt)
            return true;
    }
    return false;
}

Also I can assure you that there are no hassles with respect to linking the native .dll . And , the "InterruptableCharacterArray" , as of now contains only '\t'( The "tab" key ). Hence , value of index as of now is 1 .

Probelm:

1> The control doesn't seem to block at :

char variable = (char) read_character();

That is , it doesn't seem to allow the user to enter the input through the Java Console at that line , which is intended to do that . And , same is the problem even in the case of getche() ( Non-blocking but echoes )

Instead , in each iteration some default garbage value is being taken for "variable" and that is being printed on the console when the following statement is executed :

System.out.println(variable);

However , this code of mine works like a charm when getch() is replaced by its blocking counterparts like getc(stdin),getchar() etc .

I am not able to figure-out as to what exactly is the problem in invoking getch() through JNI .

2> Also , I would be grateful , if any other alternateive solutions to achieve the same are suggested .

Thank you in advance !

Edit : The command-shell is to be implemented both on Windows and Unix based O/S.

Это было полезно?

Решение

Before you can have non-blocking IO from a terminal, you need to put it into "raw" mode: Terminals usually collect one line of input (that way, you can edit the current line with the cursor keys, etc) and just send it to the stdin of the application when it's "finished" (= when the user presses enter).

In "raw" mode, any keypress is sent to the app immediately and editing isn't possible (unless the app implements it itself).

To enable this, see the manual for stty(1). To modify the mode, you will need the C function tcsetattr(3).

I suggest to look into the source for JLine2 even when you don't want to use it, specifically into UnixTerminal.java and TerminalLineSettings

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top