Skip to content

Language Server Protocol for Go templates

License

Notifications You must be signed in to change notification settings

toba/go-template-lsp

Repository files navigation

Go Template LSP

A Language Server Protocol (LSP) implementation for Go templates (text/template and html/template).

Features

  • Diagnostics: Real-time syntax error detection and semantic analysis (undefined variables, missing fields, unknown functions)
  • Hover: Type information and documentation on hover over template variables and functions
  • Go to Definition: Navigate to template definitions ({{define "name"}})
  • Formatting: Re-indent based on HTML and template nesting, with optional attribute wrapping
  • Folding Ranges: Collapse template blocks ({{if}}...{{end}}, {{range}}...{{end}}) and comments
  • Semantic Tokens: Enhanced syntax highlighting for keywords, variables, functions, strings, numbers, and operators
  • Document Highlight: Highlight matching template keywords (e.g. click {{if}} to highlight its {{else}} and {{end}})
  • Document Links: Clickable links in template documents
  • Custom Function Discovery: Automatically scans Go source files for template.FuncMap definitions so custom functions are recognized
  • CLI Linting: check subcommand for CI/CD and command-line diagnostics

Installation

Download Binary

Download prebuilt binaries from GitHub Releases.

Install from Source

go install github.com/toba/go-template-lsp/cmd/go-template-lsp@latest

Build from Source

# Clone the repository
git clone https://github.com/toba/go-template-lsp.git
cd go-template-lsp

# Build the binary
go build -o go-template-lsp ./cmd/go-template-lsp

# Or install to $GOBIN
go install ./cmd/go-template-lsp

# Run tests
go test ./...

# Run linter
golangci-lint run

Editor Integration

Zed

Use the gozer Zed extension, which automatically downloads this LSP.

Neovim (with nvim-lspconfig)

local lspconfig = require('lspconfig')
local configs = require('lspconfig.configs')

configs.gotmpl = {
  default_config = {
    cmd = { 'go-template-lsp' },
    filetypes = { 'gotmpl', 'gohtml', 'html' },
    root_dir = lspconfig.util.root_pattern('go.mod', '.git'),
  },
}

lspconfig.gotmpl.setup{}

Other Editors

The LSP binary works with any editor that supports the Language Server Protocol. Configure your editor to run go-template-lsp for template files.

Formatting

The formatter re-indents Go template files based on HTML tag and template action nesting. It respects the standard LSP tabSize and insertSpaces settings.

Attribute Wrapping

When an HTML opening tag exceeds a configured line width, the formatter can wrap its attributes across multiple lines. Configure via initializationOptions:

{
  "initializationOptions": {
    "printWidth": 120,
    "attrWrapMode": "overflow"
  }
}
Setting Type Default Description
printWidth int 0 (disabled) Maximum line width before wrapping attributes. Set to 0 to disable.
attrWrapMode string "overflow" "overflow": only wrap attributes that push past printWidth. "all": wrap every attribute onto its own line.

overflow mode keeps attributes on the first line as long as they fit, then wraps the rest:

<button type="button"
   class="map-zoom-btn"
   title="Expand">

all mode puts every attribute on its own line:

<button
   type="button"
   class="map-zoom-btn"
   title="Expand">

Continuation lines are indented one level deeper than the tag. Multi-line tags already in the source are joined back into a single line before re-wrapping.

CLI Linting (check)

The check subcommand runs the same diagnostic pipeline as the LSP server and prints errors to stdout. This is useful for CI/CD pipelines, pre-commit hooks, and AI agents.

# Check the current directory
go-template-lsp check

# Check a specific directory
go-template-lsp check ./views

# JSON output
go-template-lsp check -json ./views

# Declare extra template function names (comma-separated)
go-template-lsp check -funcs asset,renderPage ./views

Custom template functions are auto-discovered by scanning Go source files for template.FuncMap definitions. The scan starts from the Go module root (go.mod directory), so FuncMap definitions anywhere in the module are found even when checking a subdirectory. The -funcs flag lets you declare additional function names that can't be auto-discovered (e.g. from external packages or generated code).

Text output (default):

views/user.html:8:22: missing matching '{{ end }}' statement

JSON output (-json):

[
  {
    "file": "views/user.html",
    "line": 8,
    "column": 22,
    "endLine": 8,
    "endColumn": 24,
    "message": "missing matching '{{ end }}' statement"
  }
]

Exit codes:

Code Meaning
0 No errors found
1 Template errors found
2 Tool failure (e.g. directory not found)

Supported File Extensions

Extension Type
.gotmpl, .go.tmpl, .gtpl, .tpl, .tmpl Go text templates
.gohtml, .go.html Go HTML templates
.html HTML (with template detection)

Credits

Template Parser and Analyzer

yayolande/gota (MIT License)

The template parsing and semantic analysis code in internal/template is derived from gota by yayolande.

LSP Implementation

yayolande/go-template-lsp (MIT License)

The LSP server architecture is based on this project by yayolande.

License

MIT License - see LICENSE for details.

About

Language Server Protocol for Go templates

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages