 
 (defonce current-ns (atom 'cljs.user))
 
-(defn- known-namespaces
+(defn- all-ns
+  "Returns a sequence of all namespaces."
   []
   (keys (:cljs.analyzer/namespaces @st)))
 
 (defn- get-namespace
-  [sym]
-  (get-in @st [:cljs.analyzer/namespaces sym]))
+  "Gets the AST for a given namespace."
+  [ns]
+  {:pre [(symbol? ns)]}
+  (get-in @st [:cljs.analyzer/namespaces ns]))
+
+(defn- public-syms
+  "Returns a sequence of the public symbols in a namespace."
+  [ns]
+  {:pre [(symbol? ns)]}
+  (->> (get-namespace ns)
+    :defs
+    (filter (comp not :private second))
+    (map key)))
 
 (defn- get-aenv
   []


(defn ^:export get-completions
  [buffer]
  (let [namespace-candidates (map str (known-namespaces))
        top-form?            (re-find #"^\s*\(\s*[^()\s]*$" buffer)
        typed-ns             (second (re-find #"(\b[a-zA-Z-.]+)/[a-zA-Z-]+$" buffer))]
    (let [buffer-match-suffix (re-find #"[a-zA-Z-]*$" buffer)

        (let [ns-name (:value result)]
          (if-not (symbol? ns-name)
            (println "Argument to in-ns must be a symbol.")
            (if (some (partial = ns-name) (all-ns))
              (reset! current-ns ns-name)
              (let [ns-form `(~'ns ~ns-name)]
                (cljs/eval
