package org.gnu.readline; import java.io.File; import java.io.Reader; import java.io.IOException; import java.io.EOFException; import java.io.UnsupportedEncodingException; /** * A <code>Reader</code> wrapper for the Readline classes. This seems * to work fine in conjunction with such classes as BufferedReader, * but it hasn't been tested well enough to see if this will work well * in all cases. * * This was implemented to make it easier to supplant Readline's * functionality [shrug] anywhere and everywhere, but specifically in * <a href="http://www.beanshell.org">BeanShell</a>. * * @version $Revision: 1.2 $ * @author Shane Celis <shane@terrapsring.com> **/ public class ReadlineReader extends Reader { public static final String DEFAULT_PROMPT = ""; private StringBuffer iBuff; private String iLineSeparator; private String iPrompt; private File iHistoryFile; /** * Constructs a ReadlineReader object with the given prompt. **/ public ReadlineReader(String prompt,ReadlineLibrary lib) { iBuff = new StringBuffer(); setPrompt(prompt); Readline.load(lib); Readline.initReadline("ReadlineReader"); iLineSeparator = System.getProperty("line.separator", "\n"); } /** * Constructs a ReadlineReader object with the default prompt. **/ public ReadlineReader(ReadlineLibrary lib) { this(DEFAULT_PROMPT,lib); } /** * Constructs a ReadlineReader object with an associated history * file. **/ public ReadlineReader(File history,ReadlineLibrary lib) throws IOException { this(DEFAULT_PROMPT,lib); Readline.readHistoryFile(history.getAbsolutePath()); iHistoryFile = history; // only set this if we can read the file } /** * Constructs a ReadlineReader object with an associated history * file and prompt. **/ public ReadlineReader(String prompt, File history,ReadlineLibrary lib) throws IOException { this(history,lib); setPrompt(prompt); } /** * Returns the current prompt. **/ public String getPrompt() { return iPrompt; } /** * Sets the prompt to the given value. **/ public void setPrompt(String prompt) { iPrompt = prompt; } /** * Reads what's given from <code>readline()</code> into a buffer. * When that buffer is emptied, <code>readline()</code> is called * again to replenish that buffer. This seems to work fine in * conjunction with such classes as BufferedReader, but it hasn't * been tested well enough to see if this will work well in all * cases. **/ public int read(char[] cbuf, int off, int len) throws IOException { try { if (iBuff.length() == 0) { String line = Readline.readline(iPrompt); iBuff.append((line == null ? "" : line) + iLineSeparator); } if (len > iBuff.length()) len = iBuff.length(); if (len == 0) return 0; char[] sbuf = iBuff.substring(0, len).toCharArray(); System.arraycopy(sbuf, 0, cbuf, off, len); iBuff.delete(0, len); return len; } catch (EOFException eof) { throw eof; } catch (UnsupportedEncodingException uee) { throw uee; } } /** * Nullifies all buffers and writes history file if one was given * at construction time. **/ public void close() throws IOException { iBuff = null; iPrompt = null; if (iHistoryFile != null) { Readline.writeHistoryFile(iHistoryFile.getAbsolutePath()); iHistoryFile = null; } } public static void main(String[] args) throws Exception { java.io.BufferedReader rd = new java.io.BufferedReader(new ReadlineReader("hmm ", new File("test"),ReadlineLibrary.GnuReadline)); String line; try { while ((line = rd.readLine()) != null) { System.out.println("got: " + line); } } finally { rd.close(); } } }