-
Notifications
You must be signed in to change notification settings - Fork 367
LSP: Getting started
CUE has an LSP server built-in. LSP servers are used to provide language-specific support for editors.
Guidance for every possible editor is beyond our means. In general, you need to:
- Install the
cuebinary and make sure it's available on yourPATH. v0.15.0-alpha.1 is the earliest version of CUE that has LSP support. - Tell your editor that the CUE language server should be started by running
cue lsp serve
Our CUE extension is available on the marketplace. If cue is installed on your machine, the extension should find it and enable LSP support automatically if possible.
Our CUE plugin is available on the marketplace. LSP support is not yet available for this extension (work in progress), but the LSP4IJ plugin can be used, for example.
The lsp-mode package works with CUE's LSP server. Something like this should work:
(use-package lsp-mode
:init
:commands (lsp lsp-deferred)
(with-eval-after-load 'lsp-mode
(add-to-list 'lsp-language-id-configuration '(cue-mode . "cue"))
(lsp-register-client (make-lsp-client
:new-connection (lsp-stdio-connection (list "cue" "lsp" "serve"))
:activation-fn (lsp-activate-on "cue")
:server-id 'cuelsp))
)
:hook ((cue-mode . lsp-deferred))
)
(use-package cue-mode)[language-server.cuelsp]
command = "cue"
args = ["lsp", "serve"]
[[language]]
name = "cue"
language-servers = [ "cuelsp" ]
file-types = ["cue"]
auto-format = true
comment-token = "//"
indent = { tab-width = 3, unit = "\t" }The foundation of CUE's LSP server is based on Go's gopls LSP server. As such, it supports the same remote mode of operation. This means you can configure it to listen on a socket (e.g. cue lsp serve -listen='unix;/run/user/1000/cuelsp/cuelsp') and then configure your editor to connect to that socket (e.g. cue lsp -remote='unix;/run/user/1000/cuelsp/cuelsp')
As of CUE v0.15.0-alpha.1, the CUE LSP server supports:
-
Goto-definition. There are two modes for this. Firstly, from a value, goto-definition will take you to all the places where that value is defined. For example:
num: int num: > 6 num: 17 out: 3 + num
If you place your cursor on the
numin the last line, and goto-definition, then you will be shown all 3 definitions ofnumon the previous lines. The other mode is to place your cursor on a field name itself:#Schema { name!: string age!: int } data: #Schema data: age: 0
If you place your cursor on the
agein the last line, and goto-definition, then you will be taken to the definition ofagewithin the#Schemastruct. -
Completion. Completions are provided both for field names and for values.
num: int num: > 6 num: 17 out: 3 + n
As you type the
non the last line,numwill be suggested.#Schema { name!: string age!: int } data: #Schema data: a
As you type the
aon the last line,age:will be suggested as a field name. -
Hover. Hover is used to display relevant documentation in your editor as you "hover over" (or similar) a value. This works exactly the same way as Goto-definition; it works for field values:
// num must be an int num: int // num must be greater than six num: > 6 num: 17 out: 3 + num
Hovering over
numon the last line will show the docs from lines 1 and 3. It also works for fields:#Schema { // The name of the thing name!: string // The age of the thing age!: int } data: #Schema data: age: 0
Hovering over
ageon the last line will show the docs for theagefield within#Schema. -
Formatting. The CUE LSP server can format entire files. This means you can configure your editor to "format on save" if you wish to.
The LSP server does not currently attempt to fully evaluate CUE; this could take a long time, and/or require additional configuration. Instead, it performs a "static analysis": analysing your code without running it. This is very similar to how type-checking is implemented in many "statically typed" languages. Although a simple unification of struct fields is performed, and attempts are made to resolve references, there is no evaluation of expressions in general. Field names are not tested against patterns, and dynamic fields are not evaluated.
Dynamic indexing with a constant will work. For example:
[8, {a: "hi"}, {a: true}][1].aIf you goto-definition from the final a, then that will jump to the a: "hi" field because the constant index [1] is understood. But if this constant index is made into a dynamic expression then the LSP server will not attempt to evaluate that expression. For example:
n: 1
[8, {a: "hi"}, {a: true}][n*1].aAs of v0.15.0-alpha.1, the LSP server will currently only support CUE files within modules, and that have a package declaration.