Empowering your editor with language servers

Learn about the LSP and how to easily make use of implementations in vim.
Original image by Guillermo Ferla from

Thanks to Microsoft and the standardization of the Language Server Protocol (often abbreviated as LSP) we can nowadays easily get access to features like:

  • code completion
  • go to implementation
  • diagnostics (warnings, errors,...)
  • display reference on hover
  • formatting
  • and many more...

The LSP works as a client-server protocol. This allows us to code one implementation for a given language and then use it for multiple clients. The clients here being our different editors. To mention some examples, we can use lsp implementations in:

  • vim
  • vscode
  • emacs
  • sublime
  • atom
  • etc...

We can easily have multiple language servers for different languages running at the same time

Breaking it down, all we have to do is:

  • install the binary (server) implementing the lsp
  • let our editor (the client) know where to find the binary
  • perhaps configure our client to disable specific features we don't want

CoC - handling language servers in vim

A somewhat famous tool for handling language servers in vim is Coc (Conquerer of Completion). It allows us to install language servers for many languages by just issuing a single command.

  • Typescript?
CocInstall coc-tsserver
  • Json?
CocInstall coc-json
  • Vue with Typescript?
CocInstall coc-volar
  • etc...

There are situations where no coc plugin does exist yet. Or old ones not working accordingly or at all because they are unmaintained and breaking changes happened.

Therefore I will provide you a quick hands on guide for integrating a lsp binary into an editor. Since I am using vim, the example will cover vim.

Hands on scenario - tailwindcss vim lsp

Since I am using tailwindcss as my go to tool for styling anything nowadays, I wanted to get these features for the tailwindcss syntax.

The problem

At the time of writing this post, I have found (and tried) two tailwindcss repos which claim to install tailwindcss for coc. Each having above 100 stars.

However (having tried both of them) they did either not work at all or did only partially work. (E.g. throwing weird errors, only supporting old directives, etc..) After looking around in the issues, I noticed people having similar experiences.

The Solution

Whenever there is no handy CocInstall lspNameHere command existing or working, we can just grab the implementation of the lsp. The implementation is most of the time freely available. Partly since this is what is often being used for extensions in the currently really famous (120k github stars) open source editor vscode.

The official lsp for tailwindcss can be found here.

All we have to do is make the specific lsp binary available to Coc and configure Coc to use it.

  • Make it available by installing the binary globally.
    npm install -g @tailwindcss/language-server
    

NOTE: This step will vary depending on the language the server was written in.

  • Configure Coc to use the language server
    vim ~/.vim/coc-settings.json
    
    tailwindcss lsp config for coc
    The base of this config is from [here](https://github.com/rodrigore/coc-tailwind-intellisense/issues/29).
    In case you want to copy and paste the config:
    "languageserver": {
        "tailwind-lsp": {
            "command": "tailwindcss-language-server",
            "args": [
                "--stdio"
            ],
            "filetypes": [
                "vue",
                "javascript",
                "javascriptreact",
                "typescript",
                "typescriptreact"
            ],
            "rootPatterns": [
                "tailwind.config.js",
                "tailwind.config.ts",
                "postcss.config.js",
                "postcss.config.ts",
                "package.json",
                "node_modules",
                ".git"
            ],
            "settings": {
                "tailwindCSS": {
                    "validate": true,
                    "lint": {
                        "cssConflict": "warning",
                        "invalidApply": "error",
                        "invalidScreen": "error",
                        "invalidVariant": "error",
                        "invalidConfigPath": "error",
                        "invalidTailwindDirective": "error",
                        "recommendedVariantOrder": "warning"
                    },
                    "classAttributes": [
                        "class",
                        "className",
                        "classList",
                        "ngClass"
                    ],
                    "experimental": {}
                }
            }
        }
    }

Start hacking away with your lsp installed :]

tailwindcss lsp suggestions inside vim
Hooray, tailwindcss lsp is doing work.