diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-12-29 19:40:17 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-12-29 19:40:17 +0000 |
commit | 49063a9bba42d14f83474802b3240f13e75bcb36 (patch) | |
tree | 0a1fb640c7d29169df84c86bed9b22bfa641d437 /src/jvm/clojure | |
parent | db598ed1a8d2105f552e1dcdaf2b37b781f015e0 (diff) |
unified clojure.main, patch from Stephen C. Gilardi
Diffstat (limited to 'src/jvm/clojure')
-rw-r--r-- | src/jvm/clojure/lang/LineNumberingPushbackReader.java | 45 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Repl.java | 106 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Script.java | 68 | ||||
-rw-r--r-- | src/jvm/clojure/main.java | 41 |
4 files changed, 91 insertions, 169 deletions
diff --git a/src/jvm/clojure/lang/LineNumberingPushbackReader.java b/src/jvm/clojure/lang/LineNumberingPushbackReader.java index f722e867..ad81ce9a 100644 --- a/src/jvm/clojure/lang/LineNumberingPushbackReader.java +++ b/src/jvm/clojure/lang/LineNumberingPushbackReader.java @@ -18,6 +18,16 @@ import java.io.IOException; public class LineNumberingPushbackReader extends PushbackReader{
+// This class is a PushbackReader that wraps a LineNumberReader. The code
+// here to handle line terminators only mentions '\n' because
+// LineNumberReader collapses all occurrences of CR, LF, and CRLF into a
+// single '\n'.
+
+private static final int newline = (int) '\n';
+
+private boolean _atLineStart = true;
+private boolean _prev;
+
public LineNumberingPushbackReader(Reader r){
super(new LineNumberReader(r));
}
@@ -26,7 +36,40 @@ public int getLineNumber(){ return ((LineNumberReader) in).getLineNumber() + 1;
}
+public int read() throws IOException{
+ int c = super.read();
+ _prev = _atLineStart;
+ _atLineStart = (c == newline) || (c == -1);
+ return c;
+}
+
+public void unread(int c) throws IOException{
+ super.unread(c);
+ _atLineStart = _prev;
+}
+
public String readLine() throws IOException{
- return ((LineNumberReader)in).readLine();
+ int c = read();
+ String line;
+ switch (c) {
+ case -1:
+ line = null;
+ break;
+ case newline:
+ line = "";
+ break;
+ default:
+ String first = String.valueOf((char) c);
+ String rest = ((LineNumberReader)in).readLine();
+ line = (rest == null) ? first : first + rest;
+ _prev = false;
+ _atLineStart = true;
+ break;
+ }
+ return line;
+}
+
+public boolean atLineStart(){
+ return _atLineStart;
}
}
diff --git a/src/jvm/clojure/lang/Repl.java b/src/jvm/clojure/lang/Repl.java index 4a9153b2..9abe82aa 100644 --- a/src/jvm/clojure/lang/Repl.java +++ b/src/jvm/clojure/lang/Repl.java @@ -12,111 +12,11 @@ package clojure.lang; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; +import clojure.main; -public class Repl{ -static final Symbol USER = Symbol.create("user"); -static final Symbol CLOJURE = Symbol.create("clojure.core"); - -static final Var in_ns = RT.var("clojure.core", "in-ns"); -static final Var refer = RT.var("clojure.core", "refer"); -static final Var ns = RT.var("clojure.core", "*ns*"); -static final Var compile_path = RT.var("clojure.core", "*compile-path*"); -static final Var warn_on_reflection = RT.var("clojure.core", "*warn-on-reflection*"); -static final Var print_meta = RT.var("clojure.core", "*print-meta*"); -static final Var print_length = RT.var("clojure.core", "*print-length*"); -static final Var print_level = RT.var("clojure.core", "*print-level*"); -static final Var star1 = RT.var("clojure.core", "*1"); -static final Var star2 = RT.var("clojure.core", "*2"); -static final Var star3 = RT.var("clojure.core", "*3"); -static final Var stare = RT.var("clojure.core", "*e"); +class Repl { public static void main(String[] args) throws Exception{ - -// RT.init(); - - try - { - //*ns* must be thread-bound for in-ns to work - //thread-bind *warn-on-reflection* so it can be set! - //thread-bind *1,*2,*3,*e so each repl has its own history - //must have corresponding popThreadBindings in finally clause - Var.pushThreadBindings( - RT.map(ns, ns.get(), - warn_on_reflection, warn_on_reflection.get(), - print_meta, print_meta.get(), - print_length, print_length.get(), - print_level, print_level.get(), - compile_path, "classes", - star1, null, - star2, null, - star3, null, - stare, null)); - - //create and move into the user namespace - in_ns.invoke(USER); - refer.invoke(CLOJURE); - - //load any supplied files - for(String file : RT.processCommandLine(args)) - try - { - Compiler.loadFile(file); - } - catch(Exception e) - { - e.printStackTrace((PrintWriter) RT.ERR.get()); - } - - //repl IO support - LineNumberingPushbackReader rdr = new LineNumberingPushbackReader(new InputStreamReader(System.in, RT.UTF8)); - OutputStreamWriter w = (OutputStreamWriter) RT.OUT.get();//new OutputStreamWriter(System.out); - Object EOF = new Object(); - - //start the loop - w.write("Clojure\n"); - for(; ;) - { - try - { - w.write(Compiler.currentNS().name + "=> "); - w.flush(); - Object r = LispReader.read(rdr, false, EOF, false); - if(r == EOF) - { - w.write("\n"); - w.flush(); - break; - } - Object ret = Compiler.eval(r); - RT.print(ret, w); - w.write('\n'); - //w.flush(); - star3.set(star2.get()); - star2.set(star1.get()); - star1.set(ret); - } - catch(Throwable e) - { - Throwable c = e; - while(c.getCause() != null) - c = c.getCause(); - ((PrintWriter) RT.ERR.get()).println(e instanceof Compiler.CompilerException ? e : c); - stare.set(e); - } - } - } - catch(Exception e) - { - e.printStackTrace((PrintWriter) RT.ERR.get()); - } - finally - { - Var.popThreadBindings(); - } - System.exit(0); + main.legacy_repl(args); } - } diff --git a/src/jvm/clojure/lang/Script.java b/src/jvm/clojure/lang/Script.java index e67f85e9..84abbe59 100644 --- a/src/jvm/clojure/lang/Script.java +++ b/src/jvm/clojure/lang/Script.java @@ -12,73 +12,11 @@ package clojure.lang; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.IOException; -import java.util.List; -import java.util.Arrays; +import clojure.main; -/** - * <code>Script</code> provides a way to run one or more Clojure files - * from a command line. Example usage: - * <p> - * <pre>java -cp clojure.jar script1.clj @/dir/script2.clj -- [arguments]</pre> - * </p> - * <p> - * The example above will: - * <ol> - * <li>bind *command-line-args* to a seq containing the (optional) arguments provided - * after the two dashes (--); this provides a way to provide command-line arguments - * to your scripts</li> - * <li>load the Clojure file <i>at the filesystem path</i> <code>script1.clj</code></li> - * <li>load the Clojure file with the name <code>dir/script2.clj</code> <i>from the - * current Java classpath</i>. Files to be loaded from the classpath must be prefixed - * with a '@' character, and must be an "absolute path" to the classpath resource. - * Note that the "path" will be treated as absolute within the classpath, whether it is - * prefixed with a slash or not.</li> - * </ol> - * </p> - * <p> - * Any number of Clojure files can be provided as path arguments; these - * files are loaded in order, as if via <code>load-file</code>. Filesystem and classpath - * paths may be provided in any order, and be intermixed as necessary. - * </p> - * <p> - * Once the final script path has been loaded, the java process exits. - * </p> - */ -public class Script{ +class Script { public static void main(String[] args) throws Exception{ - try - { - for(String file : RT.processCommandLine(args)) - { - if (file.startsWith("@")) - { - // trim leading slash if it's there -- loadResourceScript prepends its - // own slash to every name it's given - RT.loadResourceScript(file.substring(file.startsWith("@/") ? 2 : 1)); - } - else - { - Compiler.loadFile(file); - } - } - } - finally - { - OutputStreamWriter w = (OutputStreamWriter) RT.OUT.get(); - try - { - w.flush(); - w.close(); - } - catch(IOException e) - { - e.printStackTrace((PrintWriter)RT.ERR.get()); - } - } + main.legacy_script(args); } } - diff --git a/src/jvm/clojure/main.java b/src/jvm/clojure/main.java new file mode 100644 index 00000000..50bc3434 --- /dev/null +++ b/src/jvm/clojure/main.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +package clojure; + +import clojure.lang.Symbol; +import clojure.lang.Namespace; +import clojure.lang.Var; +import clojure.lang.RT; + +public class main{ + +final static private Symbol CLOJURE_MAIN = Symbol.create("clojure.main"); +final static private Namespace CLOJURE_MAIN_NS = Namespace.findOrCreate(CLOJURE_MAIN); +final static private Var REQUIRE = Var.intern(RT.CLOJURE_NS, Symbol.create("require")); +final static private Var LEGACY_REPL = Var.intern(CLOJURE_MAIN_NS, Symbol.create("legacy-repl")); +final static private Var LEGACY_SCRIPT = Var.intern(CLOJURE_MAIN_NS, Symbol.create("legacy-script")); +final static private Var MAIN = Var.intern(CLOJURE_MAIN_NS, Symbol.create("main")); + +public static void legacy_repl(String[] args) throws Exception{ + REQUIRE.invoke(CLOJURE_MAIN); + LEGACY_REPL.invoke(RT.seq(args)); +} + +public static void legacy_script(String[] args) throws Exception{ + REQUIRE.invoke(CLOJURE_MAIN); + LEGACY_SCRIPT.invoke(RT.seq(args)); +} + +public static void main(String[] args) throws Exception{ + REQUIRE.invoke(CLOJURE_MAIN); + MAIN.applyTo(RT.seq(args)); +} +} |