/** * Move the cursor <i>where</i> characters, withough checking the current buffer. * * @see #where * @param where the number of characters to move to the right or left. */ private final void moveInternal(final int where) throws IOException { // debug ("move cursor " + where + " (" // + buf.cursor + " => " + (buf.cursor + where) + ")"); buf.cursor += where; char c; if (where < 0) { int len = 0; for (int i = buf.cursor; i < buf.cursor - where; i++) { if (buf.getBuffer().charAt(i) == '\t') len += TAB_WIDTH; else len++; } char cbuf[] = new char[len]; Arrays.fill(cbuf, BACKSPACE); out.write(cbuf); return; } else if (buf.cursor == 0) { return; } else if (mask != null) { c = mask.charValue(); } else { printCharacters(buf.buffer.substring(buf.cursor - where, buf.cursor).toCharArray()); return; } // null character mask: don't output anything if (NULL_MASK.equals(mask)) { return; } printCharacters(c, Math.abs(where)); }
private final boolean deletePreviousWord() throws IOException { while (isDelimiter(buf.current()) && backspace()) {; } while (!isDelimiter(buf.current()) && backspace()) {; } return true; }
private final boolean nextWord() throws IOException { while (isDelimiter(buf.current()) && (moveCursor(1) != 0)) {; } while (!isDelimiter(buf.current()) && (moveCursor(1) != 0)) {; } return true; }
/** Output put the prompt + the current buffer */ public final void drawLine() throws IOException { if (prompt != null) { printString(prompt); } printString(buf.buffer.toString()); if (buf.length() != buf.cursor) // not at end of line back(buf.length() - buf.cursor); // sync }
/** Output the specified character, both to the buffer and the output stream. */ private final void putChar(final int c, final boolean print) throws IOException { buf.write((char) c); if (print) { // no masking... if (mask == null) { printCharacter(c); } // null mask: don't print anything... else if (mask.charValue() == 0) {; } // otherwise print the mask... else { printCharacter(mask.charValue()); } drawBuffer(); } }
/** * Clear the buffer and add its contents to the history. * * @return the former contents of the buffer. */ final String finishBuffer() { String str = buf.buffer.toString(); // we only add it to the history if the buffer is not empty // and if mask is null, since having a mask typically means // the string was a password. We clear the mask after this call if (str.length() > 0) { if (mask == null && useHistory) { history.addToHistory(str); } else { mask = null; } } history.moveToEnd(); buf.buffer.setLength(0); buf.cursor = 0; return str; }
/** Write out the specified string to the buffer and the output stream. */ public final void putString(final String str) throws IOException { buf.write(str); printString(str); drawBuffer(); }
/** * Read a line from the <i>in</i> {@link InputStream}, and return the line (without any trailing * newlines). * * @param prompt the prompt to issue to the console, may be null. * @return a line that is read from the terminal, or null if there was null input (e.g., * <i>CTRL-D</i> was pressed). */ public String readLine(final String prompt, final Character mask) throws IOException { this.mask = mask; if (prompt != null) this.prompt = prompt; try { terminal.beforeReadLine(this, this.prompt, mask); if ((this.prompt != null) && (this.prompt.length() > 0)) { out.write(this.prompt); out.flush(); } // if the terminal is unsupported, just use plain-java reading if (!terminal.isSupported()) { return readLine(in); } while (true) { int[] next = readBinding(); if (next == null) { return null; } int c = next[0]; int code = next[1]; if (c == -1) { return null; } boolean success = true; switch (code) { case EXIT: // ctrl-d if (buf.buffer.length() == 0) { return null; } case COMPLETE: // tab success = complete(); break; case MOVE_TO_BEG: success = setCursorPosition(0); break; case KILL_LINE: // CTRL-K success = killLine(); break; case CLEAR_SCREEN: // CTRL-L success = clearScreen(); break; case KILL_LINE_PREV: // CTRL-U success = resetLine(); break; case NEWLINE: // enter moveToEnd(); printNewline(); // output newline return finishBuffer(); case DELETE_PREV_CHAR: // backspace success = backspace(); break; case DELETE_NEXT_CHAR: // delete success = deleteCurrentCharacter(); break; case MOVE_TO_END: success = moveToEnd(); break; case PREV_CHAR: success = moveCursor(-1) != 0; break; case NEXT_CHAR: success = moveCursor(1) != 0; break; case NEXT_HISTORY: success = moveHistory(true); break; case PREV_HISTORY: success = moveHistory(false); break; case REDISPLAY: break; case PASTE: success = paste(); break; case DELETE_PREV_WORD: success = deletePreviousWord(); break; case PREV_WORD: success = previousWord(); break; case NEXT_WORD: success = nextWord(); break; case START_OF_HISTORY: success = history.moveToFirstEntry(); if (success) setBuffer(history.current()); break; case END_OF_HISTORY: success = history.moveToLastEntry(); if (success) setBuffer(history.current()); break; case CLEAR_LINE: moveInternal(-(buf.buffer.length())); killLine(); break; case INSERT: buf.setOvertyping(!buf.isOvertyping()); break; case UNKNOWN: default: if (c != 0) { // ignore null chars ActionListener action = (ActionListener) triggeredActions.get(new Character((char) c)); if (action != null) action.actionPerformed(null); else putChar(c, true); } else success = false; } if (!(success)) { beep(); } flushConsole(); } } finally { terminal.afterReadLine(this, this.prompt, mask); } }