Logo

dev-resources.site

for different kinds of informations.

How to Setup Vim for Kotlin Development

Published at
12/27/2024
Categories
neovim
kotlin
lsp
vim
Author
calamont
Categories
4 categories in total
neovim
open
kotlin
open
lsp
open
vim
open
Author
8 person written this
calamont
open
How to Setup Vim for Kotlin Development

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:

  1. A Kotlin grammar file to enable syntax highlighting.
  2. The Kotlin language server (for IntelliSense and code navigation).
  3. 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
Enter fullscreen mode Exit fullscreen mode

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,
  },
}
Enter fullscreen mode Exit fullscreen mode

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 [email protected]:fwcd/kotlin-language-server.git
$ cd kotlin-language-server
Enter fullscreen mode Exit fullscreen mode

Check the build and tests work as expected.

$ ./gradlew clean build
Enter fullscreen mode Exit fullscreen mode

Build the project and binaries.

$ ./gradlew installDist
Enter fullscreen mode Exit fullscreen mode

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" },
}
Enter fullscreen mode Exit fullscreen mode

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(),
  },
}
Enter fullscreen mode Exit fullscreen mode

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.
Kotlin development, in action

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.

vim Article's
30 articles in total
Favicon
Vim Macros: Automate Repetitive Tasks Instantly
Favicon
Develop a ulauncher extension with a command database
Favicon
vim_notes
Favicon
My text editor setup in 2025 and how I came out of extension hell
Favicon
Mastering Vim and NvChad for Coding and Development: A Comprehensive Guide
Favicon
Vim cheat sheet
Favicon
Setting Up NeoVim + LazyVim on My New Mac Mini M4 πŸ’»βœ¨
Favicon
πŸŽ‰ Welcome to the LazyVim Adventure! πŸŽ‰ Part1
Favicon
Mastering VIM: A Complete Beginner's Guide to the Command-Line Editor
Favicon
Explaining Null Device or Black Hole Register in Vim
Favicon
From Vi to NeoVim: A Journey into the Heart of Text Editing
Favicon
Neovim how to ignore directories like node_modules in Telescope
Favicon
How to Create a Markdown Code Block in Vim With a Single Keystroke
Favicon
Setting Up Neovim
Favicon
The Most Interesting Mostly Tech Reads of 2024
Favicon
How to Setup Vim for Kotlin Development
Favicon
Using Vim Navigation (h, j, k, l) as Arrow Keys on Mac with Karabiner-Elements
Favicon
vim
Favicon
How to Modify Multiple Various Matches at Once in Vim
Favicon
On Vim's Modal Nature and the Importance of Tools: The Example of Numbered Registers
Favicon
I’ve been working in IT for what feels like forever. All this time, I’ve been using Vim and just exiting by turning off the terminal. Today, an intern casually showed me :wq... My life will never be the same. πŸ€¦β€β™‚οΈ
Favicon
Atomic Note-Taking Guide
Favicon
What I've Learned About My Editing Skills
Favicon
Like Vim, but Helix
Favicon
Vim Regex Tricks - Capitalize Every First Letter
Favicon
Configurando Os Temas do Vim no Termux
Favicon
[SOLVED] Vue 3 + TypeScript + Inlay Hint support in NeoVim
Favicon
Vim: Minimalist Environment
Favicon
Configurando o AutoComplete do Vim pelo Termux
Favicon
Migrating from VSCode to Neovim: A Journey of Learning, Confusion, and Triumph! πŸš€

Featured ones: