Tinymist IntelliJ Plugin

July 7, 2026 · View on GitHub

Last Updated: August 31, 2025

The goal of this project is to provide comprehensive Typst language support for IntelliJ-based IDEs. We are using the lsp4ij library developed by Red Hat (https://github.com/redhat-developer/lsp4ij).

Prerequisites

  • IntelliJ IDEA: Other IDEs will also work, but given developing a plugin for IntelliJ, the best support for that is provided by IntelliJ.
  • JDK 21 You must choose JDK 21 in the IntelliJ IDEA settings.

Core Directory Structure

  • editors/intellij/: Root directory for the IntelliJ plugin.
    • build.gradle.kts: Gradle build script for managing dependencies (like lsp4ij, IntelliJ Platform SDK) and plugin packaging.
    • src/main/kotlin/org/tinymist/intellij/: Contains the core Kotlin source code for the plugin. This is further structured into sub-packages like lsp, preview, and structure.
    • src/main/resources/META-INF/plugin.xml: The plugin descriptor file, essential for IntelliJ to load and recognize the plugin and its components (e.g., language support, LSP integration, preview editors, structure view).

Build the Plugin

You can build the plugin using the Gradle tool window in IntelliJ (Tasks > intellij > buildPlugin) or via the terminal:

./gradlew :intellij:buildPlugin

Launch the Plugin

Use the Gradle task runIde (Tasks > intellij > runIde) from the Gradle tool window or terminal:

./gradlew :intellij:runIde

Using a custom tinymist Language Server Executable

Ensure that tinymist is installed on your system and the path in TinymistLspStreamConnectionProvider.kt is correct for your development environment if you are modifying the LSP.

Viewing Logs

  • IntelliJ Plugin Logs: Check the idea.log file of the sandboxed IntelliJ instance. You can find its location via "Help" > "Show Log in Finder/Explorer" in the sandbox IDE.
  • LSP Communication Logs: lsp4ij provides an "LSP Consoles" view in the sandbox IDE (usually accessible from the tool window bar at the bottom left). Set its verbosity (e.g., to "verbose") via Languages & Frameworks > Language Servers settings to see JSON-RPC messages between the plugin and tinymist.

Project Roadmap & Status

I. Completed Milestones

  • Initial Server Integration: Resolved server startup crashes.
  • Basic Diagnostics: Implemented linting/diagnostics with custom formatting.
  • Core LSP Features:
    • textDocument/completion (Code Completion) - Fully implemented and tested
    • textDocument/hover (Hover Information) - Fully implemented and tested
    • textDocument/definition (Go To Definition) - Fully implemented and tested
    • textDocument/signatureHelp (Signature Help) - Implemented
    • textDocument/rename (Rename Symbol) - Implemented
  • Configuration: Robust executable path resolution with settings integration
  • Preview Integration: Full JCEF-based preview with tinymist's background preview server
  • Settings Panel: Comprehensive settings panel with server management modes (auto-install vs custom path)
  • Automated Server Installation: Full cross-platform auto-installation system for tinymist binaries
  • Server Management: Dual-mode server management (AUTO_MANAGE for auto-installation, CUSTOM_PATH for manual configuration)

LSP Features Implementation Status

The following table shows the implementation status of LSP features as supported by the tinymist server:

LSP FeatureStatusImplementation TypeNotes
textDocument/completion✅ ImplementedHandled by lsp4ijAuto-completion for Typst syntax and functions
textDocument/hover✅ ImplementedHandled by lsp4ijDocumentation and type information on hover
textDocument/definition✅ ImplementedHandled by lsp4ijGo to definition functionality
textDocument/signatureHelp✅ ImplementedHandled by lsp4ijFunction signature hints
textDocument/rename✅ ImplementedHandled by lsp4ijSymbol renaming
textDocument/publishDiagnostics✅ ImplementedDirect implementationCustom diagnostic formatting with HTML support (TinymistLanguageClient.kt:24)
textDocument/semanticTokens✅ ImplementedHandled by lsp4ijSemantic syntax highlighting
textDocument/references✅ ImplementedHandled by lsp4ijFind all references to a symbol
textDocument/documentHighlight✅ partly implementedHandled by lsp4ijHighlight related symbols; currently the highlight only works upon entirely selecting a symbol not just placing the carret there
textDocument/documentSymbol✅ ImplementedHandled by lsp4ijDocument outline/structure view
textDocument/inlayHint✅ ImplementedHandled by lsp4ijInlay additional information into code editor, i.e. the names of function parameters
textDocument/codeAction✅ ImplementedHandled by lsp4ijCode fixes and refactoring actions
textDocument/formatting❌ Not implemented-Document formatting
textDocument/rangeFormatting❌ Not implemented-Range-based formatting
textDocument/onTypeFormatting❌ Not implemented-Format-on-type
textDocument/codeLens❌ Not implemented-Inline code annotations
textDocument/foldingRange✅ ImplementedHandled by lsp4ijCode folding regions
textDocument/selectionRange✅ ImplementedHandled by lsp4ijSmart text selection
textDocument/prepareCallHierarchy❌ Not implemented-Call hierarchy preparation
textDocument/callHierarchy/incomingCalls❌ Not implemented-Incoming call hierarchy
textDocument/callHierarchy/outgoingCalls❌ Not implemented-Outgoing call hierarchy
textDocument/linkedEditingRange❌ Not implemented-Linked editing of related symbols
textDocument/moniker❌ Not implemented-Symbol monikers for cross-references
workspace/didChangeConfiguration✅ ImplementedHandled by lsp4ijConfiguration change notifications
workspace/didChangeWatchedFiles✅ ImplementedHandled by lsp4ijFile watching
workspace/symbol✅ ImplementedHandled by lsp4ijWorkspace-wide symbol search
window/showMessage✅ ImplementedHandled by lsp4ijServer messages to client
window/showMessageRequest✅ ImplementedHandled by lsp4ijMessage request handling
tinymist/document✅ ImplementedDirect implementationCustom tinymist notification (TinymistLanguageClient.kt:58)
tinymist/documentOutline✅ Not implementedDirect implementationCustom outline notification (TinymistLSPDiagnosticFeature)

Legend:

  • ✅ Implemented: Feature is working and available
  • ❌ Not implemented: Feature is not yet implemented in the plugin
  • Handled by lsp4ij: Feature implementation is provided by the lsp4ij library
  • Direct implementation: Feature has custom implementation in the plugin code

II. Current Focus

  • Debug server startup procedure
    • currently no logs are shown in the preview. Is this because, our current method sends a command before the initialization?
  • Preview Panel Stability: Handle server connection state
  • A PreviewServerManager class to manage the server connection state and setup
    • The preview panel should subscribe to the events from the preview manager
    • The PreviewServerManager should start (and stop?) the preview server via the LSP command tinymist/startPreview
    • The preview server holds one of these states:
      • Server starting up -> the preview panel displays a message
      • Server ready -> the preview panel loads URL:port as preview
      • Server failed -> the preview panel displays an error message
    • The PreviewServerManager informs its subscribers (mainly the preview panel) about state change

III. Next steps

  • Investigate textDocument/formatting + variant capabilities
  • Debug failing integration tests

V. Planned Features & Enhancements

  • Additional LSP Features:
    • textDocument/formatting (Document formatting)
  • Enhanced Settings Panel:
    • Configure font paths, PDF export options
    • Settings for tinymist preview server configuration
  • Make the editor more colorfull. Does the current situation have something to do with 'textDocument/documentColor' not answering?

VI. Technical Debt & Refinements

  • Missing File Type Icon: TODO in TypstLanguage.kt - need to add custom icon for .typ files.
  • LSP Initialization Options: Currently commented out in TinymistLspStreamConnectionProvider.kt - initialization options for the LSP server (e.g., colorTheme, preview URL, preview.background.enabled) should be configurable via settings panel.

File Overview

This section outlines the architecture of the Tinymist IntelliJ plugin, detailing the roles of key files and their interactions, particularly with the IntelliJ Platform and LSP4IJ APIs.

Kotlin Source Files (src/main/kotlin/org/tinymist/intellij/)

The source code is organized into the following main areas:

  1. Base Language Support (org.tinymist.intellij)

    • TypstLanguage.kt: Defines TypstLanguage (a subclass of com.intellij.lang.Language) and TypstFileType (a subclass of com.intellij.openapi.fileTypes.LanguageFileType). This is the fundamental registration of "Typst" as a recognized language and file type within the IntelliJ Platform.
    • TypstFile.kt: Defines TypstFile (a subclass of com.intellij.extapi.psi.PsiFileBase). This class represents a Typst file in IntelliJ's Program Structure Interface (PSI) tree, allowing the platform to understand it as a structured file.
    • Local Parsing/Lexing/Highlighting: The plugin does not currently include or register custom local lexers (TypstLexerAdapter.kt), parsers (TypstParserDefinition.kt), or syntax highlighters (TypstSyntaxHighlighter.kt). It relies on the LSP server for semantic tokens for syntax highlighting and for other structural understanding. The grammar files in src/main/grammars/ are unused by the plugin's runtime.
  2. LSP (Language Server Protocol) Integration (org.tinymist.intellij.lsp)

    • TinymistLanguageServerFactory.kt: Implements com.redhat.devtools.lsp4ij.LanguageServerFactory. Creates instances of TinymistLspStreamConnectionProvider for server connection, provides TinymistLSPDiagnosticFeature for custom diagnostic handling, and includes TinymistLanguageServerInstaller for automated server installation.
    • TinymistLspStreamConnectionProvider.kt: Extends com.redhat.devtools.lsp4ij.server.OSProcessStreamConnectionProvider. This class manages the lifecycle and communication with the tinymist LSP executable using sophisticated executable resolution:
      • Uses TinymistSettingsService to determine server management mode (AUTO_MANAGE or CUSTOM_PATH)
      • For AUTO_MANAGE mode: Uses TinymistLanguageServerInstaller to get automatically installed executable path
      • For CUSTOM_PATH mode: Uses user-configured executable path from settings
      • Initialization options are currently commented out (TODO) but previously provided server configuration
    • TinymistLanguageServerInstaller.kt: Comprehensive auto-installation system that downloads and installs platform-specific tinymist binaries from GitHub releases. Supports Windows, macOS (x64/ARM64), and Linux (x64/ARM64) with proper archive extraction and executable permissions.
    • TinymistLanguageClient.kt: Extends com.redhat.devtools.lsp4ij.client.LanguageClientImpl. This custom client handles Tinymist-specific LSP notifications and can customize how standard LSP messages are processed.
      • @JsonNotification("tinymist/document") handleDocument(...): Placeholder for handling a custom notification, potentially for preview updates or other document-specific events. (Currently logs receipt).
      • publishDiagnostics(...): Overrides the default handler to reformat diagnostic messages (errors, warnings) from the server (e.g., replacing newlines with <br>) for better display in IntelliJ's UI.
      • showMessageRequest(...): Overrides the default to handle window/showMessageRequest from the server, mainly to log them and prevent potential NPEs in lsp4ij if actions are null.
  3. Settings Management (org.tinymist.intellij.settings)

    • TinymistSettingsService.kt: Application-level service that implements PersistentStateComponent<TinymistSettingsState> for persistent storage of plugin settings. Provides convenient accessors for tinymistExecutablePath and serverManagementMode.
    • TinymistSettingsState.kt: Data class defining the plugin's settings state, including ServerManagementMode enum (AUTO_MANAGE vs CUSTOM_PATH) and executable path configuration.
    • TinymistSettingsPanel.kt: Swing-based UI panel for the settings interface with radio buttons for server management mode and text field for custom executable path.
    • TinymistSettingsConfigurable.kt: Implements Configurable interface to integrate the settings panel into IntelliJ's Settings/Preferences dialog under "Tools > Tinymist LSP".
    • TinymistVersion.kt: Version management for the tinymist server, used by the installer to determine which version to download.
  4. JCEF-based Preview (org.tinymist.intellij.preview)

    • TypstPreviewFileEditor.kt: Implements com.intellij.openapi.fileEditor.FileEditor and uses com.intellij.ui.jcef.JCEFHtmlPanel to embed a Chromium-based browser view. This editor displays the live preview of the Typst document.
      • It connects to a web server (e.g., http://127.0.0.1:23635) that is started and managed by the tinymist language server itself (when preview.background.enabled is true).
      • It includes logic to wait for the server to be available before attempting to load the URL.
      • It handles cases where JCEF might not be supported in the user's environment.
    • TypstPreviewFileEditorProvider.kt: Implements com.intellij.openapi.fileEditor.FileEditorProvider. This provider is responsible for creating instances of TypstPreviewFileEditor when IntelliJ needs to open a preview for a Typst file. It also defines the editor's ID and policy (e.g., where it should be placed relative to other editors).
    • TypstTextEditorWithPreviewProvider.kt: Extends com.intellij.openapi.fileEditor.TextEditorWithPreviewProvider. This class is the main entry point registered in plugin.xml for opening Typst files. It combines a standard text editor (provided by IntelliJ) with the custom TypstPreviewFileEditor (obtained via TypstPreviewFileEditorProvider), allowing for a side-by-side text and preview editing experience. It accepts files of type TypstFileType.

Key Interactions

  • IntelliJ Platform & Plugin Startup: IntelliJ reads plugin.xml to discover the plugin's capabilities. It registers TypstLanguage and TypstFileType.
  • Opening a Typst File:
    • TypstTextEditorWithPreviewProvider is invoked, creating a split editor with a text part and a TypstPreviewFileEditor.
    • TinymistLanguageServerFactory is triggered, which starts TinymistLspStreamConnectionProvider to launch the tinymist LSP server process.
    • TinymistLanguageClient establishes communication with the server.
  • LSP Communication:
    • The client and server exchange JSON-RPC messages for features like diagnostics, completion, hover, etc.
    • TinymistLanguageClient handles custom notifications like tinymist/document (currently a placeholder). A tinymist/documentOutline handler would be needed for a Structure View.
  • Structure View:
    • (Currently not implemented as described in dev-notes.md). If implemented, when the user opens the Structure View, a TypstStructureViewFactory would create a TypstStructureViewModel.
    • The view model would fetch data (potentially from an OutlineDataHolder populated by TinymistLanguageClient) and build the tree.
  • Preview Panel:
    • TypstPreviewFileEditor loads its content from the HTTP server run by the tinymist LSP (if preview.background.enabled is true in initialization options).
    • Updates to the preview are likely driven by the tinymist server itself, potentially triggered by textDocument/didChange notifications from the client or its own file watching.