src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

main.go (2179B)


      1 package main
      2 
      3 import (
      4 	"context"
      5 	"flag"
      6 
      7 	"os"
      8 	"os/signal"
      9 	"path/filepath"
     10 	"syscall"
     11 	"time"
     12 
     13 	"code.dwrz.net/src/pkg/life"
     14 	"code.dwrz.net/src/pkg/log"
     15 	"code.dwrz.net/src/pkg/terminal"
     16 )
     17 
     18 var (
     19 	height = flag.Int("h", 0, "height")
     20 	width  = flag.Int("w", 0, "width")
     21 	tick   = flag.Int("t", 100, "ms between turns")
     22 )
     23 
     24 func main() {
     25 	var l = log.New(os.Stderr)
     26 
     27 	// Parse flags.
     28 	flag.Parse()
     29 	if *height < 0 {
     30 		l.Error.Fatalf("invalid height: %d", *height)
     31 	}
     32 	if *width < 0 {
     33 		l.Error.Fatalf("invalid width: %d", *width)
     34 	}
     35 	if *tick <= 0 {
     36 		l.Error.Fatalf("invalid tick: %d", *tick)
     37 	}
     38 
     39 	// Setup the main context.
     40 	ctx, cancel := context.WithCancel(context.Background())
     41 
     42 	// Setup workspace and log file.
     43 	cdir, err := os.UserCacheDir()
     44 	if err != nil {
     45 		l.Error.Fatalf(
     46 			"failed to determine user cache directory: %v", err,
     47 		)
     48 	}
     49 	wdir := filepath.Join(cdir, "life")
     50 
     51 	if err := os.MkdirAll(wdir, os.ModeDir|0700); err != nil {
     52 		l.Error.Fatalf("failed to create tmp dir: %v", err)
     53 	}
     54 
     55 	f, err := os.Create(wdir + "/log")
     56 	if err != nil {
     57 		l.Error.Fatalf("failed to create log file: %v", err)
     58 	}
     59 	defer f.Close()
     60 
     61 	// Retrieve terminal info.
     62 	t, err := terminal.New(os.Stdin.Fd())
     63 	if err != nil {
     64 		l.Error.Fatalf("failed to get terminal attributes: %v", err)
     65 	}
     66 	size, err := t.Size()
     67 	if err != nil {
     68 		l.Error.Fatalf("failed to get terminal size: %v", err)
     69 	}
     70 	if *height == 0 {
     71 		rows := int(size.Rows)
     72 		height = &rows
     73 	}
     74 	if *width == 0 {
     75 		cols := int(size.Columns) + 1
     76 		width = &cols
     77 	}
     78 
     79 	// TODO: refactor; handle sigwinch.
     80 	go func() {
     81 		var signals = make(chan os.Signal, 1)
     82 		signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
     83 
     84 		// Block until we receive a signal.
     85 		s := <-signals
     86 		l.Debug.Printf("received signal: %s", s)
     87 
     88 		cancel()
     89 	}()
     90 
     91 	// Setup the game.
     92 	var game = life.New(life.Parameters{
     93 		Height:   *height,
     94 		In:       os.Stdin,
     95 		Log:      log.New(f),
     96 		Out:      os.Stdout,
     97 		Terminal: t,
     98 		Tick:     time.Duration(*tick) * time.Millisecond,
     99 		Width:    *width,
    100 	})
    101 	if err != nil {
    102 		l.Error.Fatalf("failed to create game: %v", err)
    103 	}
    104 
    105 	// Run the game.
    106 	if err := game.Run(ctx); err != nil {
    107 		l.Error.Fatal(err)
    108 	}
    109 }