1
0

refactor build

This commit is contained in:
Arpad Ryszka 2026-01-16 01:03:43 +01:00
parent b4086951ee
commit dd6cdb1aac
10 changed files with 134 additions and 161 deletions

2
.gitignore vendored
View File

@ -1,6 +1,4 @@
*.test
*.out
.coverprofile
.coverprofile-cmd
codecov
.build

184
Makefile
View File

@ -1,35 +1,24 @@
sources = $(shell find . -name '*.go' | grep -v cmd/treerack/docreflect.gen.go)
sources = $(shell find . -name '*.go' \
| grep -v cmd/treerack/docreflect.gen.go \
| grep -v head.go \
| grep -v .build/head.go \
| grep -v headexported.go \
| grep -v .build/headexported.go \
| grep -v internal/self/self.go \
| grep -v .build/self.go)
parsers = $(shell find . -name '*.treerack')
release_date = $(shell git show -s --format=%cs HEAD)
version = $(date)-$(shell git rev-parse --short HEAD)
.PHONY: cpu.out
version = $(release_date)-$(shell git rev-parse --short HEAD)
PREFIX ?= /usr/local
prefix ?= $(PREFIX)
default: build
deps:
go get golang.org/x/tools/cmd/goimports
go get -t ./...
.build:
mkdir -p .build
imports: $(sources)
@echo imports
@goimports -w $(sources)
cmd/treerack/docreflect.gen.go: $(sources)
go run scripts/docreflect.go > .build/docreflect.gen.go && \
mv .build/docreflect.gen.go cmd/treerack || \
rm .build/docreflect.gen.go
build: $(sources) cmd/treerack/readme.md cmd/treerack/docreflect.gen.go .build/treerack .build/treerack.1
.build/treerack:
go build
go build -o .build/treerack ./cmd/treerack
install: $(sources)
go install ./cmd/treerack
head: $(sources) fmt
.build/head.go: $(sources) .build
go fmt ./...
go run scripts/createhead.go -- \
char.go \
sequence.go \
@ -39,8 +28,14 @@ head: $(sources) fmt
context.go \
nodehead.go \
syntaxhead.go \
> head.go
@gofmt -s -w head.go
> .build/head.go
go fmt .build/head.go
head.go: .build/head.go
cp .build/head.go .
.build/headexported.go: $(sources) .build
go fmt ./...
go run scripts/createhead.go --exported -- \
char.go \
sequence.go \
@ -50,72 +45,66 @@ head: $(sources) fmt
context.go \
nodehead.go \
syntaxhead.go \
> headexported.go
@gofmt -s -w headexported.go
> .build/headexported.go
go fmt .build/headexported.go
generate: $(sources) $(parsers) fmt head install
treerack generate -export -package-name self < syntax.treerack > self/self.go.next
@mv self/self.go.next self/self.go
@gofmt -s -w self/self.go
headexported.go: .build/headexported.go
cp .build/headexported.go .
regenerate: $(sources) $(parsers) fmt head install
treerack generate -export -package-name self < syntax.treerack > self/self.go.next
@mv self/self.go.next self/self.go
go install ./cmd/treerack
treerack generate -export -package-name self < syntax.treerack > self/self.go.next
@mv self/self.go.next self/self.go
@gofmt -s -w self/self.go
.build/self.go: $(sources) $(parsers) head.go headexported.go .build
# since generator code depends on the syntax itself, we need to passes:
go build -o .build/treerack.current ./cmd/treerack
.build/treerack.current generate --export --package-name self < syntax.treerack > .build/self.go
go fmt .build/self.go
cp internal/self/self.go .build/self.go.backup
cp .build/self.go internal/self
# second pass:
go build -o .build/treerack.interim ./cmd/treerack || mv .build/self.go.backup internal/self/self.go
.build/treerack.interim generate --export --package-name self < syntax.treerack > .build/self.go \
|| mv .build/self.go.backup internal/self/self.go
go fmt .build/self.go || mv .build/self.go.backup internal/self/self.go
mv .build/self.go.backup internal/self/self.go
check-generate: $(sources) $(parsers)
@echo checking head
@mv headexported.go headexported.go.backup
@go run scripts/createhead.go --exported -- \
char.go \
sequence.go \
choice.go \
idset.go \
results.go \
context.go \
nodehead.go \
syntaxhead.go \
> headexported.go
@gofmt -s -w headexported.go
@if ! diff headexported.go headexported.go.backup > /dev/null; then \
mv headexported.go.backup headexported.go; \
echo head does not match; \
false; \
fi
@echo checking self
@mv self/self.go self/self.go.backup
@treerack generate -export -package-name self < syntax.treerack > self/self.go.next
@mv self/self.go.next self/self.go
@gofmt -s -w self/self.go
@if ! diff self/self.go self/self.go.backup > /dev/null; then \
mv self/self.go.backup self/self.go; \
echo self does not match; \
false; \
fi
internal/self/self.go: .build/self.go
cp .build/self.go internal/self
@echo ok
@mv headexported.go.backup headexported.go
@mv self/self.go.backup self/self.go
lib: $(sources) head.go headexported.go internal/self/self.go
go build
go build ./internal/self
.build:
mkdir -p .build
cmd/treerack/docreflect.gen.go: $(sources) .build
go run scripts/docreflect.go > .build/docreflect.gen.go
mv .build/docreflect.gen.go cmd/treerack
cmd/treerack/readme.md: $(sources) cmd/treerack/docreflect.gen.go
go run scripts/cmdreadme.go ./cmd/treerack > cmd/treerack/readme.md || \
rm cmd/treerack/readme.md
.build/treerack.1: $(sources) cmd/treerack/docreflect.gen.go
.build/treerack: $(sources) lib cmd/treerack/docreflect.gen.go .build
go build -o .build/treerack -ldflags "-X main.version=$(version)" ./cmd/treerack
.build/treerack.1: $(sources) cmd/treerack/docreflect.gen.go .build
go run scripts/man.go $(version) $(release_date) > .build/treerack.1 || \
rm .build/treerack.1
check: build $(parsers)
go test -test.short -run ^Test
go test ./cmd/treerack -test.short -run ^Test
build: lib cmd/treerack/readme.md .build/treerack .build/treerack.1
checkall: build $(parsers)
check-generate: .build/head.go .build/headexported.go .build/self.go
@if ! diff head.go .build/head.go > /dev/null; then \
echo head.go does not match; \
false; \
fi
@if ! diff headexported.go .build/headexported.go > /dev/null; then \
echo headexported.go does not match; \
false; \
fi
@if ! diff internal/self/self.go .build/self.go > /dev/null; then \
echo self.go does not match; \
false; \
fi
check: $(sources) $(parsers) build check-generate
go test
go test ./cmd/treerack
@ -137,39 +126,28 @@ cover-cmd: .coverprofile-cmd
showcover-cmd: .coverprofile-cmd
go tool cover -html .coverprofile-cmd
# command line interface not included
publishcoverage: .coverprofile
curl -s https://codecov.io/bash -o codecov
bash codecov -Zf .coverprofile
.PHONY: cpu.out
cpu.out:
go test -v -run TestMMLFile -cpuprofile cpu.out
cpu: cpu.out
go tool pprof -top cpu.out
fmt: $(sources)
gofmt -w -s $(sources)
fmt: $(sources) head.go headexported.go internal/self/self.go cmd/treerack/docreflect.gen.go
go fmt ./...
checkfmt: $(sources)
if [ "$$(gofmt -s -d $(sources))" != "" ]; then false; else true; fi
$(prefix)/bin/treerack: .build/treerack
mkdir -p $(prefix)/bin
cp .build/treerack $(prefix)/bin
vet:
go vet ./...
$(prefix)/share/man/man1/treerack.1: .build/treerack.1
mkdir -p $(prefix)/share/man/man1
cp .build/treerack.1 $(prefix)/share/man/man1
precommit: fmt check-generate vet build checkall
install: $(prefix)/bin/treerack $(prefix)/share/man/man1/treerack.1
clean:
rm -f *.test
rm -f cpu.out
rm -f .coverprofile
go clean -i ./...
rm -f .build/treerack
rm -f .build/treerack.1
rm -f cmd/treerack/docreflect.gen.go
rm -f cmd/treerack/readme.md
ci-trigger: deps checkfmt build checkall
ifeq ($(TRAVIS_BRANCH)_$(TRAVIS_PULL_REQUEST), master_false)
make publishcoverage
endif
rm -rf .build
go clean ./...

