github.com/mattn/anko@v0.1.10/anko.go (about)

     1  // +build !appengine
     2  
     3  package main
     4  
     5  import (
     6  	"bufio"
     7  	"flag"
     8  	"fmt"
     9  	"io"
    10  	"io/ioutil"
    11  	"os"
    12  	"strings"
    13  
    14  	"github.com/mattn/anko/core"
    15  	"github.com/mattn/anko/env"
    16  	_ "github.com/mattn/anko/packages"
    17  	"github.com/mattn/anko/parser"
    18  	"github.com/mattn/anko/vm"
    19  )
    20  
    21  const version = "0.1.8"
    22  
    23  var (
    24  	flagExecute string
    25  	file        string
    26  	args        []string
    27  	e           *env.Env
    28  )
    29  
    30  func main() {
    31  	var exitCode int
    32  
    33  	parseFlags()
    34  	setupEnv()
    35  	if flagExecute != "" || flag.NArg() > 0 {
    36  		exitCode = runNonInteractive()
    37  	} else {
    38  		exitCode = runInteractive()
    39  	}
    40  
    41  	os.Exit(exitCode)
    42  }
    43  
    44  func parseFlags() {
    45  	flagVersion := flag.Bool("v", false, "prints out the version and then exits")
    46  	flag.StringVar(&flagExecute, "e", "", "execute the Anko code")
    47  	flag.Parse()
    48  
    49  	if *flagVersion {
    50  		fmt.Println(version)
    51  		os.Exit(0)
    52  	}
    53  
    54  	if flagExecute != "" || flag.NArg() < 1 {
    55  		args = flag.Args()
    56  		return
    57  	}
    58  
    59  	file = flag.Arg(0)
    60  	args = flag.Args()[1:]
    61  }
    62  
    63  func setupEnv() {
    64  	e = env.NewEnv()
    65  	e.Define("args", args)
    66  	core.Import(e)
    67  }
    68  
    69  func runNonInteractive() int {
    70  	var source string
    71  	if flagExecute != "" {
    72  		source = flagExecute
    73  	} else {
    74  		sourceBytes, err := ioutil.ReadFile(file)
    75  		if err != nil {
    76  			fmt.Println("ReadFile error:", err)
    77  			return 2
    78  		}
    79  		source = string(sourceBytes)
    80  	}
    81  
    82  	_, err := vm.Execute(e, nil, source)
    83  	if err != nil {
    84  		fmt.Println("Execute error:", err)
    85  		return 4
    86  	}
    87  
    88  	return 0
    89  }
    90  
    91  func runInteractive() int {
    92  	var following bool
    93  	var source string
    94  	scanner := bufio.NewScanner(os.Stdin)
    95  
    96  	parser.EnableErrorVerbose()
    97  
    98  	for {
    99  		if following {
   100  			source += "\n"
   101  			fmt.Print("  ")
   102  		} else {
   103  			fmt.Print("> ")
   104  		}
   105  
   106  		if !scanner.Scan() {
   107  			break
   108  		}
   109  		source += scanner.Text()
   110  		if source == "" {
   111  			continue
   112  		}
   113  		if source == "quit()" {
   114  			break
   115  		}
   116  
   117  		stmts, err := parser.ParseSrc(source)
   118  
   119  		if e, ok := err.(*parser.Error); ok {
   120  			es := e.Error()
   121  			if strings.HasPrefix(es, "syntax error: unexpected") {
   122  				if strings.HasPrefix(es, "syntax error: unexpected $end,") {
   123  					following = true
   124  					continue
   125  				}
   126  			} else {
   127  				if e.Pos.Column == len(source) && !e.Fatal {
   128  					fmt.Fprintln(os.Stderr, e)
   129  					following = true
   130  					continue
   131  				}
   132  				if e.Error() == "unexpected EOF" {
   133  					following = true
   134  					continue
   135  				}
   136  			}
   137  		}
   138  
   139  		following = false
   140  		source = ""
   141  		var v interface{}
   142  
   143  		if err == nil {
   144  			v, err = vm.Run(e, nil, stmts)
   145  		}
   146  		if err != nil {
   147  			if e, ok := err.(*vm.Error); ok {
   148  				fmt.Fprintf(os.Stderr, "%d:%d %s\n", e.Pos.Line, e.Pos.Column, err)
   149  			} else if e, ok := err.(*parser.Error); ok {
   150  				fmt.Fprintf(os.Stderr, "%d:%d %s\n", e.Pos.Line, e.Pos.Column, err)
   151  			} else {
   152  				fmt.Fprintln(os.Stderr, err)
   153  			}
   154  			continue
   155  		}
   156  
   157  		fmt.Printf("%#v\n", v)
   158  	}
   159  
   160  	if err := scanner.Err(); err != nil {
   161  		if err != io.EOF {
   162  			fmt.Fprintln(os.Stderr, "ReadString error:", err)
   163  			return 12
   164  		}
   165  	}
   166  
   167  	return 0
   168  }