Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
232fbe2
version
ItsMeBrianD Sep 13, 2025
4055f2d
feat: noise + noise block autocomplete
ItsMeBrianD Sep 15, 2025
7047453
feat: proper snippet support
ItsMeBrianD Sep 15, 2025
2fecfa3
fix: err == nil NOT err != nil
ItsMeBrianD Sep 15, 2025
5e7b196
chore: interface splits, remove outdated tests, repomix configs
ItsMeBrianD Sep 17, 2025
acb9531
lsp checkpoint
ItsMeBrianD Sep 25, 2025
8976584
feat: Noise density function completions feel perfect
ItsMeBrianD Sep 25, 2025
bab2835
commit before switch
ItsMeBrianD Sep 26, 2025
668657d
chore: begin rewrite
ItsMeBrianD Sep 26, 2025
6c0332a
chore: commit before refactor
ItsMeBrianD Sep 26, 2025
4de4369
feat: noise parses and exports
ItsMeBrianD Sep 27, 2025
d84048a
feat: parse, export, and hover working
ItsMeBrianD Sep 30, 2025
9e900c2
feat: autocomplete is mostly wired up
ItsMeBrianD Oct 1, 2025
1ac188f
feat: surface rules should be working, missing vertical anchors
ItsMeBrianD Oct 2, 2025
acc6023
fixes
ItsMeBrianD Oct 2, 2025
e702f74
feat: prefiltering / autocomplete improvements
ItsMeBrianD Oct 2, 2025
4fbcd78
feat: VERY simple implementation of conditionals for surface rules
ItsMeBrianD Oct 3, 2025
c840952
chore: trivial implementation of conditions and lists
ItsMeBrianD Oct 3, 2025
4c75d7a
feat: enhance completions for ConditionSpec and ListSpec, add complet…
ItsMeBrianD Oct 6, 2025
67a0df1
chore: delete unused test
ItsMeBrianD Oct 6, 2025
e887a5d
checkpoint
ItsMeBrianD Oct 6, 2025
e226b83
fix: conditional serialization
ItsMeBrianD Oct 6, 2025
93e6f07
feat: surface rules is ready
ItsMeBrianD Oct 7, 2025
3ce1ab5
fix: list / conditional completions
ItsMeBrianD Oct 7, 2025
5c56460
feat: enhance density functions and surface rules
ItsMeBrianD Oct 8, 2025
9e81d1e
feat: refactor and enhance density functions, completions, and serial…
ItsMeBrianD Oct 9, 2025
b3fa2a0
feat: refactor parsing and serialization, add tag support, and improv…
ItsMeBrianD Oct 10, 2025
bab26eb
chore: delete syntax highlighting
ItsMeBrianD Oct 10, 2025
d205dc5
chore: missed a spot
ItsMeBrianD Oct 10, 2025
aba73d5
feat: wire up build command
ItsMeBrianD Oct 11, 2025
3bc8879
chore: remove copywrite notices
ItsMeBrianD Oct 11, 2025
5cb16b7
chore: coderabbit reviews
ItsMeBrianD Oct 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ gen
extensions/vscode-extension/node_modules
overworld.json
surface_rules_wiki.txt
repomix-output.xml
spec.md
mms_dist
9 changes: 9 additions & 0 deletions .helix/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[keys.normal]
C-space = "completion"
C-r = ":reload"
[keys.normal.l]
r = ":lsp-restart"
f = ":reload"
c = "completion"
l = [ ":vsplit", ":log-open" ]
o = [ ":sh echo \"\" > ~/.cache/helix/helix.log", ":reload" ]
4 changes: 2 additions & 2 deletions .helix/languages.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ name = "mms"
scope = "source.mms"
injection-regex = "mms"
file-types = ["mms"]
comment-tokens = "#"
language-servers = [ "mms-lsp" ]
comment-tokens = "//"
language-servers = [ "mms-lsp" ]
11 changes: 11 additions & 0 deletions .repomixignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Add patterns to ignore here, one per line
# Example:
# *.log
# tmp/
lang/grammar
result
vendor
.junie
.helix
.github
wasm/mms.js
92 changes: 92 additions & 0 deletions .windsurfrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Minecraft Metascript (MMS) — Workspace AI Rules