View File

@ -2,46 +2,49 @@
Generated with https://code.squareroundforest.org/arpio/docreflect
*/
package main
import "code.squareroundforest.org/arpio/docreflect"
func init() {
docreflect.Register("main", "")
docreflect.Register("main.check", "check parses input content against the provided syntax definition and fails if the input does not match.\nSyntax can be provided via a filename option or an inline string option. Input can be provided via a filename\noption, a positional argument filename, an inline string option, or piped from standard input.\n\nfunc(o, stdin, args)")
docreflect.Register("main.checkOptions", "")
docreflect.Register("main.checkOptions.Input", "Input specifies the filename of the input content to be validated.\n")
docreflect.Register("main.checkOptions.InputString", "InputString specifies the input content as an inline string.\n")
docreflect.Register("main.checkOptions.Syntax", "Syntax specifies the filename of the syntax definition file.\n")
docreflect.Register("main.checkOptions.SyntaxString", "SyntaxString specifies the syntax as an inline string.\n")
docreflect.Register("main.checkSyntax", "checkSyntax validates a syntax definition. The syntax may be provided via a file path (using an option or a\npositional argument), an inline string, or piped from standard input.\n\nfunc(o, stdin, args)")
docreflect.Register("main.checkSyntaxOptions", "")
docreflect.Register("main.checkSyntaxOptions.Syntax", "Syntax specifies the filename of the syntax definition file.\n")
docreflect.Register("main.checkSyntaxOptions.SyntaxString", "SyntaxString specifies the syntax as an inline string.\n")
docreflect.Register("main.errInvalidFilename", "")
docreflect.Register("main.errMultipleInputs", "")
docreflect.Register("main.errNoInput", "")
docreflect.Register("main.generate", "generate generates Go code that can parse arbitrary input with the provided syntax, and can be used embedded\nin an application.\n\nThe syntax may be provided via a file path (using an option or a positional argument), an\ninline string, or piped from standard input.\n\nfunc(o, stdin, stdout, args)")
docreflect.Register("main.generateOptions", "")
docreflect.Register("main.generateOptions.Export", "Export determines whether the generated parse function is exported (visible outside its package).\n")
docreflect.Register("main.generateOptions.PackageName", "PackageName specifies the package name for the generated code. Defaults to main.\n")
docreflect.Register("main.generateOptions.Syntax", "Syntax specifies the filename of the syntax definition file.\n")
docreflect.Register("main.generateOptions.SyntaxString", "SyntaxString specifies the syntax as an inline string.\n")
docreflect.Register("main.initInput", "\nfunc(filename, stringValue, stdin, args)")
docreflect.Register("main.main", "\nfunc()")
docreflect.Register("main.mapNode", "\nfunc(n)")
docreflect.Register("main.node", "")
docreflect.Register("main.node.From", "")
docreflect.Register("main.node.Name", "")
docreflect.Register("main.node.Nodes", "")
docreflect.Register("main.node.Text", "")
docreflect.Register("main.node.To", "")
docreflect.Register("main.noop", "\nfunc()")
docreflect.Register("main.show", "show input content against a provided syntax definition and outputs the resulting AST (Abstract Syntax Tree)\nin JSON format. Syntax can be provided via a filename option or an inline string option. Input can be\nprovided via a filename option, a positional argument filename, an inline string option, or piped from\nstandard input.\n\nfunc(o, stdin, stdout, args)")
docreflect.Register("main.showOptions", "")
docreflect.Register("main.showOptions.Indent", "Indent specifies a custom indentation string for the output.\n")
docreflect.Register("main.showOptions.Input", "Input specifies the filename of the input content to be validated.\n")
docreflect.Register("main.showOptions.InputString", "InputString specifies the input content as an inline string.\n")
docreflect.Register("main.showOptions.Pretty", "Pretty enables indented, human-readable output.\n")
docreflect.Register("main.showOptions.Syntax", "Syntax specifies the filename of the syntax definition file.\n")
docreflect.Register("main.showOptions.SyntaxString", "SyntaxString specifies the syntax as an inline string.\n")
}
docreflect.Register("main", "")
docreflect.Register("main.check", "check parses input content against the provided syntax definition and fails if the input does not match.\nSyntax can be provided via a filename option or an inline string option. Input can be provided via a filename\noption, a positional argument filename, an inline string option, or piped from standard input.\n\nfunc(o, stdin, args)")
docreflect.Register("main.checkOptions", "")
docreflect.Register("main.checkOptions.Input", "Input specifies the filename of the input content to be validated.\n")
docreflect.Register("main.checkOptions.InputString", "InputString specifies the input content as an inline string.\n")
docreflect.Register("main.checkOptions.Syntax", "Syntax specifies the filename of the syntax definition file.\n")
docreflect.Register("main.checkOptions.SyntaxString", "SyntaxString specifies the syntax as an inline string.\n")
docreflect.Register("main.checkSyntax", "checkSyntax validates a syntax definition. The syntax may be provided via a file path (using an option or a\npositional argument), an inline string, or piped from standard input.\n\nfunc(o, stdin, args)")
docreflect.Register("main.checkSyntaxOptions", "")
docreflect.Register("main.checkSyntaxOptions.Syntax", "Syntax specifies the filename of the syntax definition file.\n")
docreflect.Register("main.checkSyntaxOptions.SyntaxString", "SyntaxString specifies the syntax as an inline string.\n")
docreflect.Register("main.errInvalidFilename", "")
docreflect.Register("main.errMultipleInputs", "")
docreflect.Register("main.errNoInput", "")
docreflect.Register("main.generate", "generate generates Go code that can parse arbitrary input with the provided syntax, and can be used embedded\nin an application.\n\nThe syntax may be provided via a file path (using an option or a positional argument), an\ninline string, or piped from standard input.\n\nfunc(o, stdin, stdout, args)")
docreflect.Register("main.generateOptions", "")
docreflect.Register("main.generateOptions.Export", "Export determines whether the generated parse function is exported (visible outside its package).\n")
docreflect.Register("main.generateOptions.PackageName", "PackageName specifies the package name for the generated code. Defaults to main.\n")
docreflect.Register("main.generateOptions.Syntax", "Syntax specifies the filename of the syntax definition file.\n")
docreflect.Register("main.generateOptions.SyntaxString", "SyntaxString specifies the syntax as an inline string.\n")
docreflect.Register("main.init", "\nfunc()")
docreflect.Register("main.initInput", "\nfunc(filename, stringValue, stdin, args)")
docreflect.Register("main.main", "\nfunc()")
docreflect.Register("main.mapNode", "\nfunc(n)")
docreflect.Register("main.node", "")
docreflect.Register("main.node.From", "")
docreflect.Register("main.node.Name", "")
docreflect.Register("main.node.Nodes", "")
docreflect.Register("main.node.Text", "")
docreflect.Register("main.node.To", "")
docreflect.Register("main.noop", "\nfunc()")
docreflect.Register("main.show", "show input content against a provided syntax definition and outputs the resulting AST (Abstract Syntax Tree)\nin JSON format. Syntax can be provided via a filename option or an inline string option. Input can be\nprovided via a filename option, a positional argument filename, an inline string option, or piped from\nstandard input.\n\nfunc(o, stdin, stdout, args)")
docreflect.Register("main.showOptions", "")
docreflect.Register("main.showOptions.Indent", "Indent specifies a custom indentation string for the output.\n")
docreflect.Register("main.showOptions.Input", "Input specifies the filename of the input content to be validated.\n")
docreflect.Register("main.showOptions.InputString", "InputString specifies the input content as an inline string.\n")
docreflect.Register("main.showOptions.Pretty", "Pretty enables indented, human-readable output.\n")
docreflect.Register("main.showOptions.Syntax", "Syntax specifies the filename of the syntax definition file.\n")
docreflect.Register("main.showOptions.SyntaxString", "SyntaxString specifies the syntax as an inline string.\n")
docreflect.Register("main.version", "")
}

