feat(lsp): add Language Server Protocol server (glint lsp)
New internal/lsp package implements a minimal JSON-RPC 2.0 LSP server over stdin/stdout with Content-Length framing. Supported lifecycle: initialize → initialized → shutdown → exit. Document sync: Full (sends complete text on every change). Handles textDocument/didOpen, didChange, didSave, didClose; publishes textDocument/publishDiagnostics after every change. Rule IDs surface as the diagnostic `code` field with `"glint"` as source. Parse errors produce an Error diagnostic at the top of the document. Include resolution is best-effort (GITLAB_TOKEN env var; ~/.cache/glint default cache). CLI: glint lsp [--token] [--gitlab-url] [--cache-dir] [--offline]. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"git.k3nny.fr/glint/internal/fetcher"
|
||||
"git.k3nny.fr/glint/internal/lsp"
|
||||
)
|
||||
|
||||
func cmdLSP(args []string) {
|
||||
fs := flag.NewFlagSet("glint lsp", flag.ExitOnError)
|
||||
token := fs.String("token", "", "GitLab personal access token (overrides GITLAB_TOKEN)")
|
||||
gitlabURL := fs.String("gitlab-url", "", "GitLab instance URL (overrides CI_SERVER_URL / GITLAB_URL)")
|
||||
cacheDir := fs.String("cache-dir", "", "directory for caching fetched remote includes")
|
||||
offline := fs.Bool("offline", false, "skip all network calls; serve only from --cache-dir")
|
||||
fs.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "glint %s\n\n", version)
|
||||
fmt.Fprint(os.Stderr, `Start a Language Server Protocol server for .gitlab-ci.yml files.
|
||||
|
||||
Reads JSON-RPC 2.0 messages from stdin and writes responses to stdout using
|
||||
the standard Content-Length framing. Connect with any LSP client (VS Code,
|
||||
Neovim, Emacs, etc.).
|
||||
|
||||
Usage: glint lsp [OPTIONS]
|
||||
|
||||
Options:
|
||||
--token <TOKEN>
|
||||
GitLab personal access token used for resolving project: and
|
||||
component: includes. Defaults to GITLAB_TOKEN env var.
|
||||
|
||||
--gitlab-url <URL>
|
||||
GitLab instance URL for resolving remote includes.
|
||||
[env: CI_SERVER_URL | GITLAB_URL] [default: https://gitlab.com]
|
||||
|
||||
--cache-dir <DIR>
|
||||
Cache directory for fetched remote includes. Defaults to
|
||||
~/.cache/glint so subsequent opens are served from cache.
|
||||
|
||||
--offline
|
||||
Do not make any network calls; resolve only local includes.
|
||||
Implies --cache-dir default (~/.cache/glint) when not set.
|
||||
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
Examples:
|
||||
glint lsp
|
||||
glint lsp --token glpat-xxxx --cache-dir ~/.cache/glint
|
||||
glint lsp --offline
|
||||
`)
|
||||
}
|
||||
_ = fs.Parse(args)
|
||||
|
||||
resolvedCacheDir := *cacheDir
|
||||
if resolvedCacheDir == "" {
|
||||
resolvedCacheDir = defaultCacheDir()
|
||||
}
|
||||
if *offline && resolvedCacheDir == "" {
|
||||
resolvedCacheDir = defaultCacheDir()
|
||||
}
|
||||
|
||||
cfg := fetcher.AutoConfig().WithOverrides(*gitlabURL, *token, resolvedCacheDir, *offline)
|
||||
|
||||
srv := lsp.New(os.Stdin, os.Stdout, cfg, version)
|
||||
if err := srv.Run(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "glint lsp: %v\n", err)
|
||||
exit(2)
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@ Commands:
|
||||
check Lint a pipeline file — exits 0 (clean) or 1 (errors found)
|
||||
graph Visualise the pipeline as a job tree or Mermaid graph
|
||||
explain Show description and fix for a lint rule (e.g. glint explain GL007)
|
||||
lsp Start a Language Server Protocol server (stdin/stdout)
|
||||
|
||||
Options:
|
||||
-h, --help Print help
|
||||
@@ -90,6 +91,8 @@ func main() {
|
||||
cmdGraph(os.Args[2:])
|
||||
case "explain":
|
||||
cmdExplain(os.Args[2:])
|
||||
case "lsp":
|
||||
cmdLSP(os.Args[2:])
|
||||
case "-h", "--help", "help":
|
||||
fmt.Fprintf(os.Stderr, "glint %s\n\n", version)
|
||||
fmt.Fprint(os.Stderr, globalUsage)
|
||||
|
||||
Reference in New Issue
Block a user