No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Maciej Lebiest 6f2fb15f33 new cases
2026-08-24 14:02:00 +02:00
src new cases 2026-08-24 14:02:00 +02:00
tests new cases 2026-08-24 14:02:00 +02:00
.gitignore initial commit 2026-08-16 13:32:25 +02:00
AGENTS.md new cases 2026-08-24 14:02:00 +02:00
Cargo.lock add minijinja for better jinja check, fixes, cleaning 2026-08-18 11:21:41 +02:00
Cargo.toml save 2026-08-23 21:40:52 +02:00
README.md new cases 2026-08-24 14:02:00 +02:00

slsls

[WARN] This is AI-slopped experimental project

A minimal Language Server Protocol (LSP) server for SaltStack .sls files.

Three validation passes run on each open/change:

  • Jinja block-closure checking — flags unclosed opening blocks ({% if %} without {% endif %}), closing blocks without a matching opener ({% endif %} alone), and mismatched closers ({% if %} closed by {% endfor %}). Tracks nesting, handles Jinja whitespace-control delimiters ({%- ... -%}, {%+ ... +%}), recognizes keywords without surrounding whitespace ({% if(x) %}), ignores block-looking content inside {% raw %} blocks, and never treats tag delimiters found inside Jinja string literals as real tags.
  • Jinja expression checking (minijinja) — when the block structure is sound, the whole document is compiled as a Jinja template; compile failures are reported as jinja-invalid-expression. Salt-only tags such as {% import_yaml %} and {% load_yaml as x %}...{% endload %} blocks and do statements with inline conditionals are understood and not flagged. Jinja2 implicit tuples ({% for x in 'a','b' %}, {% if v in 'a','b' %}) are accepted as well.
  • YAML syntax checking — Jinja tags are masked out before parsing so the YAML parser never sees them; syntax errors are reported with their locations.

No other LSP language features are implemented.

Build

cargo build --release

The resulting executable is target/release/sls-lsp.

Neovim setup

Neovim 0.11+ with the built-in LSP client:

vim.filetype.add({
  extension = {
    sls = "sls",
  },
})

vim.lsp.config("sls_lsp", {
  cmd = { "sls-lsp" },
  filetypes = { "sls" },
  root_markers = { ".git" },
})

vim.lsp.enable("sls_lsp")

Verify with:

:set filetype?
:checkhealth vim.lsp
:lua =vim.lsp.get_clients({ bufnr = 0 })

Diagnostics

Code Description
jinja-unclosed-block Opening block without its closer.
jinja-unexpected-closing-block Closing block with no matching opener.
jinja-mismatched-closing-block Closing block does not match the top of the stack.
jinja-invalid-expression Jinja template compile error (minijinja).
yaml-syntax-error YAML parse error (Jinja tags are masked first).

All diagnostics share the source sls-jinja-blocks, use error severity, and report positions as zero-based line numbers and UTF-16 code unit columns.

When a Jinja tag is malformed (an unterminated {%, {{ or {#), only the Jinja error is reported; YAML checking is skipped for that revision because the masked view of the file would not be faithful.

Quick fixes are offered per Jinja closure issue and only for diagnostics overlapping the requested range: add a missing closer (inserted at the end of the document, keeping the opener's indentation; when deeper blocks are still open, their closers are appended first so nested fixes compose in one shot), remove an unexpected closer, or replace a mismatched closer. Expression errors offer no automated fix.

Supported messages

initialize, initialized, shutdown, exit, textDocument/didOpen, textDocument/didChange (full document sync), textDocument/didClose, textDocument/codeAction (quick fixes per Jinja issue).

Development

cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-features
cargo build --release