go-ethereum/cmd/ethereum/repl/repl_darwin.go

145 lines
2.9 KiB
Go
Raw Normal View History

2014-10-23 16:48:53 +03: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 21:34:25 +03:00
package ethrepl
2014-05-17 16:15:46 +03:00
2014-05-22 00:36:55 +03:00
// #cgo darwin CFLAGS: -I/usr/local/opt/readline/include
// #cgo darwin LDFLAGS: -L/usr/local/opt/readline/lib
2014-05-17 16:15:46 +03:00
// #cgo LDFLAGS: -lreadline
// #include <stdio.h>
// #include <stdlib.h>
// #include <readline/readline.h>
// #include <readline/history.h>
import "C"
2014-05-19 14:04:31 +03:00
import (
2014-10-18 14:30:38 +03:00
"fmt"
2014-05-22 00:36:55 +03:00
"os"
"os/signal"
2014-05-19 14:04:31 +03:00
"strings"
2014-05-22 00:36:55 +03:00
"syscall"
2014-05-19 14:04:31 +03:00
"unsafe"
)
2014-05-17 16:15:46 +03:00
2014-05-22 00:36:55 +03:00
func initReadLine() {
C.rl_catch_sigwinch = 0
2014-05-22 00:46:16 +03:00
C.rl_catch_signals = 0
2014-05-22 00:36:55 +03:00
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGWINCH)
2014-05-22 00:46:16 +03:00
signal.Notify(c, os.Interrupt)
2014-05-22 00:36:55 +03:00
go func() {
for sig := range c {
switch sig {
case syscall.SIGWINCH:
C.rl_resize_terminal()
2014-05-22 00:46:16 +03:00
case os.Interrupt:
C.rl_cleanup_after_signal()
2014-05-22 00:36:55 +03:00
default:
}
}
}()
}
2014-05-17 16:15:46 +03: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 14:04:31 +03: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 16:15:46 +03:00
2014-05-19 14:04:31 +03:00
func (self *JSRepl) read() {
2014-05-22 00:36:55 +03:00
initReadLine()
2014-05-17 16:15:46 +03:00
L:
for {
2014-05-19 14:04:31 +03:00
switch result := readLine(&self.prompt); true {
2014-05-17 16:15:46 +03:00
case result == nil:
2014-05-19 17:32:45 +03:00
break L
2014-05-17 16:15:46 +03:00
2014-05-19 17:32:45 +03:00
case *result != "":
2014-05-19 14:04:31 +03:00
str += *result + "\n"
self.setIndent()
if indentCount <= 0 {
2014-05-19 17:32:45 +03:00
if *result == "exit" {
self.Stop()
break L
}
hist := str[:len(str)-1]
addHistory(hist) //allow user to recall this line
self.history.WriteString(str)
2014-05-17 16:15:46 +03:00
2014-05-19 14:04:31 +03:00
self.parseInput(str)
2014-05-19 17:32:45 +03:00
str = ""
2014-05-19 14:04:31 +03:00
}
2014-05-17 16:15:46 +03:00
}
}
}
2014-05-19 17:32:45 +03:00
2014-05-20 20:28:48 +03:00
func (self *JSRepl) PrintValue(v interface{}) {
method, _ := self.re.Vm.Get("prettyPrint")
v, err := self.re.Vm.ToValue(v)
2014-05-20 20:28:48 +03:00
if err == nil {
val, err := method.Call(method, v)
if err == nil {
fmt.Printf("%v", val)
}
2014-05-20 20:28:48 +03:00
}
2014-05-19 17:32:45 +03:00
}