diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 03298ec..8186998 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -18,14 +18,24 @@ jobs: with: go-version: '1.22' + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Cross-compile shell: bash run: | - tag="${GITHUB_REF#refs/tags/}" mkdir -p dist CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o "dist/judge-linux-amd64" ./cmd/cli CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o "dist/judge-windows-amd64.exe" ./cmd/cli - ls -la dist/ + + - name: Build VS Code extension + shell: bash + run: | + npm install -g @vscode/vsce + cd editor/vscode-jdg + vsce package -o "../../dist/jdg-language-${{ github.ref_name }}.vsix" - name: Create release uses: https://gitea.com/actions/gitea-release-action@main @@ -33,5 +43,6 @@ jobs: files: |- dist/judge-linux-amd64 dist/judge-windows-amd64.exe + dist/jdg-language-${{ github.ref_name }}.vsix api_key: ${{ secrets.RELEASE_TOKEN }} title: ${{ github.ref_name }} diff --git a/dsl/ast.go b/dsl/ast.go index a877c13..1d1ccbd 100644 --- a/dsl/ast.go +++ b/dsl/ast.go @@ -9,6 +9,7 @@ type File struct { BuildDarwin string Timeout time.Duration Binary string // executable name produced by build (default: solution) + Sources string // glob pattern for source files, expanded as $SOURCES in build NormalizeCRLF bool // strip \r before matching stdout/stderr/outFiles TrimTrailingWS bool // trim trailing whitespace on each line before matching diff --git a/dsl/parser.go b/dsl/parser.go index 3e717ae..d379296 100644 --- a/dsl/parser.go +++ b/dsl/parser.go @@ -128,6 +128,17 @@ func (p *Parser) parseFile() (*File, error) { } f.Binary = s.Value + case "sources": + p.advance() + if _, err := p.expect(TOKEN_ASSIGN); err != nil { + return nil, err + } + s, err := p.expect(TOKEN_STRING) + if err != nil { + return nil, err + } + f.Sources = s.Value + case "normalize_crlf": p.advance() if _, err := p.expect(TOKEN_ASSIGN); err != nil { diff --git a/editor/.DS_Store b/editor/.DS_Store deleted file mode 100644 index 05bb5d7..0000000 Binary files a/editor/.DS_Store and /dev/null differ diff --git a/editor/vscode-jdg/syntaxes/jdg.tmLanguage.json b/editor/vscode-jdg/syntaxes/jdg.tmLanguage.json index 021df6c..b4fff90 100644 --- a/editor/vscode-jdg/syntaxes/jdg.tmLanguage.json +++ b/editor/vscode-jdg/syntaxes/jdg.tmLanguage.json @@ -53,7 +53,7 @@ }, "top-keywords": { "name": "keyword.control.jdg", - "match": "\\b(?:build|build_linux|build_windows|build_darwin|binary|timeout|normalize_crlf|trim_trailing_ws|group|test|pattern|env|file|outFile)\\b" + "match": "\\b(?:build|build_linux|build_windows|build_darwin|binary|sources|timeout|normalize_crlf|trim_trailing_ws|group|test|pattern|env|file|outFile)\\b" }, "block-keywords": { "name": "variable.parameter.jdg", diff --git a/runner/runner.go b/runner/runner.go index e1a3c41..6f49aea 100644 --- a/runner/runner.go +++ b/runner/runner.go @@ -119,9 +119,48 @@ func (r *Runner) buildCommand() string { return "go build -o solution ." } +func (r *Runner) findSources() (string, error) { + if r.file.Sources == "" { + return "", nil + } + var files []string + err := filepath.Walk(r.cfg.WorkDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + if info.Name() == ".git" || info.Name() == ".gitea" { + return filepath.SkipDir + } + return nil + } + matched, _ := filepath.Match(r.file.Sources, info.Name()) + if matched { + rel, _ := filepath.Rel(r.cfg.WorkDir, path) + files = append(files, filepath.ToSlash(rel)) + } + return nil + }) + if err != nil { + return "", fmt.Errorf("source discovery: %w", err) + } + if len(files) == 0 { + return "", fmt.Errorf("no files matching %q found", r.file.Sources) + } + return strings.Join(files, " "), nil +} + func (r *Runner) build() (string, error) { buildCmd := r.buildCommand() + sources, err := r.findSources() + if err != nil { + return "", err + } + if sources != "" { + buildCmd = strings.ReplaceAll(buildCmd, "$SOURCES", sources) + } + ctx := context.Background() if r.file.Timeout > 0 { var cancel context.CancelFunc