1. Introduction
  2. Editor Integration
  3. Common Configurations
  4. 1. Editor Frontends
    1. 1.1. VS Cod(e,ium)
    2. 1.2. Neovim
    3. 1.3. Emacs
    4. 1.4. Sublime Text
    5. 1.5. Helix
    6. 1.6. Zed
  5. Features
  6. 2. Command line interface
  7. 3. Code Documentation
  8. 4. Code Completion
  9. 5. Exporting Documents
  10. 6. Document Preview
  11. 7. Testing
  12. 8. Linting
  13. 9. Other Features
  14. Service Overview
  15. Overview of Service
  16. 10. Principles
  17. 11. Commands System
  18. 12. LSP Inputs
  19. 13. Type System
  20. Service Development
  21. 14. Crate Docs
  22. 15. LSP and CLI
  23. 16. Language Queries
  24. 17. Document Preview

Tinymist Docs

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.
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.

    1
    {
    2
      "williamboman/mason.nvim",
    3
      opts = {
    4
        ensure_installed = {
    5
          "tinymist",
    6
        },
    7
      },
    8
    }
    1
    {
    2
      "williamboman/mason.nvim",
    3
      opts = {
    4
        ensure_installed = {
    5
          "tinymist",
    6
        },
    7
      },
    8
    }
  • Or manually:

    #

    Finding Executable

    To enable LSP, you must install tinymist. You can find tinymist by:

    • Night versions available at GitHub Actions.

    • Stable versions available at GitHub Releases.
      If you are using the latest version of 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.

      1
      cargo install --git https://github.com/Myriad-Dreamin/tinymist --locked tinymist
      1
      cargo install --git https://github.com/Myriad-Dreamin/tinymist --locked tinymist

#

Configuration

  • With lspconfig:

    1
    require("lspconfig")["tinymist"].setup {
    2
        settings = {
    3
            formatterMode = "typstyle",
    4
            exportPdf = "onType",
    5
            semanticTokens = "disable"
    6
        }
    7
    }
    1
    require("lspconfig")["tinymist"].setup {
    2
        settings = {
    3
            formatterMode = "typstyle",
    4
            exportPdf = "onType",
    5
            semanticTokens = "disable"
    6
        }
    7
    }
  • Or with Coc.nvim:

    1
    {
    2
      "languageserver": {
    3
        "tinymist": {
    4
          "command": "tinymist",
    5
          "filetypes": ["typst"],
    6
          "settings": { ... }
    7
        }
    8
      }
    9
    }
    1
    {
    2
      "languageserver": {
    3
        "tinymist": {
    4
          "command": "tinymist",
    5
          "filetypes": ["typst"],
    6
          "settings": { ... }
    7
        }
    8
      }
    9
    }
  • Or finally with the builtin lsp protocol:

    1
    vim.lsp.config["tinymist"] = {
    2
        cmd = { "tinymist" },
    3
        filetypes = { "typst" },
    4
        settings = {
    5
            -- ...
    6
        }
    7
    }
    1
    vim.lsp.config["tinymist"] = {
    2
        cmd = { "tinymist" },
    3
        filetypes = { "typst" },
    4
        settings = {
    5
            -- ...
    6
        }
    7
    }

For a full list of available settings see Tinymist Server Configuration.

#

Formatting

Either typstyle or typstfmt. Both are now included in tinymist, you can select the one you prefer with:

1
formatterMode = "typstyle"
1
formatterMode = "typstyle"

#

Live Preview

Live preview can be achieved with either a web preview or a pdf reader that supports automatic reloading (zathura is good).

Web Preview

1
-- lazy.nvim
2
{
3
  'chomosuke/typst-preview.nvim',
4
  lazy = false, -- or ft = 'typst'
5
  version = '1.*',
6
  opts = {}, -- lazy.nvim will implicitly calls `setup {}`
7
}
1
-- lazy.nvim
2
{
3
  'chomosuke/typst-preview.nvim',
4
  lazy = false, -- or ft = 'typst'
5
  version = '1.*',
6
  opts = {}, -- lazy.nvim will implicitly calls `setup {}`
7
}

See typst-preview 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.

1
vim.api.nvim_create_user_command("OpenPdf", function()
2
  local filepath = vim.api.nvim_buf_get_name(0)
3
  if filepath:match("%.typ$") then
4
    local pdf_path = filepath:gsub("%.typ$", ".pdf")
5
    vim.system({ "open", pdf_path })
6
  end
7
end, {})
1
vim.api.nvim_create_user_command("OpenPdf", function()
2
  local filepath = vim.api.nvim_buf_get_name(0)
3
  if filepath:match("%.typ$") then
4
    local pdf_path = filepath:gsub("%.typ$", ".pdf")
5
    vim.system({ "open", pdf_path })
6
  end
7
end, {})
For Neovim prior to v0.9.5, os.execute can be used instead. This is not suggested. See Issue #1606 for more information.

Make sure to change exportPdf to "onType" or "onSave".

#

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:

1
// in file: /sub.typ
2
// Error: unknown label 'label-in-main'
3
@label-in-main
4
// in file: /main.typ
5
#include "sub.typ"
6
= Heading <label-in-main>
1
// in file: /sub.typ
2
// Error: unknown label 'label-in-main'
3
@label-in-main
4
// in file: /main.typ
5
#include "sub.typ"
6
= Heading <label-in-main>

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

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

12
        vim.keymap.set("n", "<leader>tu", function()
13
            client:exec_cmd({
14
                title = "unpin",
15
                command = "tinymist.pinMain",
16
                arguments = { vim.v.null },
17
            }, { bufnr = bufnr })
18
        end, { desc = "[T]inymist [U]npin", noremap = true })
19
    end,
20
}
1
require("lspconfig")["tinymist"].setup { -- Alternatively, can be used `vim.lsp.config["tinymist"]`
2
    -- ...
3
    on_attach = function(client, bufnr)
4
        vim.keymap.set("n", "<leader>tp", function()
5
            client:exec_cmd({
6
                title = "pin",
7
                command = "tinymist.pinMain",
8
                arguments = { vim.api.nvim_buf_get_name(0) },
9
            }, { bufnr = bufnr })
10
        end, { desc = "[T]inymist [P]in", noremap = true })
11

12
        vim.keymap.set("n", "<leader>tu", function()
13
            client:exec_cmd({
14
                title = "unpin",
15
                command = "tinymist.pinMain",
16
                arguments = { vim.v.null },
17
            }, { bufnr = bufnr })
18
        end, { desc = "[T]inymist [U]npin", noremap = true })
19
    end,
20
}

Note that vim.v.null should be used instead of nil in the arguments table when unpinning. See issue #1595.

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

1
-- pin the main file
2
vim.lsp.buf.execute_command({ command = 'tinymist.pinMain', arguments = { vim.api.nvim_buf_get_name(0) } })
3
-- unpin the main file
4
vim.lsp.buf.execute_command({ command = 'tinymist.pinMain', arguments = { vim.v.null } })
1
-- pin the main file
2
vim.lsp.buf.execute_command({ command = 'tinymist.pinMain', arguments = { vim.api.nvim_buf_get_name(0) } })
3
-- unpin the main file
4
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:

1
:set filetype=typst
1
:set filetype=typst

In older versions of Neovim an autocommand may be necessary.

1
autocmd BufNewFile,BufRead *.typ setfiletype typst
1
autocmd BufNewFile,BufRead *.typ setfiletype typst

#

Contributing

You can submit issues or make PRs to GitHub.