small pixel drawing of a pufferfish zoa

main.go

package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"

	"j3s.sh/zoa/env"
	"j3s.sh/zoa/shell"

	"mvdan.cc/sh/v3/interp"
)

func printUsageExit() {
	// TODO: -v -h
	fmt.Printf(`usage: zoa <command> [arguments]

commands:
  run    <main|scripts/example> - execute given zoa script
  version                       - print zoa version

examples:
  zoa run main
  zoa run scripts/hello-world
		
misc commands:
  cp    <src> <dst> [mode] - copy file from source to dest, optionally set mode
  get   <url> <dst>        - download file from url to dest
  watch <file> <command>   - execute command when file changes

examples: see README
`)

	os.Exit(1)
}

func main() {
	if len(os.Args) <= 1 {
		printUsageExit()
	}

	command := os.Args[1]
	switch command {
	case "run":
		zoaRun()
	case "version":
		fmt.Println("0.1.0")
		os.Exit(0)
	default:
		printUsageExit()
	}
}

func zoaRun() {
	if len(os.Args) <= 2 {
		fmt.Println("run requires 1 argument: the path to a posix shell script")
		os.Exit(1)
	}
	path := os.Args[2]

	if path != "main" {
		fmt.Println("incorrect script name: script must be named either main or scripts/<scriptname>")
		os.Exit(1)
	}

	envs, err := env.GenerateEnv()
	if err != nil {
		log.Fatal(err)
	}

	r, err := interp.New(
		// TODO: make quiet flag silence stdout
		interp.StdIO(nil, os.Stdout, os.Stdout),
		interp.CallHandler(shell.CallHandler),
		interp.Env(envs),
	)
	if err != nil {
		log.Fatal(err)
	}

	session := &shell.Session{
		ScriptPath:    path,
		ScriptBaseDir: filepath.Dir(path),
		Runner:        r,
		SubShell:      false,
	}

	// todo: err?
	session.Run()
}