Skip to content

Editor Integration (LSP)

GMX includes a built-in Language Server Protocol (LSP) server that provides real-time editor support for .gmx files.

Features

Feature Description
Diagnostics Parse errors displayed in real-time as you type
Semantic Highlighting Syntax-aware coloring for keywords, types, variables, strings, numbers, operators, and annotations
Hover Information Documentation on hover for models (fields), functions (signature), services, annotations, keywords, and types
Autocompletion Context-aware suggestions: annotations after @, types after :, section tags after <, ORM methods after ., keywords and model names elsewhere

Starting the Server

gmx lsp            # Start on stdio (default)
gmx lsp --debug    # Enable debug logging on stderr

The LSP server communicates over stdio (stdin/stdout), which is the standard transport for most editors.

Editor Setup

VS Code

Create or edit .vscode/settings.json in your workspace:

{
  "lsp": {
    "gmx": {
      "command": "gmx",
      "args": ["lsp"],
      "filetypes": ["gmx"]
    }
  }
}

If you use a generic LSP client extension (e.g. vscode-lsp-client), configure it to run gmx lsp for files matching *.gmx.

Neovim (nvim-lspconfig)

Add to your Neovim configuration:

vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
  pattern = "*.gmx",
  callback = function()
    vim.bo.filetype = "gmx"
  end,
})

vim.lsp.config('gmx', {
  cmd = { 'gmx', 'lsp' },
  filetypes = { 'gmx' },
  root_markers = { 'go.mod', '.git' },
})

vim.lsp.enable('gmx')

Helix

Add to ~/.config/helix/languages.toml:

[[language]]
name = "gmx"
scope = "source.gmx"
file-types = ["gmx"]
roots = ["go.mod"]
language-servers = ["gmx-lsp"]

[language-server.gmx-lsp]
command = "gmx"
args = ["lsp"]

Zed

Add to your Zed settings (settings.json):

{
  "lsp": {
    "gmx": {
      "binary": {
        "path": "gmx",
        "arguments": ["lsp"]
      }
    }
  },
  "languages": {
    "GMX": {
      "language_servers": ["gmx"]
    }
  },
  "file_types": {
    "GMX": ["gmx"]
  }
}

Sublime Text (LSP package)

Install the LSP package, then add to LSP settings:

{
  "clients": {
    "gmx": {
      "enabled": true,
      "command": ["gmx", "lsp"],
      "selector": "source.gmx"
    }
  }
}

Emacs (lsp-mode)

(with-eval-after-load 'lsp-mode
  (add-to-list 'lsp-language-id-configuration '(gmx-mode . "gmx"))
  (lsp-register-client
   (make-lsp-client
    :new-connection (lsp-stdio-connection '("gmx" "lsp"))
    :activation-fn (lsp-activate-on "gmx")
    :server-id 'gmx-lsp)))

Capabilities

Diagnostics

The LSP re-parses your .gmx file on every change and reports parse errors as diagnostics. Errors appear inline in your editor with line and column information.

Semantic Tokens

The server provides full semantic token highlighting with these token types:

Token Type Examples
keyword model, func, let, const, if, else, return, try, render, import
type Task, User (capitalized identifiers)
function (reserved for future use)
variable title, done, count (lowercase identifiers)
string "hello", `template`
number 42, 3.14
operator =, +, -, ==, !=, &&, ||
decorator @ (annotation marker)

Hover

Hovering over an identifier shows contextual documentation:

  • Model names — list of fields with types and annotations
  • Function names — full signature with parameters and return type
  • Service names — provider and available methods
  • Annotations (pk, unique, default, etc.) — description and syntax
  • Keywords (try, render, ctx, etc.) — usage description
  • Types (string, int, uuid, etc.) — type description

Completion

Autocompletion triggers depend on context:

Trigger Context Suggestions
@ After @ in a field Annotations: pk, unique, default(...), min(...), max(...), email, relation(...)
: After field name colon Types: string, int, float, bool, uuid, datetime
< Start of a section tag Tags: script, template, style, style scoped
. After an identifier ORM methods: findMany, findUnique, create, update, delete, count
(default) Anywhere else Keywords + declared model names

Architecture

The LSP server reuses the existing GMX compiler pipeline:

Editor ──stdio──▶ gmx lsp
              DocumentStore (thread-safe)
            ┌───────┼───────┐
            ▼       ▼       ▼
         Lexer   Parser   AST
            │       │       │
            ▼       ▼       ▼
       Semantic  Errors   Hover &
        Tokens  → Diags  Completion

Each open document is stored with its latest content, AST, and parse errors. On every change, the document is re-parsed using the same lexer.New()parser.New().ParseGMXFile() pipeline as the compiler.