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

     1  // +build js,wasm
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"html"
     8  	"strings"
     9  	"syscall/js"
    10  
    11  	"github.com/mattn/anko/core"
    12  	"github.com/mattn/anko/packages"
    13  	"github.com/mattn/anko/parser"
    14  	"github.com/mattn/anko/vm"
    15  )
    16  
    17  var (
    18  	result = js.Global.Get("document").Call("getElementById", "result")
    19  	input  = js.Global.Get("document").Call("getElementById", "input")
    20  )
    21  
    22  func writeCommand(s string) {
    23  	result.Set("innerHTML", result.Get("innerHTML").String()+"<p class='command'>"+html.EscapeString(s)+"</p>")
    24  	result.Set("scrollTop", result.Get("scrollHeight").Int())
    25  }
    26  
    27  func writeStdout(s string) {
    28  	result.Set("innerHTML", result.Get("innerHTML").String()+"<p class='stdout'>"+html.EscapeString(s)+"</p>")
    29  	result.Set("scrollTop", result.Get("scrollHeight").Int())
    30  }
    31  
    32  func writeStderr(s string) {
    33  	result.Set("innerHTML", result.Get("innerHTML").String()+"<p class='stderr'>"+html.EscapeString(s)+"</p>")
    34  	result.Set("scrollTop", result.Get("scrollHeight").Int())
    35  }
    36  
    37  func main() {
    38  	env := vm.NewEnv()
    39  	core.Import(env)
    40  	packages.DefineImport(env)
    41  
    42  	env.Define("print", func(a ...interface{}) {
    43  		writeStdout(fmt.Sprint(a...))
    44  	})
    45  	env.Define("printf", func(a string, b ...interface{}) {
    46  		writeStdout(fmt.Sprintf(a, b...))
    47  	})
    48  
    49  	var following bool
    50  	var source string
    51  
    52  	parser.EnableErrorVerbose()
    53  
    54  	ch := make(chan string)
    55  
    56  	input.Call("addEventListener", "keypress", js.NewCallback(func(args []js.Value) {
    57  		e := args[0]
    58  		if e.Get("keyCode").Int() != 13 {
    59  			return
    60  		}
    61  		s := e.Get("target").Get("value").String()
    62  		e.Get("target").Set("value", "")
    63  		writeCommand(s)
    64  		ch <- s
    65  	}))
    66  	input.Set("disabled", false)
    67  	result.Set("innerHTML", "")
    68  
    69  	go func() {
    70  		for {
    71  			text, ok := <-ch
    72  			if !ok {
    73  				break
    74  			}
    75  			source += text
    76  			if source == "" {
    77  				continue
    78  			}
    79  			if source == "quit()" {
    80  				break
    81  			}
    82  
    83  			stmts, err := parser.ParseSrc(source)
    84  
    85  			if e, ok := err.(*parser.Error); ok {
    86  				es := e.Error()
    87  				if strings.HasPrefix(es, "syntax error: unexpected") {
    88  					if strings.HasPrefix(es, "syntax error: unexpected $end,") {
    89  						following = true
    90  						continue
    91  					}
    92  				} else {
    93  					if e.Pos.Column == len(source) && !e.Fatal {
    94  						writeStderr(e.Error())
    95  						following = true
    96  						continue
    97  					}
    98  					if e.Error() == "unexpected EOF" {
    99  						following = true
   100  						continue
   101  					}
   102  				}
   103  			}
   104  
   105  			following = false
   106  			source = ""
   107  			var v interface{}
   108  
   109  			if err == nil {
   110  				v, err = vm.Run(stmts, env)
   111  			}
   112  			if err != nil {
   113  				if e, ok := err.(*vm.Error); ok {
   114  					writeStderr(fmt.Sprintf("%d:%d %s\n", e.Pos.Line, e.Pos.Column, err))
   115  				} else if e, ok := err.(*parser.Error); ok {
   116  					writeStderr(fmt.Sprintf("%d:%d %s\n", e.Pos.Line, e.Pos.Column, err))
   117  				} else {
   118  					writeStderr(err.Error())
   119  				}
   120  				continue
   121  			}
   122  
   123  			writeStdout(fmt.Sprintf("%#v\n", v))
   124  		}
   125  	}()
   126  
   127  	select {}
   128  
   129  }