Improved project structure

This commit is contained in:
Eduard Urbach 2023-10-20 17:07:44 +02:00
parent 3a002a7562
commit bd73132a30
Signed by: eduard
GPG key ID: 49226B848C78F6C8
18 changed files with 33 additions and 15 deletions

37
src/cli/Build.go Normal file
View file

@ -0,0 +1,37 @@
package cli
import (
"git.akyoto.dev/cli/q/src/build"
"git.akyoto.dev/cli/q/src/log"
)
// Build builds an executable.
func Build(args []string) int {
directory := "."
if len(args) > 0 {
directory = args[0]
}
b := build.New(directory)
for i := 1; i < len(args); i++ {
switch args[i] {
case "--dry":
b.WriteExecutable = false
default:
log.Error.Printf("Unknown parameter: %s\n", args[i])
return 2
}
}
err := b.Run()
if err != nil {
log.Error.Println(err)
return 1
}
return 0
}

14
src/cli/Help.go Normal file
View file

@ -0,0 +1,14 @@
package cli
import (
"git.akyoto.dev/cli/q/src/log"
)
// Help shows the command line argument usage.
func Help(args []string) int {
log.Error.Println("Usage: q [command] [options]")
log.Error.Println("")
log.Error.Println(" build [directory]")
log.Error.Println(" system")
return 2
}

21
src/cli/Main.go Normal file
View file

@ -0,0 +1,21 @@
package cli
// Main is the entry point for the CLI frontend.
// It returns the exit code of the compiler.
// We never call os.Exit directly here because it's bad for testing.
func Main(args []string) int {
if len(args) == 0 {
return Help(nil)
}
switch args[0] {
case "build":
return Build(args[1:])
case "system":
return System(args[1:])
default:
return Help(args[1:])
}
}

37
src/cli/System.go Normal file
View file

@ -0,0 +1,37 @@
package cli
import (
"os"
"runtime"
"git.akyoto.dev/cli/q/src/log"
)
// System shows system information.
func System(args []string) int {
line := "%-19s%s\n"
log.Info.Printf(line, "Platform:", runtime.GOOS)
log.Info.Printf(line, "Architecture:", runtime.GOARCH)
log.Info.Printf(line, "Go:", runtime.Version())
// Directory
directory, err := os.Getwd()
if err == nil {
log.Info.Printf(line, "Directory:", directory)
} else {
log.Info.Printf(line, "Directory:", err.Error())
}
// Compiler
executable, err := os.Executable()
if err == nil {
log.Info.Printf(line, "Compiler:", executable)
} else {
log.Info.Printf(line, "Compiler:", err.Error())
}
return 0
}

47
src/cli/cli_test.go Normal file
View file

@ -0,0 +1,47 @@
package cli_test
import (
"io"
"os"
"testing"
"git.akyoto.dev/cli/q/src/cli"
"git.akyoto.dev/cli/q/src/log"
"git.akyoto.dev/go/assert"
)
func TestMain(m *testing.M) {
log.Info.SetOutput(io.Discard)
log.Error.SetOutput(io.Discard)
os.Exit(m.Run())
}
func TestCLI(t *testing.T) {
type cliTest struct {
arguments []string
expectedExitCode int
}
tests := []cliTest{
{[]string{}, 2},
{[]string{"invalid"}, 2},
{[]string{"system"}, 0},
{[]string{"build", "non-existing-directory"}, 1},
{[]string{"build", "examples/hello/hello.q"}, 1},
{[]string{"build", "examples/hello", "--invalid"}, 2},
}
for _, test := range tests {
exitCode := cli.Main(test.arguments)
t.Log(test.arguments)
assert.Equal(t, exitCode, test.expectedExitCode)
}
}
func BenchmarkBuild(b *testing.B) {
args := []string{"build", "examples/hello", "--dry"}
for i := 0; i < b.N; i++ {
cli.Main(args)
}
}