Skip to content
ClojureScript "IntelliSense" support for JS objects and their properties/methods. Via figwheel and Emacs CIDER.
Clojure Other
  1. Clojure 98.4%
  2. Other 1.6%
Branch: master
Clone or download
Latest commit 0ee7f7f Oct 5, 2019

suitable - Addon for Figwheel and Emacs CIDER to aid exploratory development in ClojureScript Clojars Project

This project is a code completion backend for interactive repls and editors that use runtime introspection to provide "IntelliSense" support. This can be extremely useful and productive if you're experimenting around with unknown APIs.

For example you work with DOM objects but can't remember how to query for child elements. Type (.| js/document) (with | marking the postion of your cursor) and press TAB. Methods and properties of js/document will appear — including querySelector and querySelectorAll.

Currently Emacs (via CIDER) and figwheel.main are supported. If you want support for your favorite tool please let me know and I'll look into it (no promises, though).


The animation shows how various properties and methods of the native DOM can be accessed (Tab is used to show completions for the expression at the cursor):


figwheel.main with rebel-readline

Please note that you need to use rebel-readline with figwheel for that to work. Plain repls have no completion feature.

Tools CLI

First make sure that the normal Tools CLI setup works.

Then modify deps.edn and dev.cljs.edn, you should end up with the files looking like below:

  • deps.edn
{:deps {com.bhauman/figwheel-main {:mvn/version "RELEASE"}
        com.bhauman/rebel-readline-cljs {:mvn/version "RELEASE"}}
 :paths ["src" "resources" "target"]
 :aliases {:suitable {:extra-deps {org.rksm/suitable {:mvn/version "RELEASE"}}
	              :main-opts ["-e" "(require,'suitable.hijack-rebel-readline-complete)"
                                  "-m" "figwheel.main"
                                  "--build" "dev" "--repl"]}}}
  • dev.cljs.edn
{:main example.core
 :preloads [suitable.js-introspection]}
  • src/example/core.cljs
(ns example.core)

You can now start a figwheel repl via clj -A:suitable and use TAB to complete.


First make sure that the normal leiningen setup works.

Add [org.rksm/suitable "0.2.14"] to your dependencies vector.

Then you can start a repl with lein trampoline run -m suitable.figwheel.main -- -b dev -r


Suitable is now a default middleware in CIDER (as of CIDER 0.22.0)! So no extra installation steps are required.

Custom nREPL server

To load suitable into a custom server you can load it using this monstrosity:

clj -Sdeps '{:deps {cider/cider-nrepl {:mvn/version "0.22.0"} cider/piggieback {:mvn/version"0.4.1"}}}' -m nrepl.cmdline --middleware "[cider.nrepl/cider-middleware,cider.piggieback/wrap-cljs-repl]"

Or from within Clojure:

(ns my-own-nrepl-server
  (:require cider.nrepl

(defn start-cljs-nrepl-server []
(let [middlewares (conj (map resolve cider.nrepl/cider-middleware)
      handler (apply nrepl.server/default-handler middlewares)]
  (nrepl.server/start-server :handler handler))

How does it work?

suitable uses the same input as the widely used compliment. This means it gets a prefix string and a context form from the tool it is connected to. For example you type (.l| js/console) with "|" marking where your cursor is. The input we get would then be: prefix = .l and context = (__prefix__ js/console).

suitable recognizes various ways how CLJS can access properties and methods, such as ., .., doto, and threading forms. Also direct global access is supported such as js/console.log. suitable will then figure out the expression that defines the "parent object" that the property / method we want to use belongs to. For the example above it would be js/console. The system then uses the EcmaScript property descriptor API to enumerate the object members. Those are converted into completion candidates and send back to the tooling.


This project is MIT licensed.

You can’t perform that action at this time.