github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/cmd/ethereum/repl/repl_darwin.go (about) 1 // Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. 2 // 3 // This library is free software; you can redistribute it and/or 4 // modify it under the terms of the GNU General Public 5 // License as published by the Free Software Foundation; either 6 // version 2.1 of the License, or (at your option) any later version. 7 // 8 // This library is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 // General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this library; if not, write to the Free Software 15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 16 // MA 02110-1301 USA 17 18 package ethrepl 19 20 // #cgo darwin CFLAGS: -I/usr/local/opt/readline/include 21 // #cgo darwin LDFLAGS: -L/usr/local/opt/readline/lib 22 // #cgo LDFLAGS: -lreadline 23 // #include <stdio.h> 24 // #include <stdlib.h> 25 // #include <readline/readline.h> 26 // #include <readline/history.h> 27 import "C" 28 import ( 29 "fmt" 30 "os" 31 "os/signal" 32 "strings" 33 "syscall" 34 "unsafe" 35 ) 36 37 func initReadLine() { 38 C.rl_catch_sigwinch = 0 39 C.rl_catch_signals = 0 40 c := make(chan os.Signal, 1) 41 signal.Notify(c, syscall.SIGWINCH) 42 signal.Notify(c, os.Interrupt) 43 go func() { 44 for sig := range c { 45 switch sig { 46 case syscall.SIGWINCH: 47 C.rl_resize_terminal() 48 49 case os.Interrupt: 50 C.rl_cleanup_after_signal() 51 default: 52 53 } 54 } 55 }() 56 } 57 58 func readLine(prompt *string) *string { 59 var p *C.char 60 61 //readline allows an empty prompt(NULL) 62 if prompt != nil { 63 p = C.CString(*prompt) 64 } 65 66 ret := C.readline(p) 67 68 if p != nil { 69 C.free(unsafe.Pointer(p)) 70 } 71 72 if ret == nil { 73 return nil 74 } //EOF 75 76 s := C.GoString(ret) 77 C.free(unsafe.Pointer(ret)) 78 return &s 79 } 80 81 func addHistory(s string) { 82 p := C.CString(s) 83 C.add_history(p) 84 C.free(unsafe.Pointer(p)) 85 } 86 87 var indentCount = 0 88 var str = "" 89 90 func (self *JSRepl) setIndent() { 91 open := strings.Count(str, "{") 92 open += strings.Count(str, "(") 93 closed := strings.Count(str, "}") 94 closed += strings.Count(str, ")") 95 indentCount = open - closed 96 if indentCount <= 0 { 97 self.prompt = "> " 98 } else { 99 self.prompt = strings.Join(make([]string, indentCount*2), "..") 100 self.prompt += " " 101 } 102 } 103 104 func (self *JSRepl) read() { 105 initReadLine() 106 L: 107 for { 108 switch result := readLine(&self.prompt); true { 109 case result == nil: 110 break L 111 112 case *result != "": 113 str += *result + "\n" 114 115 self.setIndent() 116 117 if indentCount <= 0 { 118 if *result == "exit" { 119 self.Stop() 120 break L 121 } 122 123 hist := str[:len(str)-1] 124 addHistory(hist) //allow user to recall this line 125 self.history.WriteString(str) 126 127 self.parseInput(str) 128 129 str = "" 130 } 131 } 132 } 133 } 134 135 func (self *JSRepl) PrintValue(v interface{}) { 136 method, _ := self.re.Vm.Get("prettyPrint") 137 v, err := self.re.Vm.ToValue(v) 138 if err == nil { 139 val, err := method.Call(method, v) 140 if err == nil { 141 fmt.Printf("%v", val) 142 } 143 } 144 }