Commits

Meikel Brandmeyer  committed ea6199e Merge

Merge latest changes into nrepl branch

  • Participants
  • Parent commits b345b15, a5acda6

Comments (0)

Files changed (33)

 build
 ng
 .gradle
+local.gradle
 ebc7d51caa8f7aafdc916c4f681112f9be24444b v2.1.1
 3c4c4bc70e35280175aa9b60a2b438572619a692 v2.1.2
 d86f147b463088792300dc25a812a4ff43e604d6 v2.2.0
+b4e17e56720c6dd6ca8387dee533ad1fc05013d0 v2.3.0
-Copyright 2008,2009 (c) Meikel Brandmeyer.
+Copyright 2008-2011 (c) Meikel Brandmeyer.
 All rights reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy

File build.gradle

+buildscript {
+    repositories {
+        flatDir dirs: project(':').file('lib/build')
+    }
+    dependencies {
+        classpath "clojuresque:clojuresque:1.4.1"
+        classpath "local-dotgradle:local-dotgradle:1.0.0"
+    }
+}
+
+allprojects {
+    localDotGradle = project(':').file("local.gradle").absoluteFile
+    apply plugin: 'local-dotgradle'
+}
+
 subprojects {
     apply plugin: 'java-base'
 
     group = 'vimclojure'
-    version = '2.3.0-SNAPSHOT'
+    version = '2.4.0-SNAPSHOT'
 
     defaultTasks 'build'
 }
 
