/zls

Zig LSP implementation + Zig Language Server

Primary LanguageZigMIT LicenseMIT

Zig Language Server

CI Zig Tools

Need support? Wanna help out? Join our Discord server!

Zig Language Server, or zls, is a language server for Zig. The Zig wiki states that "The Zig community is decentralized" and "There is no concept of 'official' or 'unofficial'", so instead of calling zls unofficial, and I'm going to call it a cool option, one of many.

Table Of Contents

Installation

Installation starts with downloading an official release from the Releases page. Up to date builds from master branch are also available in the latest successful CI run, contained in the builds artifact.

See Downloading and Building ZLS on the Wiki, or the page about using ZLS with Visual Studio Code for a guide to help get zls running in your editor.

Installing binaries

MacOS

You can install the latest release into $HOME/zls using e.g.:

brew install xz
mkdir $HOME/zls && cd $HOME/zls && curl -L https://github.com/zigtools/zls/releases/download/0.9.0/x86_64-macos.tar.xz | tar -xJ --strip-components=1 -C . && chmod +x zls

Linux

You can install the latest release into $HOME/zls using e.g.:

sudo apt install xz-utils
mkdir $HOME/zls && cd $HOME/zls && curl -L https://github.com/zigtools/zls/releases/download/0.9.0/x86_64-linux.tar.xz | tar -xJ --strip-components=1 -C .

From Source

Building zls is very easy. You will need a build of Zig master to build zls.

git clone --recurse-submodules https://github.com/zigtools/zls
cd zls
zig build -Drelease-safe
./zig-out/bin/zls --config # Configure ZLS

For detailed building instructions, see the Wiki page about Cloning With Git.

Build Options

Option Type Default Value What it Does
-Ddata_version string (like 0.7.1 or 0.9.0) master The data file version. This selects the files in the src/data folder that correspond to the Zig version being served.

Updating Data Files

There is a generate-data.py in the src/data folder, run this file to update data files. It writes to stdout and you can redirect output to a zig file like master.zig. By default it generates data file for master, but can be configured to generate for a different version by modifying the zig_version variable. Files generated by this tool contains formatting information.

There is also a generate-data.js in the src/data folder, you'll need to run this inside a Chrome DevTools console and copy the output. Files generated by this tool does not contain formatting information.

Configuration Options

You can configure zls by running zls --config or manually creating your own zls.json configuration file. zls will look for a zls.json configuration file in multiple locations with the following priority:

  • In the local configuration folder of your OS (as provided by known-folders)
  • In the global configuration folder of your OS (as provided by known-folders)

The following options are currently available.

Option Type Default value What it Does
enable_snippets bool false Enables snippet completions when the client also supports them.
enable_ast_check_diagnostics bool true Whether to enable ast-check diagnostics
enable_autofix bool false Whether to automatically fix errors on save. Currently supports adding and removing discards.
enable_import_embedfile_argument_completions bool false Whether to enable import/embedFile argument completions
zig_lib_path ?[]const u8 null zig library path, e.g. /path/to/zig/lib/zig, used to analyze std library imports.
zig_exe_path ?[]const u8 null zig executable path, e.g. /path/to/zig/zig, used to run the custom build runner. If null, zig is looked up in PATH. Will be used to infer the zig standard library path if none is provided.
warn_style bool false Enables warnings for style guideline mismatches
build_runner_path ?[]const u8 null Path to the build_runner.zig file provided by zls. null is equivalent to ${executable_directory}/build_runner.zig
global_cache_path ?[]const u8 null Path to a directroy that will be used as zig's cache. null is equivalent to ${KnownFloders.Cache}/zls
enable_semantic_tokens bool true Enables semantic token support when the client also supports it.
enable_inlay_hints bool false Enables inlay hint support when the client also supports it.
inlay_hints_show_builtin bool true Enable inlay hints for builtin functions
inlay_hints_exclude_single_argument bool true Don't show inlay hints for single argument calls
inlay_hints_hide_redundant_param_names bool false Hides inlay hints when parameter name matches the identifier (e.g. foo: foo)
inlay_hints_hide_redundant_param_names_last_token bool false Hides inlay hints when parameter name matches the last token of a parameter node (e.g. foo: bar.foo, foo: &foo)
operator_completions bool true Enables * and ? operators in completion lists.
include_at_in_builtins bool false Whether the @ sign should be part of the completion of builtins.
max_detail_length usize 1024 * 1024 The detail field of completions is truncated to be no longer than this (in bytes).
skip_std_references bool false When true, skips searching for references in std. Improves lookup speed for functions in user's code. Renaming and go-to-definition will continue to work as is.

Per-build Configuration Options

The following options can be set on a per-project basis by placing zls.build.json in the project root directory next to build.zig.

Option Type Default value What it Does
relative_builtin_path ?[]const u8 null If present, this path is used to resolve @import("builtin")
build_options ?[]BuildOption null If present, this contains a list of user options to pass to the build. This is useful when options are used to conditionally add packages in build.zig.

BuildOption

BuildOption is defined as follows:

