Index: src/jvm/clojure/lang/Repl.java
===================================================================
--- src/jvm/clojure/lang/Repl.java	(revision 1024)
+++ src/jvm/clojure/lang/Repl.java	(working copy)
@@ -14,6 +14,7 @@
 
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
+import java.io.IOException;
 
 public class Repl{
 static final Symbol USER = Symbol.create("user");
@@ -23,6 +24,9 @@
 static final Var refer = RT.var("clojure", "refer");
 static final Var ns = RT.var("clojure", "*ns*");
 static final Var warn_on_reflection = RT.var("clojure", "*warn-on-reflection*");
+static final Var repl_last_read = RT.var("clojure", "*repl-last-read*");
+static final Var repl_last_eval = RT.var("clojure", "*repl-last-eval*");
+static final Var repl_last_exception = RT.var("clojure", "*repl-last-exception*");
 
 public static void main(String[] args) throws Exception{
 
@@ -56,6 +60,8 @@
 		LineNumberingPushbackReader rdr = new LineNumberingPushbackReader(new InputStreamReader(System.in,RT.UTF8));
 		OutputStreamWriter w = (OutputStreamWriter) RT.OUT.get();//new OutputStreamWriter(System.out);
 		Object EOF = new Object();
+		repl_last_read.bindRoot(null);
+		repl_last_eval.bindRoot(null);
 
 		//start the loop
 		w.write("Clojure\n");
@@ -65,17 +71,32 @@
 				{
 				w.write(Compiler.currentNS().name + "=> ");
 				w.flush();
-				Object r = LispReader.read(rdr, false, EOF, false);
+				int ch;
+				do ch=rdr.read();
+				while (Character.isWhitespace(ch));
+				if (ch == ',') {
+					doCommaCommand(readCommaCommand(rdr));
+					continue;
+				}
+				repl_last_read.bindRoot(null);
+				Object r = EOF;
+				if (ch != -1)
+					{
+					rdr.unread(ch);
+					r = LispReader.read(rdr, false, EOF, false);
+					}
 				if(r == EOF)
 					{
 					w.write("\n");
 					w.flush();
 					break;
 					}
+				repl_last_read.bindRoot(r);
 				Object ret = Compiler.eval(r);
 				RT.print(ret, w);
 				w.write('\n');
 				//w.flush();
+				repl_last_eval.bindRoot(ret);
 				}
 			catch(Throwable e)
 				{
@@ -83,7 +104,8 @@
 				while(c.getCause() != null)
 					c = c.getCause();
 				System.err.println(c);
-				e.printStackTrace();
+				repl_last_eval.bindRoot(e);
+				repl_last_exception.bindRoot(e);
 				}
 			}
 		}
@@ -98,4 +120,62 @@
 	System.exit(0);
 }
 
+public static String readCommaCommand(LineNumberingPushbackReader rdr) throws IOException{
+
+	StringBuilder sb = new StringBuilder();
+	for(; ;)
+	    {
+		int ch = rdr.read();
+		if(ch == -1 || ch == '\n')
+		    {
+			if (ch == -1)
+				rdr.unread(ch);
+			return sb.toString();
+		    }
+		sb.append((char) ch);
+	    }
 }
+
+public static void doCommaCommand(String command) throws Exception{
+
+	if (command.equals("s"))
+	    {
+		if (!repl_last_exception.isBound())
+		    {
+			System.err.println("no exceptions yet!");
+			return;
+		    }
+		((Throwable) repl_last_exception.get()).printStackTrace();
+		}
+	else if (command.equals("r"))
+	    {
+		OutputStreamWriter w = new OutputStreamWriter(System.err);
+    	RT.print(repl_last_read.get(), w);
+		w.write('\n');
+		w.flush();
+		}
+	else if (command.equals("e"))
+	    {
+		OutputStreamWriter w = new OutputStreamWriter(System.err);
+    	RT.print(repl_last_eval.get(), w);
+		w.write('\n');
+		w.flush();
+	    }
+	else if (command.equals("h") || command.equals("?"))
+		printCommaCommandHelp();
+	else
+    	{
+		System.err.println("unrecognized comma command: " + command);
+		printCommaCommandHelp();
+		}
+}
+
+public static void printCommaCommandHelp(){
+		System.err.println("Comma Commands");
+		System.err.println(",s    Show the most recent exception's stack trace");
+		System.err.println(",r    Show the most recent object returned by read");
+		System.err.println(",e    Show the most recent object returned by eval");
+		System.err.println(",h    Show this help");
+		System.err.println(",?    Show this help");
+}
+}
