small pixel drawing of a pufferfish zoa

main.go

package main

import (
	"fmt"
	"log"
	"os"
	"strconv"

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

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

func printUsageExit() {
	fmt.Printf(`usage: zoa <command> [arguments]

commands:
  fmt     TODO
  run     <posix shell script> - 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 "fmt":
		if len(os.Args) <= 2 {
			fmt.Println("fmt requires 1 argument: the path to a posix shell script")
			os.Exit(1)
		}
		shell.ZoaFmt(os.Args[2])
	case "cp":
		var mode os.FileMode
		if len(os.Args) < 4 {
			fmt.Println("cp requires at least 2 arguments: source and destination")
			os.Exit(1)
		}
		if len(os.Args) == 4 {
			mode = 0644
		}
		if len(os.Args) > 4 {
			m64, err := strconv.ParseUint(os.Args[4], 0, 32)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
			mode = os.FileMode(m64)
		}
		shell.ZoaCopy(os.Args[2], os.Args[3], mode)
	case "version":
		fmt.Println("0.1.0")
	default:
		printUsageExit()
	}
	os.Exit(0)
}

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

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

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

	// TODO: err?
	shell.Run(r, script)
}