package pad.prac1; import java.io.*; import java.util.Scanner; import java.util.regex.Pattern; public class EditableBufferedReader extends BufferedReader { /* * MODE DEFINITIONS */ public static final int DEL_BACKWARD = 0; public static final int DEL_FORWARD = 1; public static final int INSERT = 0; public static final int OVERWRITE = 1; /* * TYPE DEFINITIONS */ public static final int ESCAPE_SEQUENCE = 0; public static final int PRINTABLE = 1; public static final int NON_PRINTABLE = 2; /* KEY DEFINITIONS * * ESC (0x1B) starts an escape sequence * ESC+[+C (0x1B 0x5B 0x43) Cursor Forward * ESC+[+D (0x1B 0x5B 0x44) Cursor Backward * ESC+[+2+~ (0x1B 0x5B 0x32 0x7E) Insert * ESC+[+3+~ (0x1B 0x5B 0x33 0x7E) Delete forward * ESC+O+H (0x1B 0x4F 0x48) Home * ESC+O+F (0x1B 0x4F 0x46) End */ public static final int RETURN_KEY = 0x0D; public static final int BACKSPACE = 0x08; public static final int BACKSPACE_DEL = 0x7F; public static final int ESC = 0x1B; public static final int ESC_SEQ = 0x5B; public static final int FORWARD = 0x43; public static final int BACKWARD = 0x44; public static final int GOTO = 0x48; public static final int DEL = 0x33; public static final int TILDE = 0x7E; public static final int HOME_END = 0x4F; public static final int HOME = 0x48; public static final int END = 0x46; public static final int INSERT_KEY = 0x32; public static final int INS_SPACE = 0x40; public static final int DEL_CHAR = 0x50; public static final int EOF = 0x04; public static final int LINE_FEED = 0x0A; private Console console = new Console(); private Line line = new Line(console); private boolean endOfFile = false; public EditableBufferedReader(Reader in) { super(in); } public EditableBufferedReader(Reader in, int sz) { super(in,sz); } private void setRaw() throws IOException, InterruptedException { String[] cmd = {"/bin/sh", "-c", "stty raw -echo = 0x20 || character == EOF || character == BACKSPACE || character == RETURN_KEY) { switch(character) { case EOF: endOfFile = true; break; case BACKSPACE: case BACKSPACE_DEL: line.delChar(DEL_BACKWARD); break; case RETURN_KEY: character = LINE_FEED; default: line.addChar((char)character); break; } return; } } pattern = Pattern.compile("\\^\\[\\[(.{1}).*"); if(scanner.findWithinHorizon(pattern,3) != null) //escape sequence { int character = scanner.match().group(1).charAt(0); switch(character) { case FORWARD: line.setCursorTo(line.getCursorPosition()+1); break; case BACKWARD: line.setCursorTo(line.getCursorPosition()-1); break; case DEL: line.delChar(DEL_FORWARD); break; case INSERT_KEY: line.toggleMode(); break; } return; } pattern = Pattern.compile("\\^\\[O(\\w{1})"); if(scanner.findWithinHorizon(pattern,3) != null) //HOME or END { int character = (int)scanner.match().group(1).charAt(0); switch(character) { case HOME: line.setCursorTo(1); break; case END: line.setCursorTo(line.length()+1); break; } return; } } public int read() throws IOException { return super.read(); } public String readLine() { try { setRaw(); } catch (Exception e) { System.out.println("Couldn't set terminal in raw mode"); return ""; } try { while(!endOfFile) { parseKey(); } } catch(Exception e) { System.out.println("Error reading line"); return ""; } try { unsetRaw(); } catch (Exception e) { System.out.println("Couldn't unset raw mode"); return ""; } System.out.println(""); return line.toString(); } } /* TO-DO * * up/down keys (needs text to work) * pgup pgdown keys (goesto penultima linea visible) * read terminal size * update size dynamically * long strings wrap down * cursor keys skip final \n on a line * careful if overwrite mode and final character is \n */