const BuildOption = struct {
    name: []const u8,
    value: ?[]const u8 = null,
};

When value is present, the option will be passed the same as in zig build -Dname=value. When value is null, the option will be passed as a flag instead as in zig build -Dflag.

Features

zls supports most language features, including simple type function support, using namespace, payload capture type resolution, custom packages, cImport and others. Currently there is no support for compile time evaluation.

The following LSP features are supported:

  • Completions
  • Hover
  • Goto definition/declaration
  • Document symbols
  • Find references
  • Rename symbol
  • Formatting using zig fmt
  • Semantic token highlighting (implemented by a few clients including VS Code, kak and emacs lsp-mode)
  • Inlay hints (implemented by VS Code)

You can install zls using the instuctions for your text editor below:

VS Code

Install the zls-vscode extension from here or via the extensions menu. It will install zls if it is not found in your PATH

Sublime Text

  • Install the LSP package from here or via Package Control.
  • Add this snippet to LSP's user settings:

Sublime Text 3

{
    "clients": {
        "zig": {
            "command": ["zls"],
            "enabled": true,
            "languageId": "zig",
            "scopes": ["source.zig"],
            "syntaxes": ["Packages/Zig Language/Syntaxes/Zig.tmLanguage"]
        }
    }
}

Sublime Text 4

{
    "clients": {
        "zig": {
            "command": ["zls"],
            "enabled": true,
            "selector": "source.zig"
        }
    }
}

Kate

  • Install language support for Zig from here
  • Enable LSP client plugin in Kate settings.
  • Add this snippet to LSP client's user settings (e.g. /$HOME/.config/kate/lspclient) (or paste it in LSP client's GUI settings)
{
    "servers": {
        "zig": {
            "command": ["zls"],
            "url": "https://github.com/zigtools/zls",
            "highlightingModeRegex": "^Zig$"
        }
    }
}

Neovim/Vim8

CoC

  • Install the CoC engine from here.

Then choose one of the following two ways

  1. Use extension

    Run :CocInstall coc-zls to install coc-zls, this extension supports the same functionality as the VS Code extension

  2. Manually register

    {
       "languageserver": {
           "zls" : {
               "command": "command_or_path_to_zls",
               "filetypes": ["zig"]
           }
       }
    }

YouCompleteMe

  • Install YouCompleteMeFrom here.
  • Add these lines to your vimrc:
"ensure zig is a recognized filetype
autocmd BufNewFile,BufRead *.zig set filetype=zig

let g:ycm_language_server =
  \ [
  \{
  \     'name': 'zls',
  \     'filetypes': [ 'zig' ],
  \     'cmdline': [ '/path/to/zls_executable' ]
  \    }
  \ ]

nvim-lspconfig

Requires Nvim 0.5 (HEAD)!

  • Install nvim-lspconfig from here.
  • Install zig.vim from here.

nvim-lspconfig already ships a configuration for zls. A simple init.vim might look like this:

call plug#begin('~/.config/nvim/plugged')
Plug 'neovim/nvim-lspconfig'
Plug 'nvim-lua/completion-nvim'
Plug 'ziglang/zig.vim'
call plug#end()

:lua << EOF
    local lspconfig = require('lspconfig')

    local on_attach = function(_, bufnr)
        vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
        require('completion').on_attach()
    end

    local servers = {'zls'}
    for _, lsp in ipairs(servers) do
        lspconfig[lsp].setup {
            on_attach = on_attach,
        }
    end
EOF

" Set completeopt to have a better completion experience
set completeopt=menuone,noinsert,noselect

" Enable completions as you type
let g:completion_enable_auto_popup = 1

LanguageClient-neovim

  • Install the LanguageClient-neovim from here
  • Edit your neovim configuration and add zls for zig filetypes:
let g:LanguageClient_serverCommands = {
       \ 'zig': ['~/code/zls/zig-out/bin/zls'],
       \ }

Emacs

;; Setup lsp-mode as desired.
;; See https://emacs-lsp.github.io/lsp-mode/page/installation/ for more information.
(require 'lsp-mode)

;; Either place zls in your PATH or add the following:
(setq lsp-zig-zls-executable "<path to zls>")

Doom Emacs

  • Enable the lsp module
  • Install the zig-mode package (add (package! zig-mode) to your packages.el file
  • Add the following to your config.el:
(use-package! zig-mode
  :hook ((zig-mode . lsp-deferred))
  :custom (zig-format-on-save nil)
  :config
  (after! lsp-mode
    (add-to-list 'lsp-language-id-configuration '(zig-mode . "zig"))
    (lsp-register-client
      (make-lsp-client
        :new-connection (lsp-stdio-connection "<path to zls>")
        :major-modes '(zig-mode)
        :server-id 'zls))))

Spacemacs

  • Add lsp and zig to dotspacemacs-configuration-layers in your .spacemacs file.
  • If you don't have zls in your PATH, add the following to dotspacemacs/user-config in your .spacemacs file:
(setq lsp-zig-zls-executable "<path to zls>")

Helix

  • Just add zls to your PATH.
  • run hx --health to check if helix found zls.

Related Projects

License

MIT