+apply plugin: 'clojure'
+
+defaultRepositories {
+    clojarsRepo()
+}
+
 project(':server') {
     apply plugin: 'clojure'
 
-    repositories {
-        clojureReleasesRepo()
+    defaultRepositories {
+        flatDir dirs: project(':').file('lib/build')
+        mavenCentral()
     }
 
     dependencies {
-        development 'org.clojure:clojure:1.2.0'
+        compile 'org.clojure:clojure:1.+'
     }
 
     uploadArchives {
     compileClojure.dependsOn compileJava
 }
 
+project(':gradle') {
+    apply plugin: 'groovy'
+    apply plugin: 'clojure'
+
+    dependencies {
+        compile gradleApi()
+        groovy localGroovy()
+    }
+
+    uploadArchives {
+        clojarsDeploy()
+    }
+}
+
+
 project(':client') {
     task nailgunClientZip(type: Zip) {
         archiveName = "vimclojure-nailgun-client-" + project.version + ".zip"
     }
 }
 
-task genCompletions(type: JavaExec.class) {
+task genCompletions(type: clojuresque.ClojureExec) {
     classpath = project.files(
-        project(':server').sourceSets.main.clojure.sourceDir,
+        project(':server').sourceSets.main.clojure.srcDirs,
         project(':server').sourceSets.main.classesDir,
         project(':server').sourceSets.main.compileClasspath
     )
-    main = "clojure.main"
-    args = [ "-e", "(require 'vimclojure.gencompletions)", "-e",
-        "(vimclojure.gencompletions/main " +
-            "'clojure.core " +
-            "'clojure.inspector " +
-            "'clojure.java.browse 'clojure.java.browse-ui 'clojure.java.io 'clojure.java.javadoc 'clojure.java.shell " +
-            "'clojure.main " +
-            "'clojure.pprint " +
-            "'clojure.repl " +
-            "'clojure.set " +
-            "'clojure.stacktrace " +
-            "'clojure.string " +
-            "'clojure.template " +
-            "'clojure.test 'clojure.test.tap 'clojure.test.junit " +
-            "'clojure.walk " +
-            "'clojure.xml " +
-            "'clojure.zip)"
+    main = "vimclojure.gencompletions/main"
+    args = [
+        "clojure.core",
+        "clojure.data",
+        "clojure.inspector",
+        "clojure.java.browse",
+        "clojure.java.browse-ui",
+        "clojure.java.io",
+        "clojure.java.javadoc",
+        "clojure.java.shell",
+        "clojure.main",
+        "clojure.pprint",
+        "clojure.repl",
+        "clojure.set",
+        "clojure.stacktrace",
+        "clojure.string",
+        "clojure.template",
+        "clojure.test",
+        "clojure.test.tap",
+        "clojure.test.junit",
+        "clojure.walk",
+        "clojure.xml",
+        "clojure.zip"
     ]
 }
 
-task runNailgun(type: JavaExec.class, dependsOn: project(':server').classes) {
+task runNailgun(type: JavaExec) {
+    dependsOn project(':server').classes
+    dependsOn project(':server').processResources
     classpath = project.files(
-        project(':server').sourceSets.main.clojure.sourceDir,
+        project(':server').sourceSets.main.clojure.srcDirs,
         project(':server').sourceSets.main.classesDir,
         project(':server').sourceSets.main.compileClasspath
     )

File gradle/src/main/groovy/vimclojure/gradle/NailgunTask.groovy

+/*-
+ * Copyright 2011 © Meikel Brandmeyer.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+package vimclojure.gradle
+
+import org.gradle.api.tasks.JavaExec
+
+class NailgunTask extends JavaExec {
+    def String nailgunServer = "127.0.0.1"
+    def int nailgunPort = 2113
+
+    public NailgunTask() {
+        main = "vimclojure.nailgun.NGServer"
+        fixUpArgs()
+    }
+
+    void setNailgunServer(String server) {
+        this.nailgunServer = server
+        fixUpArgs()
+    }
+
+    void setNailgunPort(int port) {
+        this.nailgunPort = port
+        fixUpArgs()
+    }
+
+    private void fixUpArgs() {
+        args = [ nailgunServer + ":" + nailgunPort ]
+    }
+}

File gradle/src/main/groovy/vimclojure/gradle/VimClojurePlugin.groovy

+/*-
+ * Copyright 2011 © Meikel Brandmeyer.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+package vimclojure.gradle
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+public class VimClojurePlugin implements Plugin<Project> {
+    public void apply(Project project) {
+        project.tasks.add(name: 'runNailgun', type: NailgunTask) {
+            dependsOn project.classes
+            classpath = project.files(
+                project.sourceSets.main.clojure.srcDirs,
+                project.sourceSets.main.classesDir,
+                project.configurations.testRuntime,
+                project.configurations.development
+            )
+        }
+    }
+}

File gradle/src/main/resources/META-INF/gradle-plugins/vimclojure.properties

+implementation-class=vimclojure.gradle.VimClojurePlugin

File lib/build/clojuresque-1.4.2.jar

Binary file added.

File lib/build/local-dotgradle-1.0.0.jar

Binary file added.

File lib/build/runtime-1.4.2.jar

Binary file added.

File server/src/main/clojure/vimclojure/backend.clj

 ;-
-; Copyright 2009 (c) Meikel Brandmeyer.
+; Copyright 2009-2011 (c) Meikel Brandmeyer.
 ; All rights reserved.
 ;
 ; Permission is hereby granted, free of charge, to any person obtaining a copy
               LineNumberReader PushbackReader)))
 
 ; Documentation:
+; Mirror this from clojure 1.3 to allow backwards compatibility.
+(def ^{:private true} special-doc-map
+  '{. {:url "java_interop#dot"
+       :forms [(.instanceMember instance args*)
+               (.instanceMember Classname args*)
+               (Classname/staticMethod args*)
+               Classname/staticField]
+       :doc "The instance member form works for both fields and methods.
+  They all expand into calls to the dot operator at macroexpansion time."}
+    def {:forms [(def symbol init?)]
+         :doc "Creates and interns a global var with the name
+  of symbol in the current namespace (*ns*) or locates such a var if
+  it already exists.  If init is supplied, it is evaluated, and the
+  root binding of the var is set to the resulting value.  If init is
+  not supplied, the root binding of the var is unaffected."}
+    do {:forms [(do exprs*)]
+        :doc "Evaluates the expressions in order and returns the value of
+  the last. If no expressions are supplied, returns nil."}
+    if {:forms [(if test then else?)]
+        :doc "Evaluates test. If not the singular values nil or false,
+  evaluates and yields then, otherwise, evaluates and yields else. If
+  else is not supplied it defaults to nil."}
+    monitor-enter {:forms [(monitor-enter x)]
+                   :doc "Synchronization primitive that should be avoided
+  in user code. Use the 'locking' macro."}
+    monitor-exit {:forms [(monitor-exit x)]
+                  :doc "Synchronization primitive that should be avoided
+  in user code. Use the 'locking' macro."}
+    new {:forms [(Classname. args*) (new Classname args*)]
+         :url "java_interop#new"
+         :doc "The args, if any, are evaluated from left to right, and
+  passed to the constructor of the class named by Classname. The
+  constructed object is returned."}
+    quote {:forms [(quote form)]
+           :doc "Yields the unevaluated form."}
+    recur {:forms [(recur exprs*)]
+           :doc "Evaluates the exprs in order, then, in parallel, rebinds
+  the bindings of the recursion point to the values of the exprs.
+  Execution then jumps back to the recursion point, a loop or fn method."}
+    set! {:forms[(set! var-symbol expr)
+                 (set! (. instance-expr instanceFieldName-symbol) expr)
+                 (set! (. Classname-symbol staticFieldName-symbol) expr)]
+          :url "vars#set"
+          :doc "Used to set thread-local-bound vars, Java object instance
+fields, and Java class static fields."}
+    throw {:forms [(throw expr)]
+           :doc "The expr is evaluated and thrown, therefore it should
+  yield an instance of some derivee of Throwable."}
+    try {:forms [(try expr* catch-clause* finally-clause?)]
+         :doc "catch-clause => (catch classname name expr*)
+  finally-clause => (finally expr*)
+
+  Catches and handles Java exceptions."}
+    var {:forms [(var symbol)]
+         :doc "The symbol must resolve to a var, and the Var object
+itself (not its value) is returned. The reader macro #'x expands to (var x)."}})
+
+(defn- special-doc
+  [namespace name-symbol]
+  (assoc (or (special-doc-map name-symbol)
+             (meta (ns-resolve namespace name-symbol)))
+         :name name-symbol
+         :special-form true))
+
+(defn- namespace-doc
+  [nspace]
+  (assoc (meta nspace) :name (ns-name nspace)))
+
+(defn- print-documentation [m]
+  (println "-------------------------")
+  (println (str (when-let [ns (:ns m)] (str (ns-name ns) "/")) (:name m)))
+  (cond
+    (:forms m) (doseq [f (:forms m)]
+                 (print "  ")
+                 (prn f))
+    (:arglists m) (prn (:arglists m)))
+  (if (:special-form m)
+    (do
+      (println "Special Form")
+      (println " " (:doc m))
+      (if (contains? m :url)
+        (when (:url m)
+          (println (str "\n  Please see http://clojure.org/" (:url m))))
+        (println (str "\n  Please see http://clojure.org/special_forms#"
+                      (:name m)))))
+    (do
+      (when (:macro m)
+        (println "Macro"))
+      (println " " (:doc m)))))
+
 (defn doc-lookup
   "Lookup up the documentation for the given symbols in the given namespace.
   The documentation is returned as a string."
   [namespace symbol]
-  (condp #(%1 %2) symbol
-    special-form-anchor
-    :>>
-    (fn [_]
-      (print-special-doc symbol "Special Form" (special-form-anchor symbol)))
+  (if-let [special-name ('{& fn catch try finally try} symbol)]
+    (print-documentation (special-doc namespace special-name))
+    (condp #(%1 %2) symbol
+      special-doc-map           :>> (fn [_]
+                                      (print-documentation
+                                        (special-doc namespace symbol)))
+      find-ns                   :>> #(print-documentation (namespace-doc %))
+      #(ns-resolve namespace %) :>> #(print-documentation (meta %))
+      (println
+        (str "'" symbol "' could not be found. Please check the spelling.")))))
 
-    syntax-symbol-anchor
-    :>>
-    (fn [_]
-      (print-special-doc symbol "Special Form" (syntax-symbol-anchor symbol)))
-
-    find-ns
-    :>>
-    (fn [nspace] (print-namespace-doc nspace))
-
-    #(ns-resolve namespace %)
-    :>>
-    (fn [v] (print-doc v))
-
-    (println
-      (str "'" symbol "' could not be found. Please check the spelling."))))
+(defn find-documentation
+  "Prints documentation for any var whose documentation or name
+  contains a match for re-string-or-pattern"
+  [re-string-or-pattern]
+    (let [re (re-pattern re-string-or-pattern)
+          ms (concat (mapcat #(sort-by :name (map meta (vals (ns-interns %))))
+                             (all-ns))
+                     (map namespace-doc (all-ns))
+                     (map special-doc (keys special-doc-map)))]
+      (doseq [m ms
+              :when (and (:doc m)
+                         (or (re-find (re-matcher re (:doc m)))
+                             (re-find (re-matcher re (str (:name m))))))]
+               (print-documentation m))))
 
 (defn javadoc-path-for-class
   "Translate the name of a Class to the path of its javadoc file."

File server/src/main/clojure/vimclojure/core.clj

+;-
+; Copyright 2011 (c) Meikel Brandmeyer.
+; All rights reserved.
+;
+; Permission is hereby granted, free of charge, to any person obtaining a copy
+; of this software and associated documentation files (the "Software"), to deal
+; in the Software without restriction, including without limitation the rights
+; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of the Software, and to permit persons to whom the Software is
+; furnished to do so, subject to the following conditions:
+;
+; The above copyright notice and this permission notice shall be included in
+; all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+; THE SOFTWARE.
+
+(ns vimclojure.core)
+
+(defn init-server
+  []
+  ; Check for doc macro. 1.2 in c.core, 1.3 in c.repl
+  (when-not (ns-resolve 'clojure.core 'doc)
+    (binding [*ns* *ns*]
+      (in-ns 'user)
+      (refer-clojure)
+      (use 'clojure.repl))))

File server/src/main/clojure/vimclojure/gencompletions.clj

 ; Copyright (c) 2008 Parth Malwankar
-; Copyright (c) 2008 Meikel Brandmeyer
+; Copyright (c) 2008-2011 Meikel Brandmeyer
 ; All rights reserved.
 ;
 ; A small script to generate a dictionary of Clojure's core

File server/src/main/clojure/vimclojure/nails.clj

 ;-
-; Copyright 2009 (c) Meikel Brandmeyer.
+; Copyright 2009-2011 (c) Meikel Brandmeyer.
 ; All rights reserved.
 ;
 ; Permission is hereby granted, free of charge, to any person obtaining a copy
      (.start))))
 
 (defn- make-stream-set
-  [in out err]
-  [(-> in InputStreamReader. LineNumberingPushbackReader.)
-   (-> out OutputStreamWriter.)
-   (-> err OutputStreamWriter. PrintWriter.)])
+  [in out err encoding]
+  [(-> in (InputStreamReader. encoding) LineNumberingPushbackReader.)
+   (-> out (OutputStreamWriter. encoding))
+   (-> err (OutputStreamWriter. encoding) PrintWriter.)])
 
 (defn- set-input-stream
   [#^ThreadLocalInputStream sys local]
   [#^NGContext ctx nail]
   (let [out          (ByteArrayOutputStream.)
         err          (ByteArrayOutputStream.)
-        [clj-in clj-out clj-err] (make-stream-set (.in ctx) out err)
-        encoding     (if-let [encoding (System/getProperty "clojure.vim.encoding")]
-                       encoding
-                       "UTF-8")
+        encoding     (System/getProperty "clojure.vim.encoding" "UTF-8")
+        [clj-in clj-out clj-err] (make-stream-set (.in ctx) out err encoding)
         sys-in       (set-input-stream System/in (.in ctx))
         sys-out      (set-output-stream System/out (PrintStream. out))
         sys-err      (set-output-stream System/err (PrintStream. err))
     (set-input-stream System/in sys-in)
     (set-output-stream System/out sys-out)
     (set-output-stream System/err sys-err)
-    (.print (.out ctx)
-            (print-str
-              (util/clj->vim
-                {:value  result
-                 :stdout (.toString out encoding)
-                 :stderr (.toString err encoding)})))
+    (let [output (.getBytes
+                   (print-str
+                     (util/clj->vim
+                       {:value  result
+                        :stdout (.toString out encoding)
+                        :stderr (.toString err encoding)}))
+                   encoding)]
+      (.write (.out ctx) output 0 (alength output)))
     (.flush (.out ctx))))
 
 (defmacro defnail
 (defnail FindDoc
   "Usage: ng vimclojure.nails.FindDoc"
   []
-  (find-doc (.readLine *in*)))
+  (backend/find-documentation (.readLine *in*)))
 
 (defnail JavadocPath
   "Usage: ng vimclojure.nails.JavadocPath [options]"
               (recur (read *in* false eof)))))
         (catch clojure.lang.LispReader$ReaderException exc
           (let [e (.getCause exc)]
-            (if (= "EOF while reading" (.getMessage e))
+            (if (.startsWith (.getMessage e) "EOF while reading")
               false
               (throw exc))))))))
 

File server/src/main/clojure/vimclojure/optional/clj_stacktrace.clj

 ;-
-; Copyright 2010 (c) Meikel Brandmeyer.
+; Copyright 2010-2011 (c) Meikel Brandmeyer.
 ; All rights reserved.
 ;
 ; Permission is hereby granted, free of charge, to any person obtaining a copy

File server/src/main/clojure/vimclojure/repl.clj

 ;-
-; Copyright 2009 (c) Meikel Brandmeyer.
+; Copyright 2009-2011 (c) Meikel Brandmeyer.
 ; All rights reserved.
 ;
 ; Permission is hereby granted, free of charge, to any person obtaining a copy
   (:require
     clojure.test)
   (:use
-     [vimclojure.util :only (stream->seq pretty-print pretty-print-causetrace)])
+    [vimclojure.util :only [resolve-and-load-namespace safe-var-get stream->seq
+                            pretty-print pretty-print-causetrace]])
   (:import
-     (clojure.lang Var Compiler LineNumberingPushbackReader)))
+    clojure.lang.Var
+    clojure.lang.Compiler
+    clojure.lang.LineNumberingPushbackReader))
 
 (def
-  #^{:doc
+  ^{:dynamic true :doc
   "A map holding the references to all running repls indexed by their repl id."}
   *repls*
   (atom {}))
     (swap! id inc)))
 
 (def
-  #^{:doc
+  ^{:dynamic true :doc
   "Set to true in the Repl if you want pretty printed results. Has no effect
   if clojure.contrib.pprint is not available."}
   *print-pretty*
   false)
 
-(defstruct
-  #^{:doc
-  "The structure for the Repl interface. Holds the state of a Repl between
-  invokations. The members correspond to the Vars as bound be with-binding."}
-  repl
-  :id :ns :warn-on-reflection :print-meta :print-length :print-level
-  :compile-path :command-line-args :expr1 :expr2 :expr3 :exception :test-out
-  :line)
+(defn add-binding
+  [bindings sym]
+  (if-let [v (resolve sym)]
+    (assoc bindings v (safe-var-get v))
+    bindings))
+
+(def bindable-vars
+  `[*warn-on-reflection* *print-meta* *print-length*
+    *print-level* *compile-path* *command-line-args*
+    *unchecked-math* *math-context* *1 *2 *3 *e
+    ; VimClojure specific.
+    *print-pretty*])
 
 (defn make-repl
   "Create a new Repl."
-  ([id] (make-repl id (the-ns 'user)))
+  ([id] (make-repl id nil))
   ([id namespace]
-   (struct-map repl
-               :id                 id
-               :ns                 namespace
-               :warn-on-reflection *warn-on-reflection*
-               :print-meta         *print-meta*
-               :print-length       *print-length*
-               :print-level        *print-level*
-               :compile-path       (System/getProperty
-                                     "clojure.compile.path"
-                                     "classes")
-               :command-line-args  nil
-               :expr1              nil
-               :expr2              nil
-               :expr3              nil
-               :exception          nil
-               :print-pretty       vimclojure.repl/*print-pretty*
-               :test-out           nil
-               :line               0)))
+   {:id        id
+    :ns        (or namespace (resolve-and-load-namespace 'user))
+    :test-out  nil
+    :line      1
+    :bindings  (-> (reduce add-binding {} bindable-vars)
+                 (assoc #'*compile-path* (System/getProperty
+                                           "clojure.compile.path"
+                                           "classes")))}))
 
 (defn start
   "Start a new Repl and register it in the system."
   [nspace]
-  ; Make sure user namespace exists.
   (let [id       (repl-id)
         the-repl (make-repl id nspace)]
     (swap! *repls* assoc id the-repl)
                    (the-repl :line)
                    line)]
     (with-bindings
-      {Compiler/LINE          (Integer. (.intValue line)) ; #64: Unbox to ensure int.
-       Compiler/SOURCE        (.getName (java.io.File. file))
-       Compiler/SOURCE_PATH   file
-       #'*in*                 (make-reader *in* line)
-       #'*ns*                 (if nspace nspace (the-repl :ns))
-       #'*warn-on-reflection* (the-repl :warn-on-reflection)
-       #'*print-meta*         (the-repl :print-meta)
-       #'*print-length*       (the-repl :print-length)
-       #'*print-level*        (the-repl :print-level)
-       #'*compile-path*       (the-repl :compile-path)
-       #'*command-line-args*  (the-repl :command-line-args)
-       #'*1                   (the-repl :expr1)
-       #'*2                   (the-repl :expr2)
-       #'*3                   (the-repl :expr3)
-       #'*e                   (the-repl :exception)
-       #'vimclojure.repl/*print-pretty* (the-repl :print-pretty)
-       #'clojure.test/*test-out* (if-let [test-out (the-repl :test-out)]
-                                   test-out
-                                   *out*)}
+      (merge (:bindings the-repl)
+             ; #64: Unbox to ensure int.
+             {Compiler/LINE        (Integer. (.intValue line))
+              Compiler/SOURCE      (.getName (java.io.File. file))
+              Compiler/SOURCE_PATH file
+              #'*in*               (make-reader *in* line)
+              #'*ns*               (if nspace nspace (:ns the-repl))
+              #'clojure.test/*test-out* (if-let [test-out (the-repl :test-out)]
+                                          test-out
+                                          *out*)})
       (try
         (thunk)
         (finally
           (when (not= id -1)
             (swap! *repls* assoc id
-                   (struct-map
-                     repl
-                     :id                 id
-                     :ns                 *ns*
-                     :warn-on-reflection *warn-on-reflection*
-                     :print-meta         *print-meta*
-                     :print-length       *print-length*
-                     :print-level        *print-level*
-                     :compile-path       *compile-path*
-                     :command-line-args  *command-line-args*
-                     :expr1              *1
-                     :expr2              *2
-                     :expr3              *3
-                     :exception          *e
-                     :print-pretty       vimclojure.repl/*print-pretty*
-                     :test-out           (let [test-out clojure.test/*test-out*]
-                                           (when-not (identical? test-out *out*)
-                                             test-out))
-                     :line               (dec (.getLineNumber *in*))))))))))
+                   {:id        id
+                    :ns        *ns*
+                    :test-out  (let [test-out clojure.test/*test-out*]
+                                 (when-not (identical? test-out *out*)
+                                   test-out))
+                    :line      (dec (.getLineNumber *in*))
+                    :bindings  (reduce add-binding {} bindable-vars)})))))))
 
 (defmacro with-repl
   "Executes body in the context of the Repl with the given id. id may be -1

File server/src/main/clojure/vimclojure/util.clj

 ;-
-; Copyright 2009 (c) Meikel Brandmeyer.
+; Copyright 2009-2011 (c) Meikel Brandmeyer.
 ; All rights reserved.
 ;
 ; Permission is hereby granted, free of charge, to any person obtaining a copy

File server/src/main/java/vimclojure/Nail.java

 /*-
- * Copyright 2009 (c) Meikel Brandmeyer.
+ * Copyright 2009-2011 (c) Meikel Brandmeyer.
  * All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy

File server/src/main/java/vimclojure/nailgun/NGServer.java

 import java.util.Iterator;
 import java.util.Map;
 
+
+import clojure.lang.RT;
+import clojure.lang.Symbol;
+import clojure.lang.Var;
+
 import vimclojure.nailgun.builtins.DefaultNail;
 
 /**
  */
 public class NGServer implements Runnable {
 
+	/* Load up vimclojure */
+	static {
+		try {
+			RT.var("clojure.core", "require").invoke(
+				Symbol.create("vimclojure.core")
+			);
+			RT.var("vimclojure.core", "init-server").invoke();
+		} catch (Exception exc) {
+			Throwable e = exc;
+			System.err.println("A crisis has arisen:");
+			e.printStackTrace();
+		}
+	}
+
 	/**
 	 * The address on which to listen, or null to listen on all
 	 * local addresses

File settings.gradle

 include 'client'
 include 'server'
 include 'vim'
+include 'gradle'

File vim/autoload/vimclojure.vim

 endfunction
 
 " Configuration
+if !exists("g:vimclojure#FuzzyIndent")
+	let vimclojure#FuzzyIndent = 0
+endif
+
 if !exists("g:vimclojure#HighlightBuiltins")
 	if exists("g:clj_highlight_builtins")
 		call vimclojure#WarnDeprecated("g:clj_highlight_builtins",
 	endif
 endif
 
+if !exists("g:vimclojure#NailgunServer")
+	let vimclojure#NailgunServer = "127.0.0.1"
+endif
+
+if !exists("g:vimclojure#NailgunPort")
+	let vimclojure#NailgunPort = "2113"
+endif
+
 if !exists("g:vimclojure#UseErrorBuffer")
 	let vimclojure#UseErrorBuffer = 1
 endif
 	endif
 endfunction
 
-function! vimclojure#SynIdName()
-	return synIDattr(synID(line("."), col("."), 0), "name")
-endfunction
-
-function! vimclojure#WithSaved(closure)
-	let v = a:closure.get(a:closure.tosafe)
-	try
-		let r = a:closure.f()
-	finally
-		call a:closure.set(a:closure.tosafe, v)
-	endtry
-	return r
-endfunction
-
-function! vimclojure#WithSavedPosition(closure)
-	let a:closure['tosafe'] = "."
-	let a:closure['get'] = function("getpos")
-	let a:closure['set'] = function("setpos")
-	return vimclojure#WithSaved(a:closure)
-endfunction
-
-function! vimclojure#WithSavedRegister(closure)
-	let a:closure['get'] = function("getreg")
-	let a:closure['set'] = function("setreg")
-	return vimclojure#WithSaved(a:closure)
-endfunction
-
-function! vimclojure#WithSavedOption(closure)
-	function a:closure.get(option)
-		execute "let val = &" . a:option
-		return val
-	endfunction
-
-	function a:closure.set(option, value)
-		execute "let &" . a:option . " = a:value"
-	endfunction
-
-	return vimclojure#WithSaved(a:closure)
-endfunction
-
-function! vimclojure#Yank(r, how)
-	let closure = {'tosafe': a:r, 'yank': a:how}
-
-	function closure.f() dict
-		silent execute self.yank
-		return getreg(self.tosafe)
-	endfunction
-
-	return vimclojure#WithSavedRegister(closure)
-endfunction
-
 function! vimclojure#EscapePathForOption(path)
 	let path = fnameescape(a:path)
 
 
 " Nailgun part:
 function! vimclojure#ExtractSexpr(toplevel)
-	let closure = { "flag" : (a:toplevel ? "r" : "") }
+	let closure = {
+				\ "flag"  : (a:toplevel ? "r" : ""),
+				\ "level" : (a:toplevel ? "0" : '\d')
+				\ }
 
 	function closure.f() dict
-		if searchpairpos('(', '', ')', 'bW' . self.flag,
-					\ 'vimclojure#SynIdName() !~ "clojureParen\\d"') != [0, 0]
-			return vimclojure#Yank('l', 'normal! "ly%')
-		end
-		return ""
+		let pos = [0, 0]
+		let start = getpos(".")
+
+		if getline(start[1])[start[2] - 1] == "("
+					\ && vimclojure#util#SynIdName() =~ 'clojureParen' . self.level
+			let pos = [start[1], start[2]]
+		endif
+
+		if pos == [0, 0]
+			let pos = searchpairpos('(', '', ')', 'bW' . self.flag,
+						\ 'vimclojure#util#SynIdName() !~ "clojureParen\\d"')
+		endif
+
+		if pos == [0, 0]
+			throw "Error: Not in a s-expression!"
+		endif
+
+		return [pos, vimclojure#util#Yank('l', 'normal! "ly%')]
 	endfunction
 
-	return vimclojure#WithSavedPosition(closure)
+	return vimclojure#util#WithSavedPosition(closure)
 endfunction
 
 function! vimclojure#BufferName()
 
 " Key mappings and Plugs
 function! vimclojure#MakePlug(mode, plug, f, args)
+	if a:mode == "i"
+		let esc = "<ESC>"
+	else
+		let esc = ""
+	endif
+
 	execute a:mode . "noremap <Plug>Clojure" . a:plug
-				\ . " :call " . a:f . "(" . a:args . ")<CR>"
+				\ . " " . esc . ":call " . a:f . "(" . a:args . ")<CR>"
 endfunction
 
 function! vimclojure#MakeProtectedPlug(mode, plug, f, args)
 				\ . a:f . "\"), [ " . a:args . " ])<CR>"
 endfunction
 
+function! vimclojure#MakeCommandPlug(mode, plug, f, args)
+	execute a:mode . "noremap <Plug>Clojure" . a:plug
+				\ . " :call vimclojure#ProtectedPlug("
+				\ . " function(\"vimclojure#CommandPlug\"),"
+				\ . " [ function(\"" . a:f . "\"), [ " . a:args . " ]])<CR>"
+endfunction
+
 function! vimclojure#MapPlug(mode, keys, plug)
-	if !hasmapto("<Plug>Clojure" . a:plug)
+	if !hasmapto("<Plug>Clojure" . a:plug, a:mode)
 		execute a:mode . "map <buffer> <unique> <silent> <LocalLeader>" . a:keys
 					\ . " <Plug>Clojure" . a:plug
 	endif
 endfunction
 
-function! vimclojure#MapCommandPlug(mode, keys, plug)
-	if exists("b:vimclojure_namespace")
-		call vimclojure#MapPlug(a:mode, a:keys, a:plug)
-	elseif g:vimclojure#WantNailgun == 1
-		let msg = ':call vimclojure#ReportError("VimClojure could not initialise the server connection.\n'
-					\ . 'That means you will not be able to use the interactive features.\n'
-					\ . 'Reasons might be that the server is not running or that there is\n'
-					\ . 'some trouble with the classpath.\n\n'
-					\ . 'VimClojure will *not* start the server for you or handle the classpath.\n'
-					\ . 'There is a plethora of tools like ivy, maven, gradle and leiningen,\n'
-					\ . 'which do this better than VimClojure could ever do it.")'
-		execute a:mode . "map <buffer> <silent> <LocalLeader>" . a:keys
-					\ . " " . msg . "<CR>"
-	endif
-endfunction
+if !exists("*vimclojure#CommandPlug")
+	function vimclojure#CommandPlug(f, args)
+		if exists("b:vimclojure_loaded")
+					\ && !exists("b:vimclojure_namespace")
+					\ && g:vimclojure#WantNailgun == 1
+			unlet b:vimclojure_loaded
+			call vimclojure#InitBuffer("silent")
+		endif
+
+		if exists("b:vimclojure_namespace")
+			call call(a:f, a:args)
+		elseif g:vimclojure#WantNailgun == 1
+			let msg = "VimClojure could not initialise the server connection.\n"
+						\ . "That means you will not be able to use the interactive features.\n"
+						\ . "Reasons might be that the server is not running or that there is\n"
+						\ . "some trouble with the classpath.\n\n"
+						\ . "VimClojure will *not* start the server for you or handle the classpath.\n"
+						\ . "There is a plethora of tools like ivy, maven, gradle and leiningen,\n"
+						\ . "which do this better than VimClojure could ever do it."
+			throw msg
+		endif
+	endfunction
+endif
 
 if !exists("*vimclojure#ProtectedPlug")
 	function vimclojure#ProtectedPlug(f, args)
 	let vimclojure#SplitSize = ""
 endif
 
-let vimclojure#Buffer = {}
+let vimclojure#Object = {}
 
-function! vimclojure#Buffer.New() dict
+function! vimclojure#Object.New(...) dict
 	let instance = copy(self)
 
-	call self.MakeBuffer()
-	call self.Init(instance)
+	call call(instance.Init, a:000, instance)
 
 	return instance
 endfunction
 
-function! vimclojure#Buffer.MakeBuffer()
+function! vimclojure#Object.Init() dict
+endfunction
+
+let vimclojure#Buffer = copy(vimclojure#Object)
+let vimclojure#Buffer["__superObjectNew"] = vimclojure#Buffer["New"]
+
+function! vimclojure#Buffer.New(...) dict
 	if g:vimclojure#SplitPos == "left" || g:vimclojure#SplitPos == "right"
 		let o_sr = &splitright
 		if g:vimclojure#SplitPos == "left"
 		execute printf("%snew", g:vimclojure#SplitSize)
 		let &splitbelow = o_sb
 	endif
+
+	return call(self.__superObjectNew, a:000, self)
 endfunction
 
-function! vimclojure#Buffer.Init(instance)
-	let a:instance._buffer = bufnr("%")
+function! vimclojure#Buffer.Init() dict
+	let self._buffer = bufnr("%")
 endfunction
 
 function! vimclojure#Buffer.goHere() dict
 
 " The transient buffer, used to display results.
 let vimclojure#ResultBuffer = copy(vimclojure#Buffer)
+let vimclojure#ResultBuffer["__superBufferNew"] = vimclojure#ResultBuffer["New"]
 let vimclojure#ResultBuffer["__superBufferInit"] = vimclojure#ResultBuffer["Init"]
 let vimclojure#ResultBuffer.__instance = []
 
-function! vimclojure#ResultBuffer.New() dict
+function! vimclojure#ResultBuffer.New(...) dict
 	if g:vimclojure#ResultBuffer.__instance != []
 		let closure = {
 					\ 'instance' : g:vimclojure#ResultBuffer.__instance[0],
-					\ 'tosafe'   : 'switchbuf',
-					\ 'class'    : self
+					\ 'args'     : a:000
 					\ }
 		function closure.f() dict
 			set switchbuf=useopen
 			call self.instance.goHereWindow()
-			call self.instance.clear()
-			return self.class.Init(self.instance)
+			call call(self.instance.Init, self.args, self.instance)
+
+			return self.instance
 		endfunction
 
-		return vimclojure#WithSavedOption(closure)
+		return vimclojure#util#WithSavedOption('switchbuf', closure)
 	endif
 
-	let instance = copy(self)
+	let b:vimclojure_result_buffer = 1
+	let instance = call(self.__superBufferNew, a:000, self)
 	let g:vimclojure#ResultBuffer.__instance = [ instance ]
 
-	call g:vimclojure#Buffer.MakeBuffer()
-	call self.__superBufferInit(instance)
-	call self.Init(instance)
-
 	return instance
 endfunction
 
-function! vimclojure#ResultBuffer.Init(instance) dict
+function! vimclojure#ResultBuffer.Init() dict
+	call self.__superBufferInit()
+
 	setlocal noswapfile
 	setlocal buftype=nofile
 	setlocal bufhidden=wipe
 
 	call vimclojure#MapPlug("n", "p", "CloseResultBuffer")
 
-	call a:instance.clear()
+	call self.clear()
 	let leader = exists("g:maplocalleader") ? g:maplocalleader : "\\"
 	call append(0, "; Use " . leader . "p to close this buffer!")
-
-	return a:instance
 endfunction
 
 function! vimclojure#ResultBuffer.CloseBuffer() dict
 let vimclojure#ClojureResultBuffer["__superResultBufferShowOutput"] =
 			\ vimclojure#ResultBuffer["showOutput"]
 
-function! vimclojure#ClojureResultBuffer.Init(instance) dict
-	call self.__superResultBufferInit(a:instance)
-	setfiletype clojure
-
-	return a:instance
+function! vimclojure#ClojureResultBuffer.Init(ns) dict
+	call self.__superResultBufferInit()
+	set filetype=clojure
+	let b:vimclojure_namespace = a:ns
 endfunction
 
 function! vimclojure#ClojureResultBuffer.showOutput(text) dict
 endif
 
 function! vimclojure#ShellEscapeArguments(vals)
-	let closure = { 'vals': a:vals, 'tosafe': 'shellslash' }
+	let closure = { 'vals': a:vals }
 
 	function closure.f() dict
 		set noshellslash
 		return map(copy(self.vals), 'shellescape(v:val)')
 	endfunction
 
-	return vimclojure#WithSavedOption(closure)
+	return vimclojure#util#WithSavedOption('shellslash', closure)
 endfunction
 
 function! vimclojure#ExecuteNailWithInput(nail, input, ...)
 		call writefile(input, inputfile)
 
 		let cmdline = vimclojure#ShellEscapeArguments(
-					\ [g:vimclojure#NailgunClient, "vimclojure.Nail", a:nail]
+					\ [g:vimclojure#NailgunClient,
+					\   '--nailgun-server', g:vimclojure#NailgunServer,
+					\   '--nailgun-port', g:vimclojure#NailgunPort,
+					\   'vimclojure.Nail', a:nail]
 					\ + a:000)
 		let cmd = join(cmdline, " ") . " <" . inputfile
 		" Add hardcore quoting for Windows
 	return call(function("vimclojure#ExecuteNailWithInput"), [a:nail, ""] + a:000)
 endfunction
 
-function! vimclojure#FilterNail(nail, rngStart, rngEnd, ...)
-	let cmdline = [g:vimclojure#NailgunClient,
-				\ "vimclojure.Nail", a:nail]
-				\ + vimclojure#ShellEscapeArguments(a:000)
-	let cmd = a:rngStart . "," . a:rngEnd . "!" . join(cmdline, " ")
-
-	silent execute cmd
-endfunction
-
 function! vimclojure#DocLookup(word)
 	if a:word == ""
 		return
 	elseif has("mac")
 		let vimclojure#Browser = "open"
 	else
-		let vimclojure#Browser = "firefox -new-window"
+		" some freedesktop thing, whatever, issue #67
+		let vimclojure#Browser = "xdg-open"
 	endif
 endif
 
 function! vimclojure#SourceLookup(word)
 	let source = vimclojure#ExecuteNailWithInput("SourceLookup", a:word,
 				\ "-n", b:vimclojure_namespace)
-	let buf = g:vimclojure#ClojureResultBuffer.New()
+	let buf = g:vimclojure#ClojureResultBuffer.New(b:vimclojure_namespace)
 	call buf.showOutput(source)
 	wincmd p
 endfunction
 function! vimclojure#MetaLookup(word)
 	let meta = vimclojure#ExecuteNailWithInput("MetaLookup", a:word,
 				\ "-n", b:vimclojure_namespace)
-	let buf = g:vimclojure#ClojureResultBuffer.New()
+	let buf = g:vimclojure#ClojureResultBuffer.New(b:vimclojure_namespace)
 	call buf.showOutput(meta)
 	wincmd p
 endfunction
 
 " Evaluators
 function! vimclojure#MacroExpand(firstOnly)
-	let sexp = vimclojure#ExtractSexpr(0)
+	let [unused, sexp] = vimclojure#ExtractSexpr(0)
 	let ns = b:vimclojure_namespace
 
 	let cmd = ["MacroExpand", sexp, "-n", ns]
 
 	let expanded = call(function("vimclojure#ExecuteNailWithInput"), cmd)
 
-	let buf = g:vimclojure#ClojureResultBuffer.New()
+	let buf = g:vimclojure#ClojureResultBuffer.New(ns)
 	call buf.showOutput(expanded)
 	wincmd p
 endfunction
 	let require = "(require :reload" . all . " :verbose '". ns. ")"
 	let result = vimclojure#ExecuteNailWithInput("Repl", require, "-r")
 
-	let resultBuffer = g:vimclojure#ClojureResultBuffer.New()
+	let resultBuffer = g:vimclojure#ClojureResultBuffer.New(ns)
 	call resultBuffer.showOutput(result)
 	wincmd p
 endfunction
 
 	let result = call(function("vimclojure#ExecuteNailWithInput"),
 				\ [ "RunTests", "", "-n", ns ] + (a:all ? [ "-a" ] : []))
-	let resultBuffer = g:vimclojure#ClojureResultBuffer.New()
+	let resultBuffer = g:vimclojure#ClojureResultBuffer.New(ns)
 	call resultBuffer.showOutput(result)
 	wincmd p
 endfunction
 	let result = vimclojure#ExecuteNailWithInput("Repl", content,
 				\ "-r", "-n", ns, "-f", file)
 
-	let resultBuffer = g:vimclojure#ClojureResultBuffer.New()
+	let resultBuffer = g:vimclojure#ClojureResultBuffer.New(ns)
 	call resultBuffer.showOutput(result)
 	wincmd p
 endfunction
 	let result = vimclojure#ExecuteNailWithInput("Repl", content,
 				\ "-r", "-n", ns, "-f", file, "-l", theLine)
 
-	let resultBuffer = g:vimclojure#ClojureResultBuffer.New()
+	let resultBuffer = g:vimclojure#ClojureResultBuffer.New(ns)
 	call resultBuffer.showOutput(result)
 	wincmd p
 endfunction
 
-function! vimclojure#EvalBlock() range
+function! vimclojure#EvalBlock()
 	let file = vimclojure#BufferName()
 	let ns = b:vimclojure_namespace
 
-	let content = getbufline(bufnr("%"), a:firstline, a:lastline)
+	let content = getbufline(bufnr("%"), line("'<"), line("'>"))
 	let result = vimclojure#ExecuteNailWithInput("Repl", content,
-				\ "-r", "-n", ns, "-f", file, "-l", a:firstline - 1)
+				\ "-r", "-n", ns, "-f", file, "-l", line("'<") - 1)
 
-	let resultBuffer = g:vimclojure#ClojureResultBuffer.New()
+	let resultBuffer = g:vimclojure#ClojureResultBuffer.New(ns)
 	call resultBuffer.showOutput(result)
 	wincmd p
 endfunction
 function! vimclojure#EvalToplevel()
 	let file = vimclojure#BufferName()
 	let ns = b:vimclojure_namespace
+	let [pos, expr] = vimclojure#ExtractSexpr(1)
 
-	let pos = searchpairpos('(', '', ')', 'bWnr',
-					\ 'vimclojure#SynIdName() !~ "clojureParen\\d"')
-
-	if pos == [0, 0]
-		throw "Error: Not in toplevel expression!"
-	endif
-
-	let expr = vimclojure#ExtractSexpr(1)
 	let result = vimclojure#ExecuteNailWithInput("Repl", expr,
 				\ "-r", "-n", ns, "-f", file, "-l", pos[0] - 1)
 
-	let resultBuffer = g:vimclojure#ClojureResultBuffer.New()
+	let resultBuffer = g:vimclojure#ClojureResultBuffer.New(ns)
 	call resultBuffer.showOutput(result)
 	wincmd p
 endfunction
 		return line(".")
 	endfunction
 
-	let endPosition = vimclojure#WithSavedPosition(closure)
+	let endPosition = vimclojure#util#WithSavedPosition(closure)
 
 	let content = getbufline(bufnr("%"), startPosition, endPosition)
 	let result = vimclojure#ExecuteNailWithInput("Repl", content,
 				\ "-r", "-n", ns, "-f", file, "-l", startPosition - 1)
 
-	let resultBuffer = g:vimclojure#ClojureResultBuffer.New()
+	let resultBuffer = g:vimclojure#ClojureResultBuffer.New(ns)
 	call resultBuffer.showOutput(result)
 	wincmd p
 endfunction
 
 " The Repl
 let vimclojure#Repl = copy(vimclojure#Buffer)
+let vimclojure#Repl.__superBufferNew = vimclojure#Repl.New
 let vimclojure#Repl.__superBufferInit = vimclojure#Repl.Init
 
 let vimclojure#Repl._history = []
 	call g:vimclojure#Repl.New(ns)
 endfunction
 
+" FIXME: Ugly hack. But easier than cleaning up the buffer
+" mess in case something goes wrong with repl start.
 function! vimclojure#Repl.New(namespace) dict
-	let instance = copy(self)
+	let replStart = vimclojure#ExecuteNail("Repl", "-s",
+				\ "-n", a:namespace)
+	if replStart.stderr != ""
+		call vimclojure#ReportError(replStart.stderr)
+		return
+	endif
 
-	call g:vimclojure#Buffer.MakeBuffer()
-	call self.Init(instance, a:namespace)
+	let instance = call(self.__superBufferNew, [a:namespace], self)
+	let instance._id = replStart.value.id
+	call vimclojure#ExecuteNailWithInput("Repl",
+				\ "(require 'clojure.stacktrace)",
+				\ "-r", "-i", instance._id)
 
 	return instance
 endfunction
 
-function! vimclojure#Repl.Init(instance, namespace) dict
-	call self.__superBufferInit(a:instance)
+function! vimclojure#Repl.Init(namespace) dict
+	call self.__superBufferInit()
 
-	let a:instance._prompt = a:namespace . "=>"
+	let self._prompt = a:namespace . "=>"
 
 	setlocal buftype=nofile
 	setlocal noswapfile
 
-	call append(line("$"), ["Clojure", a:instance._prompt . " "])
+	call append(line("$"), ["Clojure", self._prompt . " "])
 
-	let replStart = vimclojure#ExecuteNail("Repl", "-s",
-				\ "-n", a:namespace)
-	let a:instance._id = replStart.value.id
-	call vimclojure#ExecuteNailWithInput("Repl",
-				\ "(require 'clojure.stacktrace)",
-				\ "-r", "-i", a:instance._id)
-
-	let b:vimclojure_repl = a:instance
+	let b:vimclojure_repl = self
 
 	set filetype=clojure
+	let b:vimclojure_namespace = a:namespace
 
-	if !hasmapto("<Plug>ClojureReplEnterHook")
+	if !hasmapto("<Plug>ClojureReplEnterHook", "i")
 		imap <buffer> <silent> <CR> <Plug>ClojureReplEnterHook
 	endif
-	if !hasmapto("<Plug>ClojureReplUpHistory")
+	if !hasmapto("<Plug>ClojureReplEvaluate", "i")
+		imap <buffer> <silent> <C-CR> <Plug>ClojureReplEvaluate
+	endif
+	if !hasmapto("<Plug>ClojureReplHatHook", "n")
+		nmap <buffer> <silent> ^ <Plug>ClojureReplHatHook
+	endif
+	if !hasmapto("<Plug>ClojureReplUpHistory", "i")
 		imap <buffer> <silent> <C-Up> <Plug>ClojureReplUpHistory
 	endif
-	if !hasmapto("<Plug>ClojureReplDownHistory")
+	if !hasmapto("<Plug>ClojureReplDownHistory", "i")
 		imap <buffer> <silent> <C-Down> <Plug>ClojureReplDownHistory
 	endif
 
 		return ""
 	endif
 
-	let cmd = vimclojure#Yank("l", ln . "," . line("$") . "yank l")
+	let cmd = vimclojure#util#Yank("l", ln . "," . line("$") . "yank l")
 
 	let cmd = substitute(cmd, "^" . self._prompt . "\\s*", "", "")
 	let cmd = substitute(cmd, "\n$", "", "")
 	return cmd
 endfunction
 
+function! vimclojure#ReplDoEnter()
+	execute "normal! a\<CR>x"
+	normal! ==x
+	if getline(".") =~ '^\s*$'
+		startinsert!
+	else
+		startinsert
+	endif
+endfunction
+
 function! vimclojure#Repl.enterHook() dict
+	let lastCol = {}
+
+	function lastCol.f() dict
+		normal! g_
+		return col(".")
+	endfunction
+
+	if line(".") < line("$") || col(".") < vimclojure#util#WithSavedPosition(lastCol)
+		call vimclojure#ReplDoEnter()
+		return
+	endif
+
 	let cmd = self.getCommand()
 
 	" Special Case: Showed prompt (or user just hit enter).
-	if cmd == ""
+	if cmd =~ '^\(\s\|\n\)*$'
+		execute "normal! a\<CR>"
+		startinsert!
 		return
 	endif
 
 	let result = vimclojure#ExecuteNailWithInput("CheckSyntax", cmd,
 				\ "-n", b:vimclojure_namespace)
 	if result.value == 0 && result.stderr == ""
-		execute "normal! GA\<CR>x"
-		normal! ==x
-		startinsert!
+		call vimclojure#ReplDoEnter()
 	elseif result.stderr != ""
 		let buf = g:vimclojure#ResultBuffer.New()
 		call buf.showOutput(result)
 	endif
 endfunction
 
+function! vimclojure#Repl.hatHook() dict
+	let l = getline(".")
+
+	if l =~ "^" . self._prompt
+		let [buf, line, col, off] = getpos(".")
+		call setpos(".", [buf, line, len(self._prompt) + 2, off])
+	else
+		normal! ^
+	endif
+endfunction
+
 function! vimclojure#Repl.upHistory() dict
 	let histLen = len(self._history)
 	let histDepth = self._historyDepth
 	endif
 endfunction
 
-function! vimclojure#InitBuffer()
+function! vimclojure#InitBuffer(...)
 	if exists("b:vimclojure_loaded")
 		return
 	endif
 					endif
 					let b:vimclojure_namespace = namespace.value
 				catch /.*/
-					call vimclojure#ReportError(
-								\ "Could not determine the Namespace of the file.\n\n"
-								\ . "This might have different reasons. Please check, that the ng server\n"
-								\ . "is running with the correct classpath and that the file does not contain\n"
-								\ . "syntax errors. The interactive features will not be enabled, ie. the\n"
-								\ . "keybindings will not be mapped.\n\nReason:\n" . v:exception)
+					if a:000 == []
+						call vimclojure#ReportError(
+									\ "Could not determine the Namespace of the file.\n\n"
+									\ . "This might have different reasons. Please check, that the ng server\n"
+									\ . "is running with the correct classpath and that the file does not contain\n"
+									\ . "syntax errors. The interactive features will not be enabled, ie. the\n"
+									\ . "keybindings will not be mapped.\n\nReason:\n" . v:exception)
+					endif
 				endtry
 			endif
 		endif
 	execute "setlocal lw+=" . a:word
 endfunction
 
+function! vimclojure#ToggleParenRainbow()
+	highlight clear clojureParen1
+	highlight clear clojureParen2
+	highlight clear clojureParen3
+	highlight clear clojureParen4
+	highlight clear clojureParen5
+	highlight clear clojureParen6
+	highlight clear clojureParen7
+	highlight clear clojureParen8
+	highlight clear clojureParen9
+
+	let g:vimclojure#ParenRainbow = !g:vimclojure#ParenRainbow
+
+	if g:vimclojure#ParenRainbow != 0
+		if &background == "dark"
+			highlight clojureParen1 ctermfg=yellow      guifg=orange1
+			highlight clojureParen2 ctermfg=green       guifg=yellow1
+			highlight clojureParen3 ctermfg=cyan        guifg=greenyellow
+			highlight clojureParen4 ctermfg=magenta     guifg=green1
+			highlight clojureParen5 ctermfg=red         guifg=springgreen1
+			highlight clojureParen6 ctermfg=yellow      guifg=cyan1
+			highlight clojureParen7 ctermfg=green       guifg=slateblue1
+			highlight clojureParen8 ctermfg=cyan        guifg=magenta1
+			highlight clojureParen9 ctermfg=magenta     guifg=purple1
+		else
+			highlight clojureParen1 ctermfg=darkyellow  guifg=orangered3
+			highlight clojureParen2 ctermfg=darkgreen   guifg=orange2
+			highlight clojureParen3 ctermfg=blue        guifg=yellow3
+			highlight clojureParen4 ctermfg=darkmagenta guifg=olivedrab4
+			highlight clojureParen5 ctermfg=red         guifg=green4
+			highlight clojureParen6 ctermfg=darkyellow  guifg=paleturquoise3
+			highlight clojureParen7 ctermfg=darkgreen   guifg=deepskyblue4
+			highlight clojureParen8 ctermfg=blue        guifg=darkslateblue
+			highlight clojureParen9 ctermfg=darkmagenta guifg=darkviolet
+		endif
+	else
+		highlight link clojureParen1 clojureParen0
+		highlight link clojureParen2 clojureParen0
+		highlight link clojureParen3 clojureParen0
+		highlight link clojureParen4 clojureParen0
+		highlight link clojureParen5 clojureParen0
+		highlight link clojureParen6 clojureParen0
+		highlight link clojureParen7 clojureParen0
+		highlight link clojureParen8 clojureParen0
+		highlight link clojureParen9 clojureParen0
+	endif
+endfunction
+
 " Epilog
 let &cpo = s:save_cpo

File vim/autoload/vimclojure/util.vim

+" Part of Vim filetype plugin for Clojure
+" Language:     Clojure
+" Maintainer:   Meikel Brandmeyer <mb@kotka.de>
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+function! vimclojure#util#SynIdName()
+	return synIDattr(synID(line("."), col("."), 0), "name")
+endfunction
+
+function! vimclojure#util#WithSaved(closure)
+	let v = a:closure.save()
+	try
+		let r = a:closure.f()
+	finally
+		call a:closure.restore(v)
+	endtry
+	return r
+endfunction
+
+function! vimclojure#util#WithSavedPosition(closure)
+	function a:closure.save() dict
+		let [ _b, l, c, _o ] = getpos(".")
+		let b = bufnr("%")
+		return [b, l, c]
+	endfunction
+
+	function a:closure.restore(value) dict
+		let [b, l, c] = a:value
+
+		if bufnr("%") != b
+			execute b "buffer!"
+		endif
+		call setpos(".", [0, l, c, 0])
+	endfunction
+
+	return vimclojure#util#WithSaved(a:closure)
+endfunction
+
+function! vimclojure#util#WithSavedRegister(reg, closure)
+	let a:closure._register = a:reg
+
+	function a:closure.save() dict
+		return [getreg(self._register, 1), getregtype(self._register)]
+	endfunction
+
+	function a:closure.restore(value) dict
+		call call(function("setreg"), [self._register] + a:value)
+	endfunction
+
+	return vimclojure#util#WithSaved(a:closure)
+endfunction
+
+function! vimclojure#util#WithSavedOption(option, closure)
+	let a:closure._option = a:option
+
+	function a:closure.save() dict
+		return eval("&" . self._option)
+	endfunction
+
+	function a:closure.restore(value) dict
+		execute "let &" . self._option . " = a:value"
+	endfunction
+
+	return vimclojure#util#WithSaved(a:closure)
+endfunction
+
+function! vimclojure#util#Yank(r, how)
+	let closure = {'reg': a:r, 'yank': a:how}
+
+	function closure.f() dict
+		silent execute self.yank
+		return getreg(self.reg)
+	endfunction
+
+	return vimclojure#util#WithSavedRegister(a:r, closure)
+endfunction
+
+function! vimclojure#util#MoveBackward()
+	call search('\S', 'Wb')
+endfunction
+
+function! vimclojure#util#MoveForward()
+	call search('\S', 'W')
+endfunction
+
+" Epilog
+let &cpo = s:save_cpo

File vim/doc/clojure.txt

 >
         let vimclojure#WantNailgun = 1
 <
+The actual server to connect to and the port of said server can be given
+via configuration variables. The defaults are:
+>
+        let vimclojure#NailgunServer = "127.0.0.1"
+        let vimclojure#NailgunPort = "2113"
+<
 Note: Should there be an error when executing an interactive command
 and the error message goes away to quickly, you can use |:messages| to
 recall the message and read it conveniently without time pressure.
 control using standard highlighting groups. The actual highlighting used
 depends on the dark/bright setting (see |'bg'|).
 
+To customise the paren rainbow colors provide a from levels to the desired
+color definitions.
+>
+        let vimclojure#ParenRainbowColors = {
+                        \ '1': 'guifg=green',
+                        \ ...
+                        \ }
+<
+This will be used for all settings of 'bg'. If you want to specify only
+for light resp. dark backgrounds, just add "Light" resp. "Dark" to the
+option name.
+
+Indenting                           *ft-clj-indent*
+---------
+
+VimClojure provides the (hopefully) correct indentation rules for
+the standard forms and macros. However user code might define also
+forms for which the indentation should follow the indentation according
+to the 'lispwords' option. The names of these forms often follow a
+pattern like "defsomething" or "with-something".
+
+By setting the fuzzy indent option, you can tell VimClojure, that you
+want names beginning in "def" or "with" to be indented as if they
+were included in the 'lispwords' option.
+>
+        let vimclojure#FuzzyIndent = 1
+<
+This option is disabled by default.
+
 Preview Window
 --------------
 
                         of the buffer. This modifies the way the form is
                         indented.
 
+<LocalLeader>tr                                 *tr* *ToggleParenRainbow*
+                        Toggle the paren rainbow option. Note: After
+                        toggling the default colors will be used. Not any
+                        customised ones.
+
 Vim Repl
 --------
 
 will send it to the Clojure instance. In case the expression is incomplete,
 eg. after "(defn foo" will result in a newline for multiline expressions.
 
+A newline will also be inserted if you are inside of the expression. The
+expression will only be submitted to the Repl when you hit enter after
+the last character of the buffer. If you are inside the expression and
+want to start the evaluation immediately you may use <C-CR> instead of
+the plain <CR>.
+
 Previously sent expressions may be recalled via <C-Up> and <C-Down>.
 Note: sending multiple expressions will save them in the same history
 entry. So playing back with <C-Up> will again send all of the contained
 expressions.
 
+If the current line starts with a repl prompt, the *^* command moves to
+the end of the prompt and to the beginning of the line.
+
 The Plugs are:
  - <Plug>ClojureReplEnterHook for the enter key
+ - <Plug>ClojureReplEvaluate for immediate evaluation (<C-CR>)
+ - <Plug>ClojureReplHatHook for ^ navigation
  - <Plug>ClojureReplUpHistory for going backwards in history (<C-Up>)
  - <Plug>ClojureReplDownHistory for going forwards in history (<C-Down>)
 
 License
 -------
 
-Copyright (c) 2008,2009,2010 Meikel Brandmeyer, Frankfurt am Main
+Copyright (c) 2008-2011 Meikel Brandmeyer, Frankfurt am Main
 All rights reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy

File vim/ftplugin/clojure.vim

 	function closure.f() dict
 		execute self.lineno
 
-		if vimclojure#SynIdName() =~ 'clojureParen\d' && vimclojure#Yank('l', 'normal! "lyl') == '('
+		if vimclojure#util#SynIdName() =~ 'clojureParen\d' && vimclojure#util#Yank('l', 'normal! "lyl') == '('
 			return 1
 		endif
 
-		if searchpairpos('(', '', ')', 'bWr', 'vimclojure#SynIdName() !~ "clojureParen\\d"') != [0, 0]
+		if searchpairpos('(', '', ')', 'bWr', 'vimclojure#util#SynIdName() !~ "clojureParen\\d"') != [0, 0]
 			return 1
 		endif
 
 endtry
 
 call vimclojure#MapPlug("n", "aw", "AddToLispWords")
+call vimclojure#MapPlug("n", "tr", "ToggleParenRainbow")
 
-call vimclojure#MapCommandPlug("n", "lw", "DocLookupWord")
-call vimclojure#MapCommandPlug("n", "li", "DocLookupInteractive")
-call vimclojure#MapCommandPlug("n", "jw", "JavadocLookupWord")
-call vimclojure#MapCommandPlug("n", "ji", "JavadocLookupInteractive")
-call vimclojure#MapCommandPlug("n", "fd", "FindDoc")
+call vimclojure#MapPlug("n", "lw", "DocLookupWord")
+call vimclojure#MapPlug("n", "li", "DocLookupInteractive")
+call vimclojure#MapPlug("n", "jw", "JavadocLookupWord")
+call vimclojure#MapPlug("n", "ji", "JavadocLookupInteractive")
+call vimclojure#MapPlug("n", "fd", "FindDoc")
 
-call vimclojure#MapCommandPlug("n", "mw", "MetaLookupWord")
-call vimclojure#MapCommandPlug("n", "mi", "MetaLookupInteractive")
+call vimclojure#MapPlug("n", "mw", "MetaLookupWord")
+call vimclojure#MapPlug("n", "mi", "MetaLookupInteractive")
 
-call vimclojure#MapCommandPlug("n", "sw", "SourceLookupWord")
-call vimclojure#MapCommandPlug("n", "si", "SourceLookupInteractive")
+call vimclojure#MapPlug("n", "sw", "SourceLookupWord")
+call vimclojure#MapPlug("n", "si", "SourceLookupInteractive")
 
-call vimclojure#MapCommandPlug("n", "gw", "GotoSourceWord")
-call vimclojure#MapCommandPlug("n", "gi", "GotoSourceInteractive")
+call vimclojure#MapPlug("n", "gw", "GotoSourceWord")
+call vimclojure#MapPlug("n", "gi", "GotoSourceInteractive")
 
-call vimclojure#MapCommandPlug("n", "rf", "RequireFile")
-call vimclojure#MapCommandPlug("n", "rF", "RequireFileAll")
+call vimclojure#MapPlug("n", "rf", "RequireFile")
+call vimclojure#MapPlug("n", "rF", "RequireFileAll")
 
-call vimclojure#MapCommandPlug("n", "rt", "RunTests")
+call vimclojure#MapPlug("n", "rt", "RunTests")
 
-call vimclojure#MapCommandPlug("n", "me", "MacroExpand")
-call vimclojure#MapCommandPlug("n", "m1", "MacroExpand1")
+call vimclojure#MapPlug("n", "me", "MacroExpand")
+call vimclojure#MapPlug("n", "m1", "MacroExpand1")
 
-call vimclojure#MapCommandPlug("n", "ef", "EvalFile")
-call vimclojure#MapCommandPlug("n", "el", "EvalLine")
-call vimclojure#MapCommandPlug("v", "eb", "EvalBlock")
-call vimclojure#MapCommandPlug("n", "et", "EvalToplevel")
-call vimclojure#MapCommandPlug("n", "ep", "EvalParagraph")
+call vimclojure#MapPlug("n", "ef", "EvalFile")
+call vimclojure#MapPlug("n", "el", "EvalLine")
+call vimclojure#MapPlug("v", "eb", "EvalBlock")
+call vimclojure#MapPlug("n", "et", "EvalToplevel")
+call vimclojure#MapPlug("n", "ep", "EvalParagraph")
 
-call vimclojure#MapCommandPlug("n", "sr", "StartRepl")
-call vimclojure#MapCommandPlug("n", "sR", "StartLocalRepl")
+call vimclojure#MapPlug("n", "sr", "StartRepl")
+call vimclojure#MapPlug("n", "sR", "StartLocalRepl")
 
 if exists("b:vimclojure_namespace")
 	setlocal omnifunc=vimclojure#OmniCompletion

File vim/ftplugin/clojure/completions-clojure.core.txt

 *err*
 *file*
 *flush-on-newline*
+*fn-loader*
 *in*
 *math-context*
 *ns*
 *print-readably*
 *read-eval*
 *source-path*
+*unchecked-math*
 *use-context-classloader*
+*verbose-defrecords*
 *warn-on-reflection*
 ->>
 -cache-protocol-fn
 bean
 bigdec
 bigint
+biginteger
 binding
 bit-and
 bit-and-not
 create-struct
 cycle
 dec
+dec'
 decimal?
 declare
 definline
 distinct
 distinct?
 doall
-doc
 dorun
 doseq
 dosync
 error-mode
 eval
 even?
+every-pred
 every?
 extend
 extend-protocol
 file-seq
 filter
 find
-find-doc
+find-keyword
 find-ns
 find-protocol-impl
 find-protocol-method
 import
 in-ns
 inc
+inc'
 init-proxy
 instance?
 int
 primitives-classnames
 print
 print-ctor
-print-doc
 print-dup
 print-method
-print-namespace-doc
 print-simple
-print-special-doc
 print-str
 printf
 println
 read
 read-line
 read-string
+realized?
 reduce
 reductions
 ref
 shutdown-agents
 slurp
 some
+some-fn
 sort
 sort-by
 sorted-map
 sorted-set
 sorted-set-by
 sorted?
-special-form-anchor
 special-symbol?
 spit
 split-at
 symbol
 symbol?
 sync
-syntax-symbol-anchor
 take
 take-last
 take-nth
 true?
 type
 unchecked-add
+unchecked-add-int
+unchecked-byte
+unchecked-char
 unchecked-dec
-unchecked-divide
+unchecked-dec-int
+unchecked-divide-int
+unchecked-double
+unchecked-float
 unchecked-inc
+unchecked-inc-int
+unchecked-int
+unchecked-long
 unchecked-multiply
+unchecked-multiply-int
 unchecked-negate
-unchecked-remainder
+unchecked-negate-int
+unchecked-remainder-int
+unchecked-short
 unchecked-subtract
+unchecked-subtract-int
 underive
 unquote
 unquote-splicing
 with-open
 with-out-str
 with-precision
+with-redefs
+with-redefs-fn
 xml-seq
 zero?
 zipmap

File vim/ftplugin/clojure/completions-clojure.data.txt

+diff

File vim/ftplugin/clojure/completions-clojure.main.txt

+demunge
 load-script
 main
 repl
 repl-exception
 repl-prompt
 repl-read
+root-cause
 skip-if-eol
 skip-whitespace
+stack-element-str