I'm doing something kind of tricky...I'm running a REPL in my Java
Swing application. I do something like:
public class MyConsoleClass extends OurEmbeddedInterpreterClass {
// ...
// inner class
private class ReplRunner extends Thread {
public void run() {
Namespace MYNS = Namespace.findOrCreate(Symbol.create("myns"));
Var ACCESS_ME = Var.intern(MYNS, Symbol.create("*me*"));
Var.pushThreadBindings(RT.map(
RT.IN, myIn, RT.OUT, myOut,
RT.ERR, myErr, ACCESS_ME, MyConsoleClass.this);
BufferedReader script = getMagicInitScript();
Compiler.load(script, getScriptPath(), getScriptFile());
}
}
// ...somewhere, make a ReplRunner and launch it when you're
supposed to
}
The "magic init script" is what runs the repl. The ins and outs are
mapped into Swing components so you can type commands, it passes to
the repl, and then output comes back to a text pane or the equivalent.
Now, my GUI app puts a KeyListener on the input component so that when
the TAB key is pressed, it runs a completion routine (Java callback)
to try to complete your command. I wrote a function (in Clojure,
inside the magic init script) that returns all the completions based
on the current command. My Java callback looks like:
// a method in MyConsoleClass...CodeCompletion is our own little
helper struct...
public List<CodeCompletion> getCompletions(String cmd) {
Var getFn = RT.var("myns", "get-completions");
try {
List<CodeCompletion> result = (List<CodeCompletion>)
getFn.invoke(cmd);
return result;
catch(Exception e) { /* handle e omitted */ }
return null;
}
The problem is, get-completions uses dir-fn and ns-map to gather
bindings based on the context of the command. But it's being invoked
in the AWT event thread (which calls this getCompletions method), NOT
the ReplRunner thread that I launch (which is of course just looping
infinitely waiting on input). So all the local bindings (including
*me* that I bound in ReplRunner.run()) are missing from the results.
Does anybody have any ideas how I can jack into the repl thread to
grab the bindings from it? I don't think any of Clojure's concurrency
constructs will help me here, because I need to interfere with a
thread that's essentially blocked at the time of the (synchronous)
completion call.
Sorry if this isn't fully specified and hurried...I can't paste the
code directly here because of NDA. If you need more details I can
provide them.
Thanks in advance for any ideas...
Mike