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  }