Project Model
This section documents the experimental project management feature. Implementation may change in future releases.
This setting controls how Tinymist resolves projects:
-
singleFile
singleFile
(Default): Treats each Typst file as an independent document (similar to Markdown workflows). No lock files or project caches are generated, which is suitable for most people who work with single Typst files or small projects. -
lockDatabase
lockDatabase
: Mimics Rust's project management by tracking compilation/preview history. Stores data in lock files (tinymist.lock
tinymist.lock
) and cache directories, enabling automatic main file selection based on historical context.
When working with multiple-file projects, Tinymist faces the challenge of determining which file to use as the main file for compilation and preview. This is because:
- All project files (entries, includes, imports) share
.typ
.typ
extensions. - No inherent distinction exists between entry files and dependencies.
- Automatic detection is ambiguous without context.
This resembles the situation in C++, where the language server also struggles to determine the header files and source files in a project. In C++, the language servers and IDEs relies on the compile_commands.json
compile_commands.json
file to understand the compilation context.
Inspired by C++ and Rust, we introduced the lockDatabase
lockDatabase
resolution method to relieve pain of handling multiple-file projects.
This is the default resolution method and has been used for years. Despite using singleFile
singleFile
, you can still work with multiple files:
- The language server will serve the previewed file as the main file when previewing a file.
-
Pinning a main file manually by commands is possible:
- Use command
Typst Pin Main
Typst Pin Main
(tinymist.pinMainToCurrent) to set the current file as the main file. - Use command
Typst Unpin Main
Typst Unpin Main
(tinymist.unpinMain) to unset the main file.
- Use command
This feature is in early development stage, and may contain bugs or incomplete features. The following sample demonstrates how to use the lockDatabase
lockDatabase
resolution method. Here is the related test.
- Set
projectResolution = "lockDatabase"
projectResolution = "lockDatabase"
in LSP settings. - Like
scripts
scripts
/test-lock.sh
test-lock.sh
, compile a file using tinymist CLI with--save-lock
--save-lock
flag:tinymist compile --save-lock main.typ
tinymist compile --save-lock main.typ
. This will create atinymist.lock
tinymist.lock
file in the current directory, which contains the Compilation History and project routes. - back to the editor, editing
chapters
chapters
/chapter1.typ
chapter1.typ
will trigger PDF export ofmain.typ
main.typ
automatically.
Please report issue on GitHub if you find any bugs, missing features, or have any questions about this feature.
We have been aware of backward compatibility issues, but any change of the schema of tinymist.lock
tinymist.lock
may corrupt the tinymist.lock
tinymist.lock
intentionally or unintentionally. The schema is unstable and in beta stage. You have to remove the tinymist.lock
tinymist.lock
file to recovery from errors, and you could open an issue to discuss with us. To reliably keep compilation commands, please put tinymist compile
tinymist compile
commands in build system such as Makefile
Makefile
or justfile
justfile
.
The Project Model only relies on the concept of Compilation History and we will explain how it works and how to use.
The Compilation History (tinymist.lock
tinymist.lock
) is a set of records. Each record contains the following information about compilation:
- Input Args: Main file path, fonts, features (e.g., HTML/Paged as export target).
- Export Args: Output path, PDF standard to use.
The source of Compilation History:
- (Implemented) CLI commands:
tinymist compile/preview --save-lock
tinymist compile/preview --save-lock
, suitable for all the editor clients. - (Not Implemented) LSP commands:
tinymist.exportXXX
tinymist.exportXXX
/previewXXX
previewXXX
, suitable for vscode or neovim clients, which allows client-side extension. - (Not Implemented) External tools: Tools that update the lock file directly. For example, the tytanic could update all example documents once executed test commands. The official typst could also do this to tell whether a test case is compiled targeting HTML or PDF.
There are several features that can be implemented using the Compilation History:
- Correct Entry Detection: When a user runs the compile or preview commands, Tinymist will save the Compilation History to the lock file and the language server will identify the main file correctly.
- Dynamic Entry Switching: When a user runs another compile command, the newer command will have higher priorit, and Tinymist will "switch" the main file accordingly.
- Per-Document Flags: Some documents are compiled to HTML, while others are compiled to PDF. The users can specify more compile flags for each document.
- Session Persistence: Users can open the recently previewed file and continue editing it. More state such as the scroll position could be remembered in future.
- Sharing and VCS: The lock file can be shared with other users by tools like git, allowing them to compile the same project with the same settings.
- Storage in file system: stored in
tinymist.lock
tinymist.lock
(TOML) files. When resolving a depended file, the nearest lock file will be used to determine the compilation arguments. - Storage in memory: The language server also maintains a Compilation History and project routes in memory. We may enable in-memory Compilation History by default in the future, which will allow Tinymist to resolve projects smarter.
The language server will load route entries from disk or memory, combine, and perform entry lookup based on the route table. Specificially, The depended files of a single compilation will be stored as route entries in the cache directory after compilation. A single route entry is a triple, (Dependent Path, Project ID, Priority), where:
- "Dependent Path" is an absoulte dependent file path, like paths to assets and source files in packages.
- "Project ID" is the project id (main file) indexing an entry in the Compilation History (
tinymist.lock
tinymist.lock
). - "Priority" is a priority number.
And the language server determines a project id associating some dependent file by the following rules:
- Highest priority routes take precedence.
- Most recent updated projects in Compilation History prioritized automatically.
The cache directory contains cache of project routes. Currently, we haven't implemented a way clean up or garbage collect the project route cache, and disk cache may be deprecated in future. It is safe to remove all the project routes in the cache directory, as Tinymist will regenerate them when needed.