Editors & LSP

Wire pyne-lsp into VS Code, Neovim, Zed, Emacs, Helix, and other LSP clients for diagnostics, completion, hover, and formatting.

This page

Abstract

pyne-lsp (alias pynescript-lsp) is a stdio Language Server (pygls) over the same parse/lint/metadata stack as the desk tools. Editors do not reimplement Pine Script™ intelligence; they speak LSP. This guide covers install, client configs in clients/, and feature expectations. Server architecture is documented under LSP.

Conceptual model

Diagram

Rendering…

FeatureRole
DiagnosticsLint rules + parse errors as squiggles
CompletionBuiltins (ta.*, strategy.*, …) + snippets
HoverSignature / docs from metadata
Definition / referencesSymbol index in document
Document symbolsOutline / breadcrumb
FormattingFull document + range via unparser path
Foldingif / for / while / switch / once, types, //#region
Code actionConvert-to-v6; W001 QuickFix inserts //@version=6

Builtin metadata is generated (scripts/generate_builtin_metadata.py); encrypted blobs may appear in release builds.

Interface surface

Install server

bash
pip install "hoox-pyne[lsp]"
# monorepo:
pip install -e ".[lsp]"
# or: make install

command -v pyne-lsp          # preferred
command -v pynescript-lsp    # alias
python -m pynescript.langserver  # equivalent entry

The process speaks LSP over stdio by default (PynescriptLanguageServer.start_io()). Do not expect a useful interactive TTY UI.

VS Code / Cursor / Antigravity

  1. Build or install the extension from hoox-sh/pyne-lsp-vsce:
bash
git clone https://github.com/hoox-sh/pyne-lsp-vsce.git
cd pyne-lsp-vsce
npm ci
npm run compile
# package: npm run package
  1. Open a .pyne (preferred for HOOX / PYNE stack sources), .pine, .pinev5, .pinev6, or .pinescript file — LSP activates when enabled. The VS Code extension also activates on workspaceContains:**/*.{pyne,pine,…}.

Marketplace / VSIX: extension id hoox-sh.pyne 0.5.5 (publisher hoox-sh, package name pyne; ships with hoox-pyne 0.6.31). VS Marketplace. Site download: hoox.sh/pyne-vscode.vsix (unversioned alias). Local package: git clone https://github.com/hoox-sh/pyne-lsp-vsce.git && cd pyne-lsp-vsce && npm ci && npm run package then code --install-extension pyne-vscode-0.5.5.vsix. The VSIX is self-contained; you still need pip install "hoox-pyne[lsp]" (or a pyne-lsp binary) on the machine.

Settings (from the extension's package.json):

KeyDefaultNotes
pynescript.lsp.enabledtrueMaster switch
pynescript.lsp.commandautoauto → pyne-lsp → pynescript-lsp → python3 -m pynescript.langserver; or an absolute path / docker
pynescript.lsp.pythonpython3Interpreter when command is auto and no binary is on PATH
pynescript.lsp.args[]Extra server args
pynescript.formatting.enabledtrue
pynescript.diagnostics.enabledtrue
pynescript.completion.snippetstrue
pynescript.syntaxHighlightingvoidPine TextMate + semantic token palette (none / void / signal / volt); independent of the workbench color theme
pynescript.inlayHints.parameterstrueParameter-name hints only (type inlays removed in 0.6.29)

Default formatter id: hoox-sh.pyne.

Neovim (nvim-lspconfig)

lua
require("lspconfig").pynescript.setup({})

Manual config from clients/neovim.lua:

lua
return {
  cmd = { "pyne-lsp" },  -- alias: pynescript-lsp
  filetypes = { "pinescript" },
  root_dir = function(fname)
    return vim.fs.root(fname, { ".git", "*.pyne", "*.pine", "*.pinev5", "*.pinev6", "pyproject.toml" })
      or vim.fn.getcwd()
  end,
  settings = {
    pinescript = {
      formatting = { enabled = true },
      diagnostics = { enabled = true },
      completion = { snippets = true },
    },
  },
}

Suggested maps: gd definition, gr references, K hover, format via vim.lsp.buf.format.

Ensure filetype detection maps *.pyne / *.pine → pinescript if your distro does not ship it.

Zed

Merge clients/zed.json or:

json
{
  "languages": {
    "Pine Script™": {
      "language_servers": ["pynescript"]
    }
  },
  "language_servers": {
    "pynescript": {
      "command": "pyne-lsp",
      "arguments": ["--stdio"]
    }
  }
}

Emacs (lsp-mode)

elisp
(use-package lsp-mode
  :hook ((pinescript-mode . lsp))
  :config
  (lsp-register-client
   (make-lsp-client
    :new-connection (lsp-stdio-connection '("pyne-lsp" "--stdio"))
    :major-modes '(pinescript-mode)
    :server-id 'pynescript)))

Or (load-file "clients/emacs.el") from a checkout.

Helix

~/.config/helix/languages.toml:

toml
[[language]]
name = "pinescript"
scope = "source.pinescript"
file-types = ["pyne", "pine", "pinev5", "pinev6"]
roots = ["pyproject.toml"]
command = "pyne-lsp"
args = ["--stdio"]

Sublime Text (LSP package)

json
{
  "clients": {
    "pynescript": {
      "command": ["pyne-lsp", "--stdio"],
      "selector": "source.pinescript",
      "initializationOptions": {}
    }
  }
}

Generic

Any LSP client:

text
Command: pyne-lsp          # alias: pynescript-lsp
Args:    (none or --stdio depending on client)
Transport: stdio

Internals (repo paths)

PathRole
src/pynescript/langserver/__main__.pyCLI entry main()
src/pynescript/langserver/server.pyPynescriptLanguageServer
src/pynescript/langserver/features/diagnostics, completion, hover, …
clients/README.mdCanonical client matrix
clients/neovim.lua, zed.json, emacs.elDrop-in snippets
hoox-sh/pyne-lsp-vsceVS Code extension (separate repo)
scripts/generate_builtin_metadata.pyCompletion/hover corpus

Invariants & edge cases

  • Python 3.10+ required on the machine running the server.
  • Server must be on PATH or configured with absolute command.
  • One server per workspace is typical; large monorepos with many .pine files still parse on demand.
  • Formatting uses the unparser pipeline — expect normalization, not clang-format style knobs.
  • Diagnostics reuse linter codes (E001, W001, …); severity maps to LSP DiagnosticSeverity.
  • Nuitka binary (dist/lsp/pynescript-lsp) may replace the Python entry in packaged distributions — point the editor at that binary if you ship it.

Worked examples

Verify server starts (stdio smoke)

bash
# Editors start this; manual smoke is limited.
python -c "from pynescript.langserver.server import PynescriptLanguageServer; print(PynescriptLanguageServer)"

Neovim minimal init.lua fragment

lua
vim.api.nvim_create_autocmd("FileType", {
  pattern = "pinescript",
  callback = function()
    vim.lsp.start({
      name = "pynescript",
      cmd = { "pyne-lsp" },
      root_dir = vim.fn.getcwd(),
    })
  end,
})

Force a specific venv binary in VS Code

json
{
  "pynescript.lsp.command": "/home/you/project/.venv/bin/pyne-lsp"
}

Failure modes

SymptomFix
Client: executable not foundInstall [lsp]; fix PATH / command setting
No module named pyglsReinstall extra in the same env as the command
No diagnosticsEnable diagnostics; confirm filetype; check server logs
Stale completionsRegenerate metadata in dev builds; restart server
Format does nothingEnable formatting; ensure document is valid enough to parse
High CPU on huge filesSplit libraries; wait for parse; check for pathological nesting

See also