These are project-specific rules and context the AI must follow when working in this repository.

## Project Context
- Language: Go (go 1.23)
Comment thread
ItsMeBrianD marked this conversation as resolved.
- Module path: `github.com/minecraftmetascript/mms`
- Vendoring: `vendor/` is present; builds typically use vendored deps
- Parsing: ANTLR4 grammars in `grammar/*.g4` generate Go code into `lang/grammar/`
- CLI: Cobra-based entrypoint
- WASM: Browser-targeted build via [main_wasm.go](cci:7://file:///Users/brian/code/minecraftmetascript/mms/main_wasm.go:0:0-0:0) and `wasm/`
- Nix: Optional flake provides reproducible builds and ANTLR generation

## Repository Layout (high-signal paths)
- `lang/`: Core API (Project, File, traversal, constructs, generated grammar package)
- `lang/grammar/`: GENERATED by ANTLR. Do not edit manually.
- `lang/constructs/...`: Construct registry and implementations (e.g., worldgen/surface_rules)
- `lang/traversal/...`: Parser traversal, construct registry, scopes
- `grammar/`: Handwritten ANTLR grammars
- `cmd/`: Cobra root command ([mms](cci:7://file:///Users/brian/code/minecraftmetascript/mms/test.mms:0:0-0:0))
- `wasm/`: JS glue (`mms.js`), package.json, and wasm artifacts
- `examples/`: MMS examples (e.g., surface rules) for manual parsing checks

## Absolute Rules (Do/Don’t)
- DO keep all imports at the top of files; never insert imports mid-file.
- DO run `gofmt`/`goimports` and `go vet` before committing or proposing changes.
- DO regenerate grammar output rather than editing anything under `lang/grammar/`.
- DO keep vendoring consistent. After editing [go.mod](cci:7://file:///Users/brian/code/minecraftmetascript/mms/go.mod:0:0-0:0)/[go.sum](cci:7://file:///Users/brian/code/minecraftmetascript/mms/go.sum:0:0-0:0): `go mod tidy` then `go mod vendor`.
- DO cite files/paths with backticks like `path/to/file.go` in explanations and PR notes.
- DON’T modify generated files under `lang/grammar/` directly.
- DON’T break build tags:
- [main.go](cci:7://file:///Users/brian/code/minecraftmetascript/mms/main.go:0:0-0:0): `//go:build !js && !wasm`
- [main_wasm.go](cci:7://file:///Users/brian/code/minecraftmetascript/mms/main_wasm.go:0:0-0:0): `//go:build js && wasm`

## Builds & Tasks (Preferred Flows)
- Nix (recommended):
- Native CLI: `nix build` → produces `./result/bin/mms` (runs ANTLR generation first)
- WASM: `nix build ".#wasm"` → produces `./result/js/` with `dist/main.wasm` and assets
- Dev shell: `nix develop` (provides `antlr-build`)
- Regenerate grammar (Nix): `antlr-build`
- Non-Nix ANTLR regeneration (if `antlr4` is in PATH):
- Lexer: `antlr4 -Dlanguage=Go grammar/Main_Lexer.g4 -o lang -package grammar`
- Parser: `antlr4 -Dlanguage=Go grammar/Main_Parser.g4 -lib lang/grammar -o lang -package grammar`
- Vendoring:
- After dependency changes: `go mod tidy && go mod vendor`

## WASM Notes
- [main_wasm.go](cci:7://file:///Users/brian/code/minecraftmetascript/mms/main_wasm.go:0:0-0:0) exports (js/wasm build tags):
- `updateFile(filename: string, content: string, cb: (serializedProject: string) => void)`
- `getFileDiag(filename: string, cb: (json: string) => void)`
- `wasm/package.json` exposes `./mms.js` and `./dist/main.wasm` for NPM packaging.

## Testing Guidance
- Important API change: `Project.Diagnostics` is a METHOD now, not a field.
- Replace: `len(p.Diagnostics)` → `len(p.Diagnostics())`
- Replace: `for d := range p.Diagnostics { ... }` → range over `p.Diagnostics()`
- Running tests:
- Full (may fail due to legacy `test/` pkg): `go test ./...`
- Preferred during migration: `go test ./lang`
- Specific test: `go test ./lang -run TestName -v`
- Pattern for new tests:
- Create a `Project`, add a `File`, call `Parse()`
- Assert on `File.Diagnostics`, `Project.Diagnostics()`
- For exports, use `Project.BuildFsLike(root)`

## Construct & Export Model
- New constructs register via `traversal.ConstructRegistry.Register(...)`
- `Project.BuildFsLike(root)` walks `GlobalScope` and calls `ExportSymbol` on constructs to build a directory-like export structure (used by WASM packaging)

## Coding Style & Quality
- Follow idiomatic Go. Keep functions cohesive and small.
- Keep generated code in `lang/grammar/` untouched; regenerate via ANTLR on grammar changes.
- Prefer package-local tests near code under test.
- Keep explanations concise and always reference changed files and symbols with backticks.

## Quick Commands Reference
- Native build: `nix build`
- WASM build: `nix build ".#wasm"`
- Dev shell (Nix): `nix develop`
- Regenerate grammar (Nix): `antlr-build`
- Regenerate grammar (manual):
- `antlr4 -Dlanguage=Go grammar/Main_Lexer.g4 -o lang -package grammar`
- `antlr4 -Dlanguage=Go grammar/Main_Parser.g4 -lib lang/grammar -o lang -package grammar`
- Core package tests: `go test ./lang -v`

## AI Execution Preferences
- When asked to modify code:
- Respect vendoring and ANTLR regeneration steps.
- Never place imports mid-file—add at the top and adjust separately if needed.
- Avoid large monolithic diffs; break up edits logically.
- When suggesting commands, prefer Nix flows where available.
- If a change would touch `lang/grammar`, instruct to regenerate via ANTLR instead of manual edits.
80 changes: 69 additions & 11 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import (
"io/fs"
"log"
"os"
"path"
"strings"

"github.com/minecraftmetascript/mms/lang"

"github.com/minecraftmetascript/mms/lib"
_project "github.com/minecraftmetascript/mms/project"
"github.com/spf13/cobra"
)

Expand All @@ -19,6 +21,7 @@ var buildCmd = &cobra.Command{
Long: ``,
ValidArgs: []cobra.Completion{"Input", "Output"},
Run: func(cmd *cobra.Command, args []string) {
log.SetFlags(log.LstdFlags | log.Lshortfile)
if len(args) < 1 {
log.Println("Please provide an input file or directory")
return
Expand All @@ -39,10 +42,9 @@ var buildCmd = &cobra.Command{
log.Println(
fmt.Sprintf("Building your project from %s to %s", inFile, outFile),
)

}

project := lang.NewProject()
project := _project.NewProject()

stat, err := fs.Stat(os.DirFS("."), inFile)

Expand All @@ -57,29 +59,85 @@ var buildCmd = &cobra.Command{
if content, err := os.ReadFile(inFile); err != nil {
log.Println("Error reading project:", err)
} else {
f := project.AddFile(inFile, string(content))
err = f.Parse()
_, err := project.AddFile(inFile, string(content))

if err != nil {
log.Println("Error parsing project:", err)
}
}
}
r, err := json.MarshalIndent(project.BuildFsLike(outFile), "", " ")
fsLike := project.BuildFsLike(outFile)
if err != nil {
log.Println("Error exporting project:", err)
return
}

_, err = fs.Stat(os.DirFS("."), outFile)
if err != nil {
if strings.HasSuffix(err.Error(), "no such file or directory") {
err = os.MkdirAll(outFile, 0755)
if err != nil {
log.Println("Error creating output directory:", err)
return
}
} else {
log.Println("Error building project", err)
}
return
}
Comment thread
ItsMeBrianD marked this conversation as resolved.

flushProject(fsLike, outFile)

if debugMode {
r, err := json.MarshalIndent(project.Symbols(), "", " ")
log.Println(
string(r),
err,
)
} else {
// induce serialization for logging
_, e := json.MarshalIndent(project.Symbols(), "", " ")
if e != nil {
log.Println("Error serializing project:", e)
}
}
},
}

if len(project.Diagnostics()) > 0 {
for _, diag := range project.Diagnostics() {
log.Println(diag)
func flushProject(root *lib.FileTreeLike, rootPath string) {
log.Println(root.Name)
for _, file := range root.Children {
targetPath := path.Join(rootPath, file.Name)
if file.IsDir {
err := mkdirIfNotExists(targetPath)
if err != nil {
log.Println("Error creating directory:", err)
}
flushProject(file, targetPath)
} else {
err := os.WriteFile(targetPath, []byte(file.Content), 0644)
if err != nil {
log.Println("Error writing file:", err)
}

}

},
}
}

func mkdirIfNotExists(dirPath string) error {
_, err := fs.Stat(os.DirFS("."), dirPath)
if err != nil {
if os.IsNotExist(err) {
err = os.MkdirAll(dirPath, 0755)
if err != nil {
return err
}
} else {
return err
}
}
return nil
}

func init() {
Expand Down
79 changes: 35 additions & 44 deletions cmd/lint.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
/*
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
"io/fs"
"log"
"os"
"strings"

"github.com/minecraftmetascript/mms/lang"
"github.com/spf13/cobra"
)

Expand All @@ -20,41 +11,41 @@ var lintCmd = &cobra.Command{
Long: ``,
ValidArgs: []cobra.Completion{"Input"},
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
log.Println("Please provide an input file or directory")
return
}
inFile := args[0]
if strings.HasSuffix(inFile, "/") {
inFile = strings.TrimSuffix(inFile, "/")
}

project := lang.NewProject()

stat, err := fs.Stat(os.DirFS("."), inFile)

if err != nil {
log.Println("Error building project.", err)
return
}
if stat.IsDir() {
log.Println("Project is a directory")
} else {
if content, err := os.ReadFile(inFile); err != nil {
log.Println("Error building project:")
} else {
f := project.AddFile(inFile, string(content))
f.Parse()
}
}

if len(project.Diagnostics()) > 0 {
for _, diag := range project.Diagnostics() {
log.Println(diag)
}
} else {
log.Println("Project has no errors or warnings")
}
//if len(args) < 1 {
// log.Println("Please provide an input file or directory")
// return
//}
//inFile := args[0]
//if strings.HasSuffix(inFile, "/") {
// inFile = strings.TrimSuffix(inFile, "/")
//}
//
//project := lang.NewProject()
//
//stat, err := fs.Stat(os.DirFS("."), inFile)
//
//if err != nil {
// log.Println("Error building project.", err)
// return
//}
//if stat.IsDir() {
// log.Println("Project is a directory")
//} else {
// if content, err := os.ReadFile(inFile); err != nil {
// log.Println("Error building project:")
// } else {
// f := project.AddFile(inFile, string(content))
// f.Parse()
// }
//}
//
//if len(project.Diagnostics()) > 0 {
// for _, diag := range project.Diagnostics() {
// log.Println(diag)
// }
//} else {
// log.Println("Project has no errors or warnings")
//}

},
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/lsp.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package cmd

import (
"fmt"
"log"

"github.com/minecraftmetascript/mms/lsp"

"github.com/spf13/cobra"
)

Expand All @@ -12,10 +13,9 @@ var lspCmd = &cobra.Command{
Use: "lsp",

Run: func(cmd *cobra.Command, args []string) {
if lsp.Start() != nil {
panic("Failed to start LSP server")
} else {
fmt.Println("LSP Started")

if err := lsp.Start(); err != nil {
log.Fatalf("Failed to start LSP server: %v\n", err)
}
},
}
Expand Down
Loading