-
Notifications
You must be signed in to change notification settings - Fork 330
LSP: Getting started
CUE has an LSP server built-in. LSP servers are used to provide language-specific support for editors.
The earliest version of CUE that has LSP support is v0.15.0-alpha.1.
Guidance for every possible editor is beyond our means. In general, you need to:
- Install the
cue
binary and make sure it's available on yourPATH
. v0.15.0-alpha.1 is the earliest version of CUE that has LSP support. - Your editor should be configured to use the command
cue lsp serve
to start CUE's LSP server.
Our CUE extension is available on the VSCode Marketplace and OpenVSX. If cue
is installed on your machine, the extension should find it and enable LSP support automatically.
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
:commands (lsp lsp-deferred)
:init
(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" }
Tested with Neovim v0.11.x. Install nvim-lspconfig
via :
git clone https://github.com/neovim/nvim-lspconfig ~/.config/nvim/pack/nvim/start/nvim-lspconfig
or via a 3rd-party plugin manager.
Then use something like this minimal ~/.config/nvim/init.lua
:
vim.cmd([[syntax on]])
vim.cmd([[filetype plugin indent on]])
-- Enable the CUE LSP
vim.lsp.enable("cue")
-- Go-to-definition on Ctrl-]
vim.keymap.set("n", "<C-]>", vim.lsp.buf.definition, { desc = "LSP Definition" })
-- Hover on Ctrl-h
vim.keymap.set("n", "<C-h>", vim.lsp.buf.hover, { desc = "LSP Hover" })
-- Optional: set trace level logging (logs at ~/.local/state/nvim/lsp.log)
vim.lsp.set_log_level('trace')
-- Optional: format on save
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = "*.cue",
callback = function()
vim.lsp.buf.format({ async = false })
end,
})
Add to your ~/.vim/after/plugin/vim-lsp.vim
if executable('cue')
au User lsp_setup call lsp#register_server({
\ 'name': 'cue lsp',
\ 'cmd': {server_info->['cue', 'lsp', 'serve']},
\ 'allowlist': ['cue'],
\ })
endif
A community-supported extension is available
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:
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:
```cue
num: int
num: > 6
num: 17
out: 3 + num
```
If you place your cursor on the `num` in the last line, and goto-definition, then you will be shown all 3 definitions of `num` on the previous lines.
The other mode is to place your cursor on a field name itself:
```cue
#Schema {
name!: string
age!: int
}
data: #Schema
data: age: 0
```
If you place your cursor on the `age` field in the last line, and goto-definition, then you will be taken to the definition of `age` within the `#Schema` struct.
Completions are provided both for field names and for values.
```cue
num: int
num: > 6
num: 17
out: 3 + n
```
As you type the `n` on the last line, `num` will be suggested.
```cue
#Schema {
name!: string
age!: int
}
data: #Schema
data: a
```
As you type the `a` on the last line, `age:` will be suggested as a field name.
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:
```cue
// num must be an int
num: int
// num must be greater than six
num: > 6
num: 17
out: 3 + num
```
Hovering over `num` on the last line will show the docs from lines 1 and 3.
It also works for fields:
```cue
#Schema {
// The name of the thing
name!: string
// The age of the thing
age!: int
}
data: #Schema
data: age: 0
```
Hovering over `age` on the last line will show the docs for the `age` field within `#Schema`.
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].a
If 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].a
As of v0.15.0-alpha.1, the LSP server will currently only support CUE files within modules, and that have a package
declaration.