<!-- This file is generated by scripts/link-docs.mjs. Do not edit manually. -->
# Tinymist Neovim Support for Typst

Run and configure `tinymist` in Neovim with support for all major distros and package managers.

## Feature Integration

- **Language service** (completion, definitions, etc.)
- **Code Formatting**
- **Live Web Preview** with [typst-preview.](https://github.com/chomosuke/typst-preview.nvim)

> [!NOTE]
> > Work for full parity for all `tinymist` features is underway. This will include: exporting to different file types, template preview, and multifile support. Neovim integration is behind VS Code currently but should be caught up in the near future.

## Installation

- (Recommended) [mason.nvim](https://github.com/mason-org/mason.nvim).
  ```lua
  {
    "mason-org/mason.nvim",
    opts = {
      ensure_installed = {
        "tinymist",
      },
    },
  }
  ```
- Or manually:
  To enable LSP, you must install `tinymist`. You can find `tinymist` by:
  - Night versions available at [GitHub Actions](https://github.com/Myriad-Dreamin/tinymist/actions).- Stable versions available at [GitHub Releases](https://github.com/Myriad-Dreamin/tinymist/releases).\
    If you are using the latest version of [typst-ts-mode](https://codeberg.org/meow_king/typst-ts-mode), then you can use command `typst-ts-lsp-download-binary` to download the latest stable binary of `tinymist` at `typst-ts-lsp-download-path`.- Build from source by cargo. You can also compile and install **latest** `tinymist` by [Cargo](https://www.rust-lang.org/tools/install).
    ```bash
    cargo install --git https://github.com/Myriad-Dreamin/tinymist --locked tinymist-cli
    ```

## Configuration

- With `lspconfig`:
  ```lua
  require("lspconfig")["tinymist"].setup {
      settings = {
          formatterMode = "typstyle",
          exportPdf = "onType",
          semanticTokens = "disable"
      }
  }
  ```

- Or with `Coc.nvim`:
  ```json
  {
    "languageserver": {
      "tinymist": {
        "command": "tinymist",
        "filetypes": ["typst"],
        "settings": { ... }
      }
    }
  }
  ```
- Or finally with the builtin lsp protocol:
  ```lua
  vim.lsp.config["tinymist"] = {
      cmd = { "tinymist" },
      filetypes = { "typst" },
      settings = {
          -- ...
      }
  }
  ```

For a full list of available settings see [Tinymist Server Configuration](/editors/neovim/Configuration.md).

## Formatting

Either [`typstyle`](https://typstyle-rs.github.io/typstyle/) or [`typstfmt`](https://github.com/astrale-sharp/typstfmt) can be used. Both are now included in `tinymist`, so you do not need to install them separately if you only intend to use them through `tinymist`. You can select the one you prefer using the `formatterMode` setting. The following snippet shows all formatting settings that you can put in the `settings` table of the snippets from the previous section:

```lua
formatterMode = "typstyle", -- or "typstfmt"
formatterProseWrap = true, -- wrap lines in content mode
formatterPrintWidth = 80,  -- limit line length to 80 if possible
formatterIndentSize = 4,   -- indentation width
```

Note that, since [this Neovim PR](https://github.com/neovim/neovim/pull/19677), neovim uses LSP servers (hence `tinymist` in our case) by default when formatting code. This applies to calls to `vim.lsp.buf.format()` (which formats the whole current buffer) and also to the `gq` command.

## Live Preview

Live preview can be achieved with either a web preview or a pdf reader that supports automatic reloading ([zathura](https://pwmt.org/projects/zathura/) is good).

**Web Preview**

```lua
-- lazy.nvim
{
  'chomosuke/typst-preview.nvim',
  lazy = false, -- or ft = 'typst'
  version = '1.*',
  opts = {}, -- lazy.nvim will implicitly calls `setup {}`
}
```

See [typst-preview](https://github.com/chomosuke/typst-preview.nvim) for more installation and configuration options.

**Pdf Preview**

This preview method is slower because of compilation delays, and additional delays in the pdf reader refreshing.

It is often useful to have a command that opens the current file in the reader.

```lua
vim.api.nvim_create_user_command("OpenPdf", function()
  local filepath = vim.api.nvim_buf_get_name(0)
  if filepath:match("%.typ$") then
    local pdf_path = filepath:gsub("%.typ$", ".pdf")
    vim.system({ "open", pdf_path })
  end
end, {})
```

> [!NOTE]
> > For Neovim prior to v0.9.5, `os.execute` can be used instead. This is not suggested. See [Issue #1606](https://github.com/Myriad-Dreamin/tinymist/issues/1606) for more information.

Make sure to change `exportPdf` to “onType” or “onSave”.

### Working under Power-Saving Mode or with Resource-consumed Projects

When working under power-saving mode or with resource-consumed projects, typst compilations costs too much CPU and memory resources. You can configure the extension to run in syntax only mode, i.e. only performing elementary tasks, like syntax checking, syntax-only code analysis and formatting by setting the `tinymist.syntaxOnly` to `enable` or `onPowerSaving` in the configuration.

For more information about power-saving mode, see [Syntax-Only Mode](https://myriad-dreamin.github.io/tinymist/feature/syntax-only-mode.html).

### Working with Multiple-Files Projects

Tinymist cannot know the main file of a multiple-files project if you don’t tell it explicitly. This causes the well-known label error when editing the `/sub.typ` file in a project like that:

```typ
// in file: /sub.typ
// Error: unknown label 'label-in-main'
@label-in-main
// in file: /main.typ
#include "sub.typ"
= Heading <label-in-main>
```

The solution is a bit internal, which should get further improvement, but you can pin a main file by command.

```lua
require("lspconfig")["tinymist"].setup { -- Alternatively, can be used `vim.lsp.config["tinymist"]`
    -- ...
    on_attach = function(client, bufnr)
        vim.keymap.set("n", "<leader>tp", function()
            client:exec_cmd({
                title = "pin",
                command = "tinymist.pinMain",
                arguments = { vim.api.nvim_buf_get_name(0) },
            }, { bufnr = bufnr })
        end, { desc = "[T]inymist [P]in", noremap = true })

        vim.keymap.set("n", "<leader>tu", function()
            client:exec_cmd({
                title = "unpin",
                command = "tinymist.pinMain",
                arguments = { vim.v.null },
            }, { bufnr = bufnr })
        end, { desc = "[T]inymist [U]npin", noremap = true })
    end,
}
```

Note that `vim.v.null` should be used instead of `nil` in the `arguments` table when unpinning. See [issue #1595](https://github.com/Myriad-Dreamin/tinymist/issues/1595).

For Neovim versions prior to 0.11.0, `vim.lsp.buf.execute_command` should be used instead:

```lua
-- pin the main file
vim.lsp.buf.execute_command({ command = 'tinymist.pinMain', arguments = { vim.api.nvim_buf_get_name(0) } })
-- unpin the main file
vim.lsp.buf.execute_command({ command = 'tinymist.pinMain', arguments = { vim.v.null } })
```

It also doesn’t remember the pinned main file across sessions, so you may need to run the command again after restarting Neovim.

This could be improved in the future.

## Troubleshooting

Generally you can find in depth information via the `:mes` command. `:checkhealth` and `LspInfo` can also provide valuable information. Tinymist also creates a debug log that is usually at `~/.local/state/nvim/lsp.log`. Reporting bugs is welcome.

### tinymist not starting when creating/opening files

This is most commonly due to nvim not recognizing the `.typ` file extension as a `typst` source file. In most cases is can be resolved with:

```typ
:set filetype=typst
```

In older versions of Neovim an autocommand may be necessary.

```vim
autocmd BufNewFile,BufRead *.typ setfiletype typst
```

## Contributing

Please check the [contributing guide](/editors/neovim/CONTRIBUTING.md) for more information on how to contribute to the project.
