The sad truth is that JVM languages are awkward to use with Vim. This is compounded for Kotlin. The user base is still smaller than Java's, so there are far fewer how-to guides to help set up your editor. Below should serve as a good crash course for developing Kotlin in Vim. Who needs to use IntelliJ ๐
So, to enable a reasonable Kotlin developer experience, we need to install:
- A Kotlin grammar file to enable syntax highlighting.
- The Kotlin language server (for IntelliSense and code navigation).
- A code completion engine (optional, for Neovim) to auto-import dependencies.
These instructions have been written primarily for Neovim, but includes alternatives if youโd prefer to use the OG Vim.
Requirements
A Vim plugin manager.
- You can manage plugins with Git submodules, but I've found this to be a painful experience.
- Some examples are vim-plug, vundle, or, lazy.nvim.
An LSP client.
- Neovim comes with a client. For Vim you will need to install one, such as CoC, LanguageClient-neovim, or vim-lsp.
- Gradle.
- Java 11+ and Kotlin. Currently there is an open issue for Kotlin versions greater than 2.0.0. Downgrade if you have any issues.
1. Syntax Highlighting
Because Kotlin isnโt as mainstream as Python or Java, many editors donโt have a default grammar to enable syntax highlighting.
Neovim
Neovim could use the default regex based grammar that Vim uses for syntax highlighting. But I recommended installing treesitter. This uses a concrete syntax tree to provide more semantic meaning to tokens, allowing enriched (and faster) highlighting.
Once treesitter is installed (using the instructions in the repository), install the Kotlin grammar.
:TSInstall kotlin
And update your init.lua
file to turn on treesitter synax highlighting.
local treesitter = require('nvim-treesitter.configs')
treesitter.setup {
highlight = {
enable = true,
additional_vim_regex_highlighting = false,
},
}
You will have beautiful syntax highlighting when you next open Neovim ๐
Vim
kotlin-vim is a reasonably popular plugin that provides syntax highlighting, among other functionalities. This enables highlighting by providing Vim a file of regex based Kotlin grammar. Once installed, it should enable syntax highlighting without further configuration.
The usefulness of the syntax highlighting also depends on your chosen colourscheme. Have a look at this collection to find new schemes to try out!
2. The Language Server
Installing the Language Server
The Kotlin language server is packaged in few places, but I recommend to build it from the source code. This helps you understand how the server and client are orchestrated. It will also aid debugging if anything goes wrong.
First, clone the repository. I suggest keeping all language servers in one directory $HOME/language_servers
.
$ cd $HOME/language_servers
$ git clone git@github.com:fwcd/kotlin-language-server.git
$ cd kotlin-language-server
Check the build and tests work as expected.
$ ./gradlew clean build
Build the project and binaries.
$ ./gradlew installDist
There should now be an executable kotlin-language-server
binary in $HOME/language_servers/build/install/bin
.
For a large project, the Kotlin language server has a slow start up time (a few minutes) while it tokenises your entire project and stores these symbols in a database.
The server is also rather flakey. At some point while using it, it is likely to throw an error and stop working. Just close Vim and reopen your buffers again ๐
Configuring the LSP Client
Neovim
Install the nvim-lspconfig plugin to make configuration of the LSP client simpler. Then update your init.lua
to tell Neovim which filetypes to use the language server for (i.e. .kt
and .kts
extensions). The LSP client will try to the start the sever by running the kotlin_language_server
binary. You can directly point Neovim to the location of the binary, or include this directory in your $PATH
.
local lsp = require('lspconfig')
lsp.kotlin_language_server.setup{
filetypes = { "kotlin" , "kt", "kts"},
-- If you don't update you $PATH
cmd = { os.getenv( "HOME" ) .. "/language_servers/build/install/bin/kotlin_language_server" },
}
Vim
Follow the configuration instructions on the GitHub repo of your chosen LSP client (each one will be different). The Kotlin language server repository also provides some sample configuration for CoC and LanguageClient-neovim.
3. Completion Engine (Neovim only)
The builtin Vim omni completion engine is simple, but surprisingly useful. It will allow you to autocomplete any existing word in your open buffers (which is sufficient for a lot of use cases). But the completion menu wonโt include options from your project dependencies.
With a language server set up, we have broader, project-wide context at our disposal. If we can plug this intelligence into our completion engine, it would then be possible to autocomplete and auto-import any method or class that exists in our project or its dependencies.
For this, we need to install a new completion engine: nvim-cmp. This engine uses completion โsourcesโ (installed as separate dependencies) to populate the completion menu. So we also need to install cmp-buffer and cmp-nvim-lsp. Check out this tutorial by TJ DeVries for more info about how this plugin works.
Once those three plugins are installed, add this configuration to your init.lua
. See the repository for more configuration options.
cmp.setup {
mapping = {
["<C-n>"] = cmp.mapping.select_next_item { behavior = cmp.SelectBehavior.Insert },
["<C-p>"] = cmp.mapping.select_prev_item { behavior = cmp.SelectBehavior.Insert },
['<C-u>'] = cmp.mapping.scroll_docs(-4),
['<C-d>'] = cmp.mapping.scroll_docs(4),
['<C-o>'] = cmp.mapping.complete_common_string(),
['<C-e>'] = cmp.mapping.abort(),
['<C-y>'] = cmp.mapping.confirm(),
},
sources = {
{ name = 'buffer', keyword_length = 3 }, -- only start autocompleting after a few chars typed
{ name = 'nvim_lsp', max_item_count = 10 }, -- don't overpopulate list with symbols from LSP
},
-- Just for aesthetics
window = {
completion = cmp.config.window.bordered(),
documentation = cmp.config.window.bordered(),
},
}
Now, when you hit CTRL-n will open a completion menu. Pressing CTRL-y on an option will autocomplete with that symbol and (if required) insert the needed import statement at the top of your file ๐
Wrap up
Following the above configuration should provide you syntax highlighting, LSP functionality (diagnostics, go to definition, etc.), and auto import.
Even with the above configuration, developing Kotlin in Vim isn't the smoothest experience. This is mostly due to limitations with the Kotlin LSP. I hope community support will improve this over time ๐
Here is a fully functioning init.lua file for Neovim that includes all the configuration for the the above plugins.
Top comments (0)