View File

@ -2,10 +2,12 @@ package main
import . "code.squareroundforest.org/arpio/wand"
var version = "dev"
func main() {
checkSyntax := Args(Command("check-syntax", checkSyntax), 0, 1)
check := Args(Command("check", check), 0, 1)
show := Args(Command("show", show), 0, 1)
generate := Args(Command("generate", generate), 0, 1)
Exec(Group("treerack", checkSyntax, check, show, generate))
Exec(Version(Group("treerack", checkSyntax, check, show, generate), version))
}

View File

@ -115,6 +115,10 @@ piped from standard input.
- --syntax-string string: specifies the syntax as an inline string.
- --help: Show help.
### treerack version
Show version.
## Environment variables:
Every command line option's value can also be provided as an environment variable. Environment variable names

2
go.mod
View File

@ -3,13 +3,13 @@ module code.squareroundforest.org/arpio/treerack
go 1.25.3
require (
code.squareroundforest.org/arpio/docreflect v0.0.0-20260113222846-40bd1879753e
code.squareroundforest.org/arpio/wand v0.0.0-20260113225451-514cd3375d96
github.com/iancoleman/strcase v0.3.0
)
require (
code.squareroundforest.org/arpio/bind v0.0.0-20251125135123-0de6ad6e67f2 // indirect
code.squareroundforest.org/arpio/docreflect v0.0.0-20260113222846-40bd1879753e // indirect
code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect
code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect
code.squareroundforest.org/arpio/textedit v0.0.0-20251209222254-5a3e22b886be // indirect

12
go.sum
View File

@ -1,34 +1,22 @@
code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088=
code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI=
code.squareroundforest.org/arpio/bind v0.0.0-20251125135123-0de6ad6e67f2 h1:zEztr5eSD/V3lzKPcRAxNprobhHMd3w6Dw3oIbjNrrk=
code.squareroundforest.org/arpio/bind v0.0.0-20251125135123-0de6ad6e67f2/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI=
code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw=
code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA=
code.squareroundforest.org/arpio/docreflect v0.0.0-20260113222846-40bd1879753e h1:Z+TXQtCxNhHUgsBSYsatNGBCRtGibRcsEbZjk1LImCQ=
code.squareroundforest.org/arpio/docreflect v0.0.0-20260113222846-40bd1879753e/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA=
code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q=
code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE=
code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc=
code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY=
code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI=
code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs=
code.squareroundforest.org/arpio/textedit v0.0.0-20251209222254-5a3e22b886be h1:hy7tbsf8Fzl0UzBUNXRottKtCg3GvVI7Hmaf28Qoias=
code.squareroundforest.org/arpio/textedit v0.0.0-20251209222254-5a3e22b886be/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs=
code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4=
code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg=
code.squareroundforest.org/arpio/wand v0.0.0-20260108202216-ba493e77d610 h1:kgDcz4+PMq5iyd3r80vcZsNfphfaRIBf9B+D7B4vYfM=
code.squareroundforest.org/arpio/wand v0.0.0-20260108202216-ba493e77d610/go.mod h1:rYqrSmdkBlKjGwEPzzWAIRQKQJCpkdzG7vDiL6Fux9Y=
code.squareroundforest.org/arpio/wand v0.0.0-20260113225451-514cd3375d96 h1:RqFGMfQznU7ivTLS8/Qj0AantFbEHSAy6U/B4xoSO88=
code.squareroundforest.org/arpio/wand v0.0.0-20260113225451-514cd3375d96/go.mod h1:fPxs3LeGPxRMWUIXgBcdszk3a8d1TRqSHSVs5VL28Rc=
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=

View File

@ -1,6 +1,6 @@
package treerack
import "code.squareroundforest.org/arpio/treerack/self"
import "code.squareroundforest.org/arpio/treerack/internal/self"
func mapNodes(m func(n *Node) *Node, n []*Node) []*Node {
var nn []*Node

View File

@ -1,7 +1,7 @@
package treerack
import (
"code.squareroundforest.org/arpio/treerack/self"
"code.squareroundforest.org/arpio/treerack/internal/self"
"errors"
"fmt"
"io"