| 
									
										
										
										
											2014-10-23 15:48:53 +02:00
										 |  |  | // Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  | // modify it under the terms of the GNU General Public | 
					
						
							|  |  |  | // License as published by the Free Software Foundation; either | 
					
						
							|  |  |  | // version 2.1 of the License, or (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  | // General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | // along with this library; if not, write to the Free Software | 
					
						
							|  |  |  | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | 
					
						
							|  |  |  | // MA 02110-1301  USA | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-15 20:34:25 +02:00
										 |  |  | package ethrepl | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-21 23:36:55 +02:00
										 |  |  | // #cgo darwin CFLAGS: -I/usr/local/opt/readline/include | 
					
						
							|  |  |  | // #cgo darwin LDFLAGS: -L/usr/local/opt/readline/lib | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | // #cgo LDFLAGS: -lreadline | 
					
						
							|  |  |  | // #include <stdio.h> | 
					
						
							|  |  |  | // #include <stdlib.h> | 
					
						
							|  |  |  | // #include <readline/readline.h> | 
					
						
							|  |  |  | // #include <readline/history.h> | 
					
						
							|  |  |  | import "C" | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2014-10-18 13:30:38 +02:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2014-05-21 23:36:55 +02:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/signal" | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2014-05-21 23:36:55 +02:00
										 |  |  | 	"syscall" | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | 	"unsafe" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-21 23:36:55 +02:00
										 |  |  | func initReadLine() { | 
					
						
							|  |  |  | 	C.rl_catch_sigwinch = 0 | 
					
						
							| 
									
										
										
										
											2014-05-21 23:46:16 +02:00
										 |  |  | 	C.rl_catch_signals = 0 | 
					
						
							| 
									
										
										
										
											2014-05-21 23:36:55 +02:00
										 |  |  | 	c := make(chan os.Signal, 1) | 
					
						
							|  |  |  | 	signal.Notify(c, syscall.SIGWINCH) | 
					
						
							| 
									
										
										
										
											2014-05-21 23:46:16 +02:00
										 |  |  | 	signal.Notify(c, os.Interrupt) | 
					
						
							| 
									
										
										
										
											2014-05-21 23:36:55 +02:00
										 |  |  | 	go func() { | 
					
						
							|  |  |  | 		for sig := range c { | 
					
						
							|  |  |  | 			switch sig { | 
					
						
							|  |  |  | 			case syscall.SIGWINCH: | 
					
						
							|  |  |  | 				C.rl_resize_terminal() | 
					
						
							| 
									
										
										
										
											2014-05-21 23:46:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			case os.Interrupt: | 
					
						
							|  |  |  | 				C.rl_cleanup_after_signal() | 
					
						
							| 
									
										
										
										
											2014-05-21 23:36:55 +02:00
										 |  |  | 			default: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | func readLine(prompt *string) *string { | 
					
						
							|  |  |  | 	var p *C.char | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//readline allows an empty prompt(NULL) | 
					
						
							|  |  |  | 	if prompt != nil { | 
					
						
							|  |  |  | 		p = C.CString(*prompt) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret := C.readline(p) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if p != nil { | 
					
						
							|  |  |  | 		C.free(unsafe.Pointer(p)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ret == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} //EOF | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s := C.GoString(ret) | 
					
						
							|  |  |  | 	C.free(unsafe.Pointer(ret)) | 
					
						
							|  |  |  | 	return &s | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func addHistory(s string) { | 
					
						
							|  |  |  | 	p := C.CString(s) | 
					
						
							|  |  |  | 	C.add_history(p) | 
					
						
							|  |  |  | 	C.free(unsafe.Pointer(p)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | var indentCount = 0 | 
					
						
							|  |  |  | var str = "" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *JSRepl) setIndent() { | 
					
						
							|  |  |  | 	open := strings.Count(str, "{") | 
					
						
							|  |  |  | 	open += strings.Count(str, "(") | 
					
						
							|  |  |  | 	closed := strings.Count(str, "}") | 
					
						
							|  |  |  | 	closed += strings.Count(str, ")") | 
					
						
							|  |  |  | 	indentCount = open - closed | 
					
						
							|  |  |  | 	if indentCount <= 0 { | 
					
						
							|  |  |  | 		self.prompt = "> " | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		self.prompt = strings.Join(make([]string, indentCount*2), "..") | 
					
						
							|  |  |  | 		self.prompt += " " | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | func (self *JSRepl) read() { | 
					
						
							| 
									
										
										
										
											2014-05-21 23:36:55 +02:00
										 |  |  | 	initReadLine() | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | L: | 
					
						
							|  |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | 		switch result := readLine(&self.prompt); true { | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | 		case result == nil: | 
					
						
							| 
									
										
										
										
											2014-05-19 16:32:45 +02:00
										 |  |  | 			break L | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-19 16:32:45 +02:00
										 |  |  | 		case *result != "": | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | 			str += *result + "\n" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			self.setIndent() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if indentCount <= 0 { | 
					
						
							| 
									
										
										
										
											2014-05-19 16:32:45 +02:00
										 |  |  | 				if *result == "exit" { | 
					
						
							|  |  |  | 					self.Stop() | 
					
						
							|  |  |  | 					break L | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-24 10:09:02 +02:00
										 |  |  | 				hist := str[:len(str)-1] | 
					
						
							|  |  |  | 				addHistory(hist) //allow user to recall this line | 
					
						
							|  |  |  | 				self.history.WriteString(str) | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | 				self.parseInput(str) | 
					
						
							| 
									
										
										
										
											2014-05-19 16:32:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				str = "" | 
					
						
							| 
									
										
										
										
											2014-05-19 13:04:31 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-05-17 15:15:46 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-05-19 16:32:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-20 19:28:48 +02:00
										 |  |  | func (self *JSRepl) PrintValue(v interface{}) { | 
					
						
							| 
									
										
										
										
											2014-08-11 16:24:35 +02:00
										 |  |  | 	method, _ := self.re.Vm.Get("prettyPrint") | 
					
						
							|  |  |  | 	v, err := self.re.Vm.ToValue(v) | 
					
						
							| 
									
										
										
										
											2014-05-20 19:28:48 +02:00
										 |  |  | 	if err == nil { | 
					
						
							| 
									
										
										
										
											2014-10-15 02:41:26 +03:00
										 |  |  | 		val, err := method.Call(method, v) | 
					
						
							|  |  |  | 		if err == nil { | 
					
						
							|  |  |  | 			fmt.Printf("%v", val) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-05-20 19:28:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-05-19 16:32:45 +02:00
										 |  |  | } |