-
-
Notifications
You must be signed in to change notification settings - Fork 146
Client features
Conjure adds support for various languages through "clients", these are Lua modules that expose a selection of functions and values that allow the wider Conjure UX to interact with the target language. There’s more information on configuring Conjure to point at clients depending on the filetype under :h conjure-clients.
Some of these functions and values are optional so the support for various features in the Conjure client interface varies from client to client. Sometimes this is due to time constraints (there’s only so many hours to work across many languages and ecosystems), other times it’s due to the way we’re forced to communicate with a REPL holding us back feature-wise.
There are also some features that aren’t strictly part of the interface and may vary in vague ways language to language (such as prompting for user input if some sort of "read line" function is invoked). In the table and documentation below you will find the following:
-
All supported language clients and their related information
-
Supported features per language client
-
Caveats around specific language clients and their feature support
-
Details about each feature, it’s implementation and how to pursue implementing it for a client
This table is dense and tries to bring together a lot of disparate information spread out across a lot of code. It will fall out of sync with the released code from time to time, if you spot an issue, please help the community by correcting it.
-
❏ Data table listing the languages, features and their overlap
-
❏ Information about each client (source code, docs etc)
-
❏ Information about each feature (how to implement it, examples, what it does)
-
❏ Caveats about specific client / feature implementations such as shortcomings due to technical limitations in a specific REPL
| Client | Config | State | Context | Eval | Eval file | Input prompt | Doc lookup | Go to def | Completions | Form node? | Debugger |
|---|---|---|---|---|---|---|---|---|---|---|---|
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
❌ |
❌ |
The client calls out to conjure.config/merge to merge their defaults into the shared tree at module load time. This allows the user to override configuration through the g:* global values as they see fit. The config should be nested under {:client {:name {:transport …}}}, so Clojure’s looks like this:
(config.merge
{:client
{:clojure
{:nrepl
{:foo true}}}})Clients can store stateful values inside Conjure’s state system. The benefit for storing stateful things inside this system is that user’s can set a state key with :ConjureClientState any-distinct-string-here! and get a whole new parallel copy of all the client state.
For Clojure, this includes nREPL connections, so you can actually set up an autocmd to set your :ConjureClientState … key to clj or cljs as you hop around your project’s front and backend source code (for example). Clojure’s usage looks like this:
(defonce get
(client.new-state
(fn []
{:conn nil
:auto-repl-proc nil
:join-next {:key nil}})))Then the rest of the Clojure client calls this get function with various path parts to extract the current value depending on the state key (which defaults to "default") like so: (state.get :conn) or (state.get :foo :bar :baz) to drill into something.
So calling new-state returns a lookup function that sort of behaves like get-in but with varargs. You give new-state a function so that it can be called for you every time a new state is created. If a state key is reused you get the original state value back out.