Search in sources :

Example 1 with UnixTerminal

use of com.googlecode.lanterna.terminal.ansi.UnixTerminal in project claro-lang by JasonSteving99.

the class ReplTerminal method runTerminal.

public void runTerminal() {
    DefaultTerminalFactory defaultTerminalFactory = new DefaultTerminalFactory();
    UnixTerminal terminal = null;
    try {
        terminal = new UnixTerminal(System.in, System.out, StandardCharsets.UTF_8, CtrlCBehaviour.CTRL_C_KILLS_APPLICATION);
        terminal.clearScreen();
        terminal.setCursorVisible(true);
        final TextGraphics textGraphics = terminal.newTextGraphics();
        // Change to a background/foreground color combo that pops more.
        textGraphics.setForegroundColor(TextColor.ANSI.WHITE);
        textGraphics.setBackgroundColor(TextColor.ANSI.BLACK);
        textGraphics.putString(2, 0, String.format("ClaroLang %s - Press ESC/Ctr-C to exit", claroVersion), SGR.BOLD);
        // Change back to the default background/foreground colors.
        textGraphics.setForegroundColor(TextColor.ANSI.DEFAULT);
        textGraphics.setBackgroundColor(TextColor.ANSI.DEFAULT);
        final String PROMPT = ">>> ";
        textGraphics.putString(0, 1, PROMPT, SGR.BOLD);
        // Need to flush for changes to become visible.
        terminal.flush();
        // Setup the control vars that'll track the current user position and state as they use the terminal.
        StringBuilder currInstruction = new StringBuilder();
        Stack<String> prevInstructions = new Stack<>();
        int instructionIndex = 0;
        int currLine = 1;
        int currPromptCol = 0;
        KeyStroke keyStroke = terminal.readInput();
        while (keyStroke.getKeyType() != KeyType.Escape) {
            switch(keyStroke.getKeyType()) {
                case Character:
                    Character currKeyStrokeCharacter = keyStroke.getCharacter();
                    currInstruction.insert(currPromptCol, keyStroke.getCharacter().charValue());
                    currPromptCol++;
                    break;
                case ArrowUp:
                    if (instructionIndex == 0) {
                        terminal.bell();
                    } else {
                        textGraphics.putString(0, currLine, PROMPT + getSpacesStringOfLength(currInstruction.length()));
                        currInstruction.delete(0, currInstruction.length());
                        currInstruction.append(prevInstructions.elementAt(--instructionIndex));
                        currPromptCol = currInstruction.length();
                    }
                    break;
                case ArrowDown:
                    if (instructionIndex == prevInstructions.size() - 1) {
                        // Moving down after the last instruction, should just clear everything.
                        textGraphics.putString(0, currLine, PROMPT + getSpacesStringOfLength(currInstruction.length()));
                        currInstruction.delete(0, currInstruction.length());
                        instructionIndex++;
                        currPromptCol = 0;
                    } else if (instructionIndex >= prevInstructions.size()) {
                        terminal.bell();
                    } else {
                        textGraphics.putString(0, currLine, PROMPT + getSpacesStringOfLength(currInstruction.length()));
                        currInstruction.delete(0, currInstruction.length());
                        currInstruction.append(prevInstructions.elementAt(++instructionIndex));
                        currPromptCol = currInstruction.length();
                    }
                    break;
                case ArrowRight:
                    if (currPromptCol < currInstruction.length()) {
                        currPromptCol++;
                    } else {
                        terminal.bell();
                    }
                    break;
                case ArrowLeft:
                    if (currPromptCol > 0) {
                        currPromptCol--;
                    } else {
                        terminal.bell();
                    }
                    break;
                case Backspace:
                    if (currPromptCol > 0) {
                        // Overwrite the buffer so that after modifying the currInstruction, the terminal will show the correctly
                        // edited instruction.
                        textGraphics.putString(0, currLine, getSpacesStringOfLength(PROMPT.length() + currInstruction.length()));
                        currInstruction.deleteCharAt(currPromptCol - 1);
                        currPromptCol--;
                    } else {
                        terminal.bell();
                    }
                    break;
                case Enter:
                    if (currInstruction.length() > 0) {
                        prevInstructions.push(currInstruction.toString());
                        instructionIndex = prevInstructions.size();
                        currInstruction.delete(0, currInstruction.length());
                        // Setup the cursor for potential output from inputHandler.
                        if (++currLine >= terminal.getTerminalSize().getRows()) {
                            terminal.scrollLines(0, currLine - 1, 1);
                        }
                        terminal.setCursorPosition(0, currLine);
                        inputHandler.apply(prevInstructions.peek());
                        currLine = terminal.getCursorPosition().getRow();
                    } else {
                        currLine++;
                    }
                    if (currLine >= terminal.getTerminalSize().getRows()) {
                        /*
               Note that currLine is potentially pointing ahead of the last row shown in the terminal
               currently because the inputHandler may have output multiple lines. In this case, this
               scrollLines method is being told to scroll lines that are currently below the fold, but
               it appears that it handles this well.
              */
                        terminal.scrollLines(0, currLine, 1);
                    }
                    currPromptCol = 0;
                    break;
            }
            // Print the currInstruction in two parts to leave the cursor exactly where the user expects it.
            textGraphics.putString(0, currLine, PROMPT + currInstruction.toString(), SGR.BOLD);
            textGraphics.putString(0, currLine, PROMPT + currInstruction.substring(0, currPromptCol));
            terminal.flush();
            keyStroke = terminal.readInput();
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (terminal != null) {
            try {
                terminal.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
Also used : DefaultTerminalFactory(com.googlecode.lanterna.terminal.DefaultTerminalFactory) UnixTerminal(com.googlecode.lanterna.terminal.ansi.UnixTerminal) TextGraphics(com.googlecode.lanterna.graphics.TextGraphics) KeyStroke(com.googlecode.lanterna.input.KeyStroke) IOException(java.io.IOException) Stack(java.util.Stack)

Aggregations

TextGraphics (com.googlecode.lanterna.graphics.TextGraphics)1 KeyStroke (com.googlecode.lanterna.input.KeyStroke)1 DefaultTerminalFactory (com.googlecode.lanterna.terminal.DefaultTerminalFactory)1 UnixTerminal (com.googlecode.lanterna.terminal.ansi.UnixTerminal)1 IOException (java.io.IOException)1 Stack (java.util.Stack)1