                    #(re-find str-or-pattern (str %))
                    #(s/includes? (str %) (str str-or-pattern)))]
     (sort (mapcat (fn [ns]
-                    (let [ns-name (str ns)
-                          ns-name (if (s/ends-with? ns-name "$macros")
-                                    (apply str (drop-last 7 ns-name))
-                                    ns-name)]
+                    (let [ns-name (drop-macros-suffix (str ns))]
                       (map #(symbol ns-name (str %))
                         (filter matches? (public-syms ns)))))
             (all-ns)))))

   :gen-class
   :keywordize-keys])

(defn- completion-candidates
  [namespace-candidates top-form? typed-ns]
  (set (if typed-ns
         (completion-candidates-for-ns (symbol typed-ns) false)
         (concat namespace-candidates
           (map str keyword-completions)
           (completion-candidates-for-ns 'cljs.core false)
           (completion-candidates-for-ns 'cljs.core$macros false)
           (completion-candidates-for-ns @current-ns true)


(defn- ^:export get-completions
  [buffer]
  (let [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)
          buffer-prefix       (subs buffer 0 (- (count buffer) (count buffer-match-suffix)))]
      (clj->js (if (= "" buffer-match-suffix)
                 []
                 (map #(str buffer-prefix %)
                   (sort
                     (filter (partial is-completion? buffer-match-suffix)
                       (completion-candidates top-form? typed-ns)))))))))

(defn- is-completely-readable?
  [source]
