-
Notifications
You must be signed in to change notification settings - Fork 38
Context
By default, the information a completion library has is quite restricted. Usually it is only a prefix of a thing that user wants to complete. But big IDEs like Eclipse parse entire source files or even projects to make their completion more intelligent and environment-aware.
Compliment tries to achieve something similar with a concept called context. Context is basically a top-level code form from where the completion was initiated. This code form undergoes several transformations on both client and server side to deliver the context to the completions source in a format that is convenient to use.
Aside this document you can also check context tests for additional understanding.
When user initiates completion in the editor, client-side Compliment plugin grabs the whole top-level form where the completion point is located. For example, completion was initiated in this code (█ represents cursor position):
(ns foo.bar
(:use [clojure.string :only [join tr█]])
(:import java.io.File))
Then the plugin replaces the completion prefix with unified prefix
placeholder (__prefix__
). This is done to communicate to
server-side Compliment the location of the prefix.
(ns foo.bar
(:use [clojure.string :only [join __prefix__]])
(:import java.io.File))
Finally the modified context form is passed as a string to the server by
calling (compliment.core/completions ...)
together with the
prefix.
Upon receiving the context Compliment performs the most significant
transformation. It takes the code form (which is a tree) and turns
it into a sequence of forms starting with immediate form containing
__prefix__
and going outwards. Thus after parsing our example
will become:
({:idx 1, :form [join __prefix__]}
{:idx 2, :form [clojure.string :only [join __prefix__]]}
{:idx 1, :form (:use [clojure.string :only [join __prefix__]])}
{:idx 2, :form (ns foo.bar
(:use [clojure.string :only [join __prefix__]])
(:import java.io.File))})
Besides :form
each map contains :idx
value which represents
the position of __prefix__
or the form that has it in the outer
form.
For maps :idx
works differently:
{:akey {someth█ 42}}
;;=>
({:idx 42, :map-role :key, :form {__prefix__ 42}}
{:idx :akey, :map-role :value, :form {:akey {__prefix__ 42}}})
You can see that :map-role
appears in the results that
correspond to map forms. It can be either :key
or :value
depending on what position is prefix or prefix-containing form.
Also :idx
now shows the opposite value in prefix’s key-value pair.
If a map literal contains odd number of elements, a single nil
is added at
the end.
{:someth█}
;;=>
({:idx nil, :map-role :key, :form {__prefix__ nil}})
A few examples of context usage can be found in default Compliment sources.