What is the best Setup for Using Typst in Helix Editor?

I am trying to explore alternative options to VSCode/VSCodium for editing Typst files, while maintaining the amazing features Tinymist can provide. Zed, my other main editor, isn’t there yet, since it doesn’t provide much of an extension API for all of tinymist’s features to be usable.

One option I’ve been considering is Helix. I’ve been meaning to get over the learning curve of modal editors, and Typst would be a good option. However, I do not want to bother if I lose most of Tinymist’s functionality. I know of this page, but I still have a couple questions.

  • Is there a best PDF viewer to use for live previews?
  • Related to the above, do any PDF viewers support the syncing feature, where I can click anywhere on the PDF and then get sent to the relevant spot in the Typst files?

Also, do people have any recommended configuration files for Helix for the best out-of-the-box experience with Typst?

2 Likes

I use Helix from time to time for small files. You don’t need to configure anything, just install tinymist. It has been listed in the default LSP configuration.

For bigger documents with a main and subfiles, the recommended configuration is the one to go with.

You might want to re-format from time to time, you can just select the whole buffer and pipe it into typstyle.

For live previews, I use zathura and it works well.

1 Like

I do all my Typst editing in Helix with Tinymist and it works well for me. For preview with Tinymist you have a choice:

  • Preview in PDF. Depending on settings the PDF gets recompiled either when you save (basically the same as typst watch) or on each keystroke. It’s the simplest to configure, but even with preview on keystroke there’s quite some lag and as far as I know there’s no way to get synctex-like “click PDF to jump to source code”.

    To export PDF when you save the source file you can use the following in the Helix languages.toml:

    [language-server.tinymist]
    command = "tinymist"
    config.exportPdf = "onSave"
    

    Replace onSave with onType to export on each keystroke.

  • Live preview in browser. In this case Tinymist serves a web page locally on some port. When you load this page in the browser you see the document, and changes are applied instantly (much snappier than with PDF export.) And it supports click-to-source!

    The live preview configuration is documented here and here but it’s a bit messy currently. Here’s what I use:

    [language-server.tinymist]
    command = "tinymist"
    config.preview.background.enabled = true
    config.preview.background.args = [
      "--data-plane-host=127.0.0.1:0", "--invert-colors=never", "--open"]
    

    This specifies 0 for the server port, so Tinymist will choose a random port the first time I open a Typst file in a given Helix instance. With --open, Tinymist will also open a tab in my browser showing the page served on this port. So with this configuration I automatically get one preview tab in the browser for each Helix instance that edits Typst files.

The next big issue is how to handle multi-file projects. Here also you have the choice:

  • Hardcode the main file in each project’s directory. In the directory you create a local config file .helix/languages.toml with something like

    [language-server.tinymist.config]
    typstExtraArgs = ["my-main-file.typ"]
    

    I find it a bit annoying to maintain these config files, especially when I want to switch between different “main” files in the same directory.

  • Configure a keybinding to set the current file as “main”. With the latest Helix version (25.07) it is now possible to send commands with arguments to the Language Server (Tinymist), so you can add the following to the Helix config file (~/.config/helix/config.toml on Linux):

    [keys.normal]
    "C-m" = ':lsp-workspace-command tinymist.pinMain "%sh{realpath %{buffer_name}}"'
    

    This way you can press Ctrl+M in Helix in normal mode to set the current file as “main” for the browser preview. In the same Helix instance you can switch to e.g. main2.typ, press Ctrl+M again and the same browser tab will now show the preview using main2.typ as main file.

5 Likes

Thank you @quachpas and @sijo. This helps out a lot.

@sijo To complete the discussion regarding browsers, how does Helix choose which browser to open for editing files? Does it use the default browser on one’s machine?

It uses the Rust open crate. From the crate’s README:

Use this library to open a path or URL using the program configured on the system. It is equivalent to running one of the following:

# macOS
$ open <path-or-url>
# Windows
$ start <path-or-url>
# Linux
$ xdg-open <path-or-url> || gio open <path-or-url> || gnome-open <path-or-url> || kde-open <path-or-url> || wslview <path-or-url>

so on Linux it’s typically using the xdg-open executable.

2 Likes

Just to expand about PDF viewer part of the initial question.

From my book, Getting Started with Typst - Typst Examples Book, these are some PDF-viewers that support live preview:

  • SumatraPDF (works on Windows)
  • Zathura and Sioyek (Linux)

: if they detect the pdf file has changed, they update the view with just a little blink, so it’s not perfect, but still good.

There are maybe some more that support that feature, but I haven’t found other mentions on Discord.

Unfortunately, it’s almost impossible to make it work with click to jump to source, as that would require integration with LSP.

2 Likes

Thanks for mentioning sioyek! I didn’t know about it, it seems to be an awesome PDF reader, minimalist GUI and keyboard focused like zathura but with impressive features (see https://sioyek.info/).

MuPDF with entr that sends refresh signal. It also has pretty good dark mode, unlike some others (but not as good as Okular).

1 Like

Okular also supports live-reload as well as inverting color brightness, though the latter is somewhat hidden in accessibility settings.

@sijo thanks for the write-up! I didn’t even know about tinymist’s live-preview yet xD