Zed's [grammars.*] block requires a real Git SHA — "HEAD" does not
resolve. Lock to 3f209ef so a fresh `zed: install dev extension` can
clone the grammar.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zed-p8
A Zed extension for the PICO-8 fantasy
console. The goal is reasonable editor support for the entire .p8 cartridge
file format and for PICO-8's Lua dialect — even where PICO-8 deviates from
standard Lua 5.2 (compound assignments, ? print shorthand, single-line
if (cond) ..., !=, binary literals, peek operators, and so on).
Status — v0.1 scaffold
Working today:
- A small tree-sitter grammar (
p8_cart, in this repo's root) that parses the.p8cartridge container: the magic header line,versionline, and the named sections__lua__,__gfx__,__gff__,__label__,__map__,__sfx__,__music__. Unknown__name__markers are accepted as a fallbackunknown_section. - A Zed language definition
Pico-8 Cartridge(file suffix.p8) that uses this grammar for outline, section-marker highlighting, and an outline view. - An injection that hands the body of the
__lua__section to Zed's built-in Lua language for syntax highlighting.
Known limitations:
- PICO-8 Lua dialect is not fully parsed. The injected grammar is plain
Lua 5.2, which does not understand
?(print shorthand),+=and friends,!=,0b...literals, the\integer-divide operator, the@/%/$peek prefixes, or the single-lineif (cond) stmt/while (cond) stmtforms. Code that uses any of those will show parse-error highlighting in those regions only — surrounding code remains correctly highlighted. See Roadmap below. - No language server. No completion, hover docs, or diagnostics for PICO-8 builtins yet. See Roadmap.
- No
.p8.pngsupport. Only the plain-text.p8format is handled.
Repository layout
zed-p8/
extension.toml ← Zed extension manifest
grammar.js ← tree-sitter-p8-cart grammar source
src/ ← generated parser ( committed; regenerate after grammar.js edits )
package.json ← tree-sitter-cli devDependency
tree-sitter.json ← tree-sitter-cli config ( auto-managed )
languages/
pico-8-cart/ ← Pico-8 Cartridge language files
config.toml
highlights.scm
injections.scm
outline.scm
examples/
hello.p8 ← minimal test cart
references/ ← upstream PICO-8 manual + Zed docs links
The cart grammar lives at the repo root rather than as a separate sibling
repository. This keeps everything in one place during early development; if
the grammar grows or wants to be reused outside Zed it can be split out
later — the only file that needs to move with it is grammar.js plus the
generated src/, and the [grammars.p8_cart] URL in extension.toml would
need updating.
Local development
Prerequisites: Node.js (for tree-sitter-cli) and Zed. Rust is NOT required
unless/until we add a language-server harness.
Edit-and-reload loop
-
Edit
grammar.js. -
Regenerate the parser:
npx tree-sitter generate -
Sanity-check on a real cart:
npx tree-sitter parse examples/hello.p8 -
Commit. The
[grammars.p8_cart]block inextension.tomlreferences this repo byfile://URL and pins a commit SHA — Zed clones the grammar from that pinned revision, so changes only take effect after they're committed. -
Update
extension.toml'srevfield to the new SHA, then in Zed runzed: install dev extension(or click Install Dev Extension on the Extensions page) and select this directory. Reinstall after every commit that should be picked up.Logs:
zed: open log. Runzed --foregroundfor live stdout.
Editing language queries
Files under languages/pico-8-cart/ (highlights.scm, injections.scm,
outline.scm) are loaded directly by Zed — no regeneration needed. Reinstall
the dev extension to pick up changes.
Roadmap
v0.2 — PICO-8 Lua dialect grammar
Fork tree-sitter-grammars/tree-sitter-lua
into tree-sitter-pico8 and add the dialect extensions documented in the
PICO-8 manual:
- Compound-assignment operators:
+= -= *= /= \= %= ^= ..= &= |= ^^= <<= >>= >>>= <<>= >><= !=as alias for~=\(integer divide) and the rotate / logical-shift operators<<>>><>>>- Binary literals
0b...and hex fractional literals0x1.4p0style - Single-line
if (cond) stmtandwhile (cond) stmt( nothen/do/end) ?as a statement-level shorthand forprint- The peek-prefix unary operators
@addr%addr$addr
Then add a second language Pico-8 Lua here (separate from Zed's built-in
Lua) and switch injections.scm to inject pico-8-lua instead of lua.
v0.3 — Language server integration
Wire up japhib/pico8-ls (or whichever
PICO-8 LSP is most maintained at the time) for:
- Completion of PICO-8 builtins (
spr,circfill,btn,flr, …) - Signature help and hover docs sourced from the manual
- Cart-aware analysis ( the LSP already understands
.p8section markers and only analyzes the__lua__body ) - Per-cart diagnostics
This will require a Rust component ( the zed_extension_api crate ) to
download the language-server binary and define
language_server_command — see Zed's developing-extensions docs.
v0.4 — Polish
- LuaCATS / EmmyLua stub file enumerating PICO-8's ~110 globals, for users
who'd rather wire up
lua-language-serveragainst their#include-d.luafiles. - Highlight rules for hex sections (
__gfx__,__map__,__sfx__, etc.) so palette indices and note pitches show up distinctly. - Snippets for common idioms (
for x=0,127 do ... end, the_init/_update/_drawtriad).
References
- PICO-8 manual:
references/pico-8_manual.txt - Zed extension docs: see links in
references/zed-doc-links.md - Cart file-format spec ( community wiki, not in the official manual ): https://pico-8.fandom.com/wiki/P8FileFormat
License
0BSD — see LICENSE.