Clojure's vars maintain bindings in ThreadLocals[1]. I'm pretty sure accessing ThreadLocals of other threads can't be done. Looking at ThreadLocal and Thread sources, you might be able to dig around private and package-private fields to get at them. Generally a bad idea.
FWIW, the Enclojure REPL is available as a standalone Swing component[2], which may or may not be a good basis for your work. Also FWIW, you might want to take a look at nREPL[3], which is an attempt to provide a common network-capable Clojure REPL (currently used by ccw and vimclojure AFAIK). The benefit for you there would be that the thread-local state of each REPL connection (its "session", for lack of a better term) can be queried at will, asynchronously from code that your users might want to send to the REPL. Cheers, - Chas [1] http://download.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html [2] http://www.enclojure.org/The+Enclojure+REPLs+%28Not+just+for+Netbeans!%29 [3] https://github.com/clojure/tools.nrepl On Dec 30 2010, 11:34 am, Mike <cki...@gmail.com> wrote: > 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 -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en