Commit e769e8fd authored by Tony Mancill's avatar Tony Mancill

Imported Upstream version 0.8.0.1+dfsg

parent 5bc022c1
package bsh.util;
import org.gnu.readline.ReadlineCompleter;
/**
* An adapter for org.gnu.readline's ReadlineCompleter interface to map to
* BeanShell's NameCompleter interface.
*
* @see org.gnu.readline.ReadlineReader
* @version $Revision: 1.1 $
* @author Shane Celis <shane@terraspring.com>
**/
public class BshCompleter implements ReadlineCompleter {
private NameCompletion completer;
/**
* Constructs a <code>ReadlineCompleter</code> out of a
* <code>NameCompleter</code> object.
**/
public BshCompleter(NameCompletion completer) {
this.completer = completer;
}
/**
* Returns String of completion if unambiguous, otherwise null
**/
public String completer(String text, int state) {
// Not sure what state is used for in ReadlineCompleter
String[] completions = completer.completeName(text);
if (completions.length == 1 && state == 0) {
return completions[0];
} else {
return null; // ambiguous result
}
}
}
This diff is collapsed.
37a38,43
> import java.io.File; // why? I don't know
> import bsh.util.BshCompleter;
> import bsh.util.NameCompletionTable;
> import bsh.classpath.ClassManagerImpl;
> import org.gnu.readline.Readline;
> import org.gnu.readline.ReadlineReader;
104a111
>
221a229
>
225a234
>
358c367,393
< Reader in = new CommandLineReader( new InputStreamReader(src));
---
> Reader in = null;
> boolean usingReadline = false;
> try {
> File history = new File(System.getProperty("user.home") +
> File.separator + ".bsh_history");
> if (!history.exists()) {
> try {
> history.createNewFile();
> } catch(IOException ioe) {
> debug("Unable to create history file: " + history.getAbsolutePath());
> }
> }
> // should I wrap CommandLineReader around it?
> if (history.canWrite() && history.canRead()) {
> in = new ReadlineReader("bsh % ", history,ReadlineLibrary.Editline);
> } else {
> in = new ReadlineReader("bsh % ",ReadlineLibrary.Editline);
> debug("Unable to read/write history file: " + history.getAbsolutePath());
> }
> } catch (IOException ioe) {
> System.err.println("Unable to invoke ReadlineReader " +
> "due to: " + ioe);
> }
> if (in == null)
> in = new CommandLineReader( new InputStreamReader(src));
> else
> usingReadline = true;
360a396,414
> if (usingReadline) {
> NameCompletionTable nct = new NameCompletionTable();
> nct.add(interpreter.getNameSpace());
>
> /** ClassManager does a lot of chatting to the stdout,
> * so this has been commented out for the time being
> **/
>
> // try {
> // BshClassManager bcm = BshClassManager.getClassManager();
> // if (bcm != null) {
> // nct.add(((ClassManagerImpl)bcm).getClassPath());
> // }
> // } catch(ClassPathException cpe) {
> // debug("classpath exception in name compl:" + cpe);
> // }
>
> Readline.setCompleter(new BshCompleter(nct));
> }
399c453
< if(interactive)
---
> if(interactive && !(in instanceof ReadlineReader))
496c550,556
< if ( interactive && !noExitOnEOF )
---
> if ( interactive && !noExitOnEOF ) {
> /* should be done for all streams in general, but this
> * ensures that the history for readline is flushed */
> try {
> in.close();
> } catch (IOException ioe) {
> }
498a559
> }
To use JavaReadline with BeanShell, you must replace one class
(bsh.Interpreter) in bsh.jar and add another one (bsh.bshCompleter).
The sourcecode for both files is provided in this package. Just
compile both files and use the jar utility from the JDK. Note that the
1.2 version has an update flag (this makes things easier). With 1.1
you have to extract the whole archive, replace the given class files
and create the archive again.
(This readme was shamelessly stolen and modified with little more than
substitution tricks from the jpython mod for readline.)
-Shane Celis <shane@terraspring.com>
Note: starting from JavaReadline 0.6, you have the choice of various backing
readline implementations. Since the license of BSH does not conform to the
GPL, it cannot be used together with GNU-Readline.
As a consequence, the backing implementation for BeanShell is Editline,
and I modified ReadlineReader, Interpreter.java and Interpreter.java.diff
accordingly.
Bernhard
\ No newline at end of file
Note: JPython is now Jython, and there have been
some changes, so the original description of what
to do to make Jython work with JavaReadline
does not apply anymore.
However, there has been a posting to the jython-users
mailing-list describing what to do (see the file
jython-install.txt). For Debian-users, things should
be much simpler, because Jython is already packaged
to use JavaReadline with EditLine as backing library.
// Copyright Corporation for National Research Initiatives
package org.python.util;
import org.python.core.*;
import org.gnu.readline.*;
// Based on CPython-1.5.2's code module
public class ReadlineConsole extends InteractiveConsole {
public String filename;
public ReadlineConsole() {
this(null, "<console>");
}
public ReadlineConsole(PyObject locals) {
this(locals, "<console>");
}
public ReadlineConsole(PyObject locals, String filename) {
super(locals,filename);
try {
Readline.load(ReadlineLibrary.Editline);
} catch (Exception e) {
}
Readline.initReadline("jpython");
}
/**
* Write a prompt and read a line.
*
* The returned line does not include the trailing newline. When the
* user enters the EOF key sequence, EOFError is raised.
*
* This subclass implements the functionality using JavaReadline.
**/
public String raw_input(PyObject prompt) {
try {
return Readline.readline(prompt==null ? "" : prompt.toString());
} catch (java.io.EOFException eofe) {
throw new PyException(Py.EOFError);
} catch (java.io.IOException ioe) {
throw new PyException();
} catch (java.io.UnsupportedEncodingException e) {
throw new PyException();
}
}
}
*** jpython.java Sun Oct 24 08:54:59 1999
--- jpython.java.orig Sun Oct 24 08:53:46 1999
***************
*** 80,91 ****
// Now create an interpreter
! InteractiveConsole interp = null;
! try {
! interp = (InteractiveConsole) Class.forName(
! PySystemState.registry.getProperty("python.console",
! "org.python.util.InteractiveConsole")).newInstance();
! } catch (Exception e) {
! interp = new InteractiveConsole();
! }
//System.err.println("interp");
PyModule mod = imp.addModule("__main__");
--- 80,84 ----
// Now create an interpreter
! InteractiveConsole interp = new InteractiveConsole();
//System.err.println("interp");
PyModule mod = imp.addModule("__main__");
// Copyright Corporation for National Research Initiatives
package org.python.util;
import org.python.core.*;
import java.util.zip.*;
import java.io.*;
public class jpython
{
private static String usage =
"usage: jpython [options] [-jar jar | -c cmd | file | -] [args]\n"+
"Options and arguments:\n"+
"-i : inspect interactively after running script, and force\n"+
" prompts, even if stdin does not appear to be a terminal\n"+
"-S : don't imply `import site' on initialization\n"+
"-X : disable class based standard exceptions\n"+
"-Dprop=v : Set the property `prop' to value `v'\n"+
"-jar jar : program read from __run__.py in jar file\n"+
"-c cmd : program passed in as string (terminates option list)\n"+
"file : program read from script file\n"+
"- : program read from stdin (default; interactive mode if a "+
"tty)\n"+
"--help : print this usage message and exit\n"+
"--version: print JPython version number and exit\n"+
"args : arguments passed to program in sys.argv[1:]";
public static void runJar(String filename) {
// TBD: this is kind of gross because a local called `zipfile' just
// magically shows up in the module's globals. Either `zipfile'
// should be called `__zipfile__' or (preferrably, IMO), __run__.py
// should be imported and a main() function extracted. This
// function should be called passing zipfile in as an argument.
//
// Probably have to keep this code around for backwards
// compatibility (?)
try {
ZipFile zip = new ZipFile(filename);
ZipEntry runit = zip.getEntry("__run__.py");
if (runit == null)
throw Py.ValueError("jar file missing '__run__.py'");
PyStringMap locals = new PyStringMap();
locals.__setitem__("__name__", new PyString(filename));
locals.__setitem__("zipfile", Py.java2py(zip));
InputStream file = zip.getInputStream(runit);
PyCode code;
try {
code = Py.compile(file, "__run__", "exec");
} finally {
file.close();
}
Py.runCode(code, locals, locals);
} catch (java.io.IOException e) {
throw Py.IOError(e);
}
}
public static void main(String[] args) {
// Parse the command line options
CommandLineOptions opts = new CommandLineOptions();
if (!opts.parse(args)) {
if (opts.version) {
System.err.println(InteractiveConsole.getDefaultBanner());
System.exit(0);
}
System.err.println(usage);
int exitcode = opts.help ? 0 : -1;
System.exit(exitcode);
}
// Setup the basic python system state from these options
PySystemState.initialize(System.getProperties(),
opts.properties, opts.argv);
if (opts.notice) {
System.err.println(InteractiveConsole.getDefaultBanner());
}
// Now create an interpreter
InteractiveConsole interp = null;
try {
interp = (InteractiveConsole) Class.forName(
PySystemState.registry.getProperty("python.console",
"org.python.util.InteractiveConsole")).newInstance();
} catch (Exception e) {
interp = new InteractiveConsole();
}
//System.err.println("interp");
PyModule mod = imp.addModule("__main__");
interp.setLocals(mod.__dict__);
//System.err.println("imp");
if (Options.importSite) {
try {
imp.load("site");
} catch (PyException pye) {
if (!Py.matchException(pye, Py.ImportError)) {
System.err.println("error importing site");
Py.printException(pye);
System.exit(-1);
}
}
}
if (opts.command != null) {
try {
interp.exec(opts.command);
} catch (Throwable t) {
Py.printException(t);
}
}
// was there a filename on the command line?
if (opts.filename != null) {
String path = new java.io.File(opts.filename).getParent();
if (path == null)
path = "";
Py.getSystemState().path.insert(0, new PyString(path));
if (opts.jar) {
runJar(opts.filename);
} else if (opts.filename.equals("-")) {
try {
interp.execfile(System.in, "<stdin>");
} catch (Throwable t) {
Py.printException(t);
}
} else {
try {
interp.execfile(opts.filename);
} catch (Throwable t) {
Py.printException(t);
}
}
}
else {
// if there was no file name on the command line, then "" is
// the first element on sys.path. This is here because if
// there /was/ a filename on the c.l., and say the -i option
// was given, sys.path[0] will have gotten filled in with the
// dir of the argument filename.
Py.getSystemState().path.insert(0, new PyString(""));
}
if (opts.interactive) {
try {
interp.interact(null);
} catch (Throwable t) {
Py.printException(t);
}
}
}
}
class CommandLineOptions
{
public String filename;
public boolean jar, interactive, notice;
private boolean fixInteractive;
public boolean help, version;
public String[] argv;
public java.util.Properties properties;
public String command;
public CommandLineOptions() {
filename = null;
jar = fixInteractive = false;
interactive = notice = true;
properties = new java.util.Properties();
help = version = false;
}
public void setProperty(String key, String value) {
properties.put(key, value);
// This only works for Java 1.2. There appears to be no portable
// way to support this under Java 1.1
// try {
// System.setProperty(key, value);
// }
// catch (SecurityException e) {}
}
public boolean parse(String[] args) {
int index=0;
while (index < args.length && args[index].startsWith("-")) {
String arg = args[index];
if (arg.equals("--help")) {
help = true;
return false;
}
else if (arg.equals("--version")) {
version = true;
return false;
}
else if (arg.equals("-")) {
if (!fixInteractive)
interactive = false;
filename = "-";
}
else if (arg.equals("-i")) {
fixInteractive = true;
interactive = true;
}
else if (arg.equals("-jar")) {
jar = true;
if (!fixInteractive)
interactive = false;
}
else if (arg.equals("-X")) {
Options.classBasedExceptions = false;
}
else if (arg.equals("-S")) {
Options.importSite = false;
}
else if (arg.equals("-c")) {
command = args[++index];
if (!fixInteractive) interactive = false;
break;
}
else if (arg.startsWith("-D")) {
String key = null;
String value = null;
int equals = arg.indexOf("=");
if (equals == -1) {
String arg2 = args[++index];
key = arg.substring(2, arg.length());
value = arg2;
}
else {
key = arg.substring(2, equals);
value = arg.substring(equals+1, arg.length());
}
setProperty(key, value);
}
else {
String opt = args[index];
if (opt.startsWith("--"))
opt = opt.substring(2);
else if (opt.startsWith("-"))
opt = opt.substring(1);
System.err.println("jpython: illegal option -- " + opt);
return false;
}
index += 1;
}
notice = interactive;
if (filename == null && index < args.length && command == null) {
filename = args[index++];
if (!fixInteractive)
interactive = false;
notice = false;
}
if (command != null)
notice = false;
int n = args.length-index+1;
argv = new String[n];
//new String[args.length-index+1];
if (filename != null)
argv[0] = filename;
else argv[0] = "";
for(int i=1; i<n; i++, index++) {
argv[i] = args[index];
}
return true;
}
}
From SteveC@ignitesports.com Sun Dec 30 17:10:46 2001
For about the third time, I have spent a few hours getting the readline
library worked into jython. (It happens every time I install a new
jython and it changes a little bit each time.) You would think this
annoying mess would get documented somewhere, but it hasn't, anywhere,
correctly, in spite of several halfway attempts to do so. And much of
the documentation is out of date.
So please, guys, make it a New Year's resolution to get this into the
official docs, somewhere. Here is a start, it worked for me:
What you have to do to get Jython and Readline working (These
instructions work for GNUReadline on my RedHat Linux system - your
mileage may vary):
Note: there is another option called Editline but Bernhard Bablok, the
author of gnu java_readline says he couldn't get it working, so I didn't
even try. Nonetheless, Editline is the default in jython according to
the source code in ReadlineConsole.java. (See item #9 below ) If this
is going to be the case, then the jython docs should give more info
about it or work it into the standard distribution somehow.
1. Download and install the javacc from
http://www.webgain.com/products/java_cc/. You can't build jython
without this.
2. Download the java-readline source from
http://www.bablokb.de/java/readline.html
3. Make the java_readline jar and backing library using the Makefile
supplied.
4. Deploy these into your system lib directory. (/usr/lib in my case)
5. Download the latest Jython sources from SourceForge.
6. Create/Modify an ant.properties file in the same directory as the
build.xml for jython and add the property readline.jar giving it the
value of a path to the java_readline.jar you deployed in step 3, as
well as the path to javacc and any other optional jars you wish to
include.
7. Build jython and deploy it.
8. Modify the jython shell script so as to precede the supplied command
(java -Dpython.home=...) with 'LD_LIBRARY_PATH="/usr/lib"'
9. Modify your registry file to add the line
python.console.readlinelib=GnuReadline
As far as I know this one isn't documented anywhere and if you don't put
it in, the system tries to find Editline and throws an exception if it
can't. I only pieced it together from reading the source code for
jython's ReadlineConsole and for the gnu java readline.
After all that, you finally have a console that recognizes the arrow
keys for history when on the last line. Way too complicated.
So while I thank the Jython developers and Mr. Bablok for their efforts
and for making this possible at all, please, someone, make this easier
or at least pull all the documentation into one place.
package samer.silk;
import java.util.*;
import org.gnu.readline.*;
import jsint.*;
/**
This completer works with the JScheme scheme
interpreter by looking up symbols in the global
namespace. You can register it with the Java
Readline library either in Java or in scheme. Something
like the following should do it:
<pre>
;;; Switches JScheme's input port to a new one that uses
;;; a ReadlineReader with a ">" prompt.
;;; (Note that on some systems, you might get a double
;;; prompt "> >" because JScheme's main loop also prints
;;; a prompt. If this bugs you a lot, you can just write your
;;; own main loop to replace jsint.Scheme.readEvalWriteLoop().)
(set! jsint.Scheme.input$ (jsint.InputPort.
(org.gnu.readline.ReadlineReader. "> "
org.gnu.readline.ReadlineLibrary.GnuReadline$)))
;;; not sure that this helps a lot, but I suppose it's good practice...
(.addShutdownHook (Runtime.getRuntime)
(Thread. (lambda ()
(display "cleaning up readline.\n")
(org.gnu.readline.Readline.cleanup))))
;;; set Readline's completer to a new Scheme-aware one
(org.gnu.readline.Readline.setCompleter (samer.silk.SilkCompleter.))
</pre>
Author: Samer Abdallah (samer.abdallah@elec.qmul.ac.uk)
November 2002
*/
public class SilkCompleter implements ReadlineCompleter {
Iterator it; // iterates over symbols in JScheme hashtable
/** Implementation of abstract function. Finds
possible completions of the given text. */
public String completer(String text, int state)
{
if (state == 0) { // first call to completer(): initialize iterator
// it=Symbol.symbolTable.entrySet().iterator();
it=Symbol.symbolTable.values().iterator();
}
while (it.hasNext()) { // subsequent calls
// Map.Entry entry = (Map.Entry)it.next();
// Symbol symbol=(Symbol)entry.getValue();
// String name=(String)entry.getKey();
Symbol symbol=(Symbol)it.next();
String name=(String)symbol.toString();
// Jscheme seems to keep a lot of undefined symbols
// in the table---pretty much anything you type, actually.
// so we check and only return defined symbols.
if (name.startsWith(text) && symbol.isDefined()) return name;
}
return null; // we reached the last choice.
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment