From 770808ce0d44cadfedbe01694c836be2eaf0e82c Mon Sep 17 00:00:00 2001 From: obscuren Date: Sat, 17 May 2014 15:15:46 +0200 Subject: [PATCH] Readline repl for linux & osx --- ethereal/ui/gui.go | 2 +- ethereum/ethereum.go | 4 +- ethereum/javascript_console.go | 71 ++++++++++++++++++---------------- ethereum/repl_darwin.go | 55 ++++++++++++++++++++++++++ ethereum/repl_linux.go | 1 + ethereum/repl_windows.go | 20 ++++++++++ utils/cmd.go | 8 ++-- 7 files changed, 122 insertions(+), 39 deletions(-) create mode 100644 ethereum/repl_darwin.go create mode 120000 ethereum/repl_linux.go create mode 100644 ethereum/repl_windows.go diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index c4cc1373f..24be9e0c5 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -197,7 +197,7 @@ func (gui *Gui) update() { case b := <-blockChan: block := b.Resource.(*ethchain.Block) if bytes.Compare(block.Coinbase, gui.addr) == 0 { - gui.setWalletValue(gui.eth.StateManager().ProcState().GetAccount(gui.addr).Amount, nil) + gui.setWalletValue(gui.eth.StateManager().CurrentState().GetAccount(gui.addr).Amount, nil) } case txMsg := <-txChan: diff --git a/ethereum/ethereum.go b/ethereum/ethereum.go index 128e11139..04933ef8e 100644 --- a/ethereum/ethereum.go +++ b/ethereum/ethereum.go @@ -151,9 +151,9 @@ save these words so you can restore your account later: %s console := NewConsole(ethereum) go console.Start() } else if StartJsConsole { - c := NewJSConsole(ethereum) + repl := NewJSRepl(ethereum) - go c.Start() + go repl.Start() } if StartRpc { diff --git a/ethereum/javascript_console.go b/ethereum/javascript_console.go index 9adf51bcc..9a10ca236 100644 --- a/ethereum/javascript_console.go +++ b/ethereum/javascript_console.go @@ -1,47 +1,58 @@ package main import ( - "bufio" "fmt" "github.com/ethereum/eth-go" "github.com/ethereum/eth-go/ethpub" "github.com/robertkrimen/otto" - "os" ) -type JSConsole struct { +type Repl interface { + Start() +} + +type JSRE struct { vm *otto.Otto lib *ethpub.PEthereum } -func NewJSConsole(ethereum *eth.Ethereum) *JSConsole { - return &JSConsole{vm: otto.New(), lib: ethpub.NewPEthereum(ethereum)} +func NewJSRE(ethereum *eth.Ethereum) *JSRE { + re := &JSRE{vm: otto.New(), lib: ethpub.NewPEthereum(ethereum)} + + re.Bind("eth", &JSEthereum{re.lib, re.vm}) + + return re } -func (self *JSConsole) Start() { - self.initBindings() +func (self *JSRE) Bind(name string, v interface{}) { + self.vm.Set(name, v) +} +func (self *JSRE) Run(code string) (otto.Value, error) { + return self.vm.Run(code) +} + +type JSRepl struct { + re *JSRE +} + +func NewJSRepl(ethereum *eth.Ethereum) *JSRepl { + return &JSRepl{re: NewJSRE(ethereum)} +} + +func (self *JSRepl) Start() { fmt.Println("Eth JavaScript console") - reader := bufio.NewReader(os.Stdin) - for { - fmt.Printf("eth >>> ") - str, _, err := reader.ReadLine() - if err != nil { - fmt.Println("Error reading input", err) - } else { - self.ParseInput(string(str)) - } - } + self.read() } -func (self *JSConsole) ParseInput(code string) { +func (self *JSRepl) parseInput(code string) { defer func() { if r := recover(); r != nil { fmt.Println("[native] error", r) } }() - value, err := self.vm.Run(code) + value, err := self.re.Run(code) if err != nil { fmt.Println(err) return @@ -50,28 +61,22 @@ func (self *JSConsole) ParseInput(code string) { fmt.Println(value) } -func (self *JSConsole) initBindings() { - t := &JSWrapper{self.lib, self.vm} - - self.vm.Set("eth", t) -} - -// The JS wrapper attempts to wrap the PEthereum object and returns -// proper javascript objects -type JSWrapper struct { +// The JSEthereum object attempts to wrap the PEthereum object and returns +// meaningful javascript objects +type JSEthereum struct { *ethpub.PEthereum vm *otto.Otto } -func (self *JSWrapper) GetKey() otto.Value { +func (self *JSEthereum) GetKey() otto.Value { return self.toVal(self.PEthereum.GetKey()) } -func (self *JSWrapper) GetStateObject(addr string) otto.Value { +func (self *JSEthereum) GetStateObject(addr string) otto.Value { return self.toVal(self.PEthereum.GetStateObject(addr)) } -func (self *JSWrapper) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value { +func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value { r, err := self.PEthereum.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr) if err != nil { fmt.Println(err) @@ -82,7 +87,7 @@ func (self *JSWrapper) Transact(key, recipient, valueStr, gasStr, gasPriceStr, d return self.toVal(r) } -func (self *JSWrapper) Create(key, valueStr, gasStr, gasPriceStr, initStr, bodyStr string) otto.Value { +func (self *JSEthereum) Create(key, valueStr, gasStr, gasPriceStr, initStr, bodyStr string) otto.Value { r, err := self.PEthereum.Create(key, valueStr, gasStr, gasPriceStr, initStr, bodyStr) if err != nil { @@ -95,7 +100,7 @@ func (self *JSWrapper) Create(key, valueStr, gasStr, gasPriceStr, initStr, bodyS } // Wrapper function -func (self *JSWrapper) toVal(v interface{}) otto.Value { +func (self *JSEthereum) toVal(v interface{}) otto.Value { result, err := self.vm.ToValue(v) if err != nil { diff --git a/ethereum/repl_darwin.go b/ethereum/repl_darwin.go new file mode 100644 index 000000000..b6de190e4 --- /dev/null +++ b/ethereum/repl_darwin.go @@ -0,0 +1,55 @@ +package main + +// #cgo LDFLAGS: -lreadline +// #include +// #include +// #include +// #include +import "C" +import "unsafe" + +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)) +} + +func (self *JSRepl) read() { + prompt := "eth >>> " + +L: + for { + switch result := readLine(&prompt); true { + case result == nil: + break L //exit loop + + case *result != "": //ignore blank lines + addHistory(*result) //allow user to recall this line + + self.parseInput(*result) + } + } +} diff --git a/ethereum/repl_linux.go b/ethereum/repl_linux.go new file mode 120000 index 000000000..276f135d7 --- /dev/null +++ b/ethereum/repl_linux.go @@ -0,0 +1 @@ +repl_darwin.go \ No newline at end of file diff --git a/ethereum/repl_windows.go b/ethereum/repl_windows.go new file mode 100644 index 000000000..c65bb1cb4 --- /dev/null +++ b/ethereum/repl_windows.go @@ -0,0 +1,20 @@ +package main + +import ( + "bufio" + "fmt" + "os" +) + +func (self *JSRepl) read() { + reader := bufio.NewReader(os.Stdin) + for { + fmt.Printf("eth >>> ") + str, _, err := reader.ReadLine() + if err != nil { + fmt.Println("Error reading input", err) + } else { + self.parseInput(string(str)) + } + } +} diff --git a/utils/cmd.go b/utils/cmd.go index 8395ac8fc..62e8f31dc 100644 --- a/utils/cmd.go +++ b/utils/cmd.go @@ -35,9 +35,11 @@ func DoMining(ethereum *eth.Ethereum) { // Give it some time to connect with peers time.Sleep(3 * time.Second) - for ethereum.IsUpToDate() == false { - time.Sleep(5 * time.Second) - } + /* + for ethereum.IsUpToDate() == false { + time.Sleep(5 * time.Second) + } + */ log.Println("Miner started") miner := ethminer.NewDefaultMiner(addr, ethereum)