package main import ( "bytes" "os" "path/filepath" "github.com/marte-community/marte-dev-tools/internal/builder" "github.com/marte-community/marte-dev-tools/internal/formatter" "github.com/marte-community/marte-dev-tools/internal/index" "github.com/marte-community/marte-dev-tools/internal/logger" "github.com/marte-community/marte-dev-tools/internal/lsp" "github.com/marte-community/marte-dev-tools/internal/parser" "github.com/marte-community/marte-dev-tools/internal/validator" ) func main() { if len(os.Args) < 2 { logger.Println("Usage: mdt [arguments]") logger.Println("Commands: lsp, build, check, fmt, init") logger.Println(" build [-o output_file] ") logger.Println(" check ") logger.Println(" fmt ") logger.Println(" init ") os.Exit(1) } command := os.Args[1] switch command { case "lsp": runLSP() case "build": runBuild(os.Args[2:]) case "check": runCheck(os.Args[2:]) case "fmt": runFmt(os.Args[2:]) case "init": runInit(os.Args[2:]) default: logger.Printf("Unknown command: %s\n", command) os.Exit(1) } } func runLSP() { lsp.RunServer() } func runBuild(args []string) { if len(args) < 1 { logger.Println("Usage: mdt build [-o output_file] ") os.Exit(1) } var outputFilePath string var inputFiles []string for i := 0; i < len(args); i++ { if args[i] == "-o" { if i+1 < len(args) { outputFilePath = args[i+1] i++ } else { logger.Println("Error: -o requires a file path") os.Exit(1) } } else { inputFiles = append(inputFiles, args[i]) } } if len(inputFiles) < 1 { logger.Println("Usage: mdt build [-o output_file] ") os.Exit(1) } output := os.Stdout if outputFilePath != "" { f, err := os.Create(outputFilePath) if err != nil { logger.Printf("Error creating output file %s: %v\n", outputFilePath, err) os.Exit(1) } defer f.Close() output = f } b := builder.NewBuilder(inputFiles) err := b.Build(output) if err != nil { logger.Printf("Build failed: %v\n", err) os.Exit(1) } } func runCheck(args []string) { if len(args) < 1 { logger.Println("Usage: mdt check ") os.Exit(1) } tree := index.NewProjectTree() for _, file := range args { content, err := os.ReadFile(file) if err != nil { logger.Printf("Error reading %s: %v\n", file, err) continue } p := parser.NewParser(string(content)) config, err := p.Parse() if err != nil { logger.Printf("%s: Grammar error: %v\n", file, err) continue } tree.AddFile(file, config) } v := validator.NewValidator(tree, ".") v.ValidateProject() for _, diag := range v.Diagnostics { level := "ERROR" if diag.Level == validator.LevelWarning { level = "WARNING" } logger.Printf("%s:%d:%d: %s: %s\n", diag.File, diag.Position.Line, diag.Position.Column, level, diag.Message) } if len(v.Diagnostics) > 0 { logger.Printf("\nFound %d issues.\n", len(v.Diagnostics)) } else { logger.Println("No issues found.") } } func runFmt(args []string) { if len(args) < 1 { logger.Println("Usage: mdt fmt ") os.Exit(1) } for _, file := range args { content, err := os.ReadFile(file) if err != nil { logger.Printf("Error reading %s: %v\n", file, err) continue } p := parser.NewParser(string(content)) config, err := p.Parse() if err != nil { logger.Printf("Error parsing %s: %v\n", file, err) continue } var buf bytes.Buffer formatter.Format(config, &buf) err = os.WriteFile(file, buf.Bytes(), 0644) if err != nil { logger.Printf("Error writing %s: %v\n", file, err) continue } logger.Printf("Formatted %s\n", file) } } func runInit(args []string) { if len(args) < 1 { logger.Println("Usage: mdt init ") os.Exit(1) } projectName := args[0] if err := os.MkdirAll(filepath.Join(projectName, "src"), 0755); err != nil { logger.Fatalf("Error creating project directories: %v", err) } files := map[string]string{ "Makefile": "MDT=mdt\n\nall: check build\n\ncheck:\n\t$(MDT) check src/*.marte\n\nbuild:\n\t$(MDT) build -o app.marte src/*.marte\n\nfmt:\n\t$(MDT) fmt src/*.marte\n", ".marte_schema.cue": "package schema\n\n#Classes: {\n // Add your project-specific classes here\n}\n", "src/app.marte": "#package App\n\n+Main = {\n Class = RealTimeApplication\n +States = {\n Class = ReferenceContainer\n +Run = {\n Class = RealTimeState\n +MainThread = {\n Class = RealTimeThread\n Functions = {}\n }\n }\n }\n +Data = {\n Class = ReferenceContainer\n }\n}\n", "src/components.marte": "#package App.Data\n\n// Define your DataSources here\n", } for path, content := range files { fullPath := filepath.Join(projectName, path) if err := os.WriteFile(fullPath, []byte(content), 0644); err != nil { logger.Fatalf("Error creating file %s: %v", fullPath, err) } logger.Printf("Created %s\n", fullPath) } logger.Printf("Project '%s' initialized successfully.\n", projectName) }