repl_darwin.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. package ethrepl
  18. // #cgo darwin CFLAGS: -I/usr/local/opt/readline/include
  19. // #cgo darwin LDFLAGS: -L/usr/local/opt/readline/lib
  20. // #cgo LDFLAGS: -lreadline
  21. // #include <stdio.h>
  22. // #include <stdlib.h>
  23. // #include <readline/readline.h>
  24. // #include <readline/history.h>
  25. import "C"
  26. import (
  27. "fmt"
  28. "os"
  29. "os/signal"
  30. "strings"
  31. "syscall"
  32. "unsafe"
  33. )
  34. func initReadLine() {
  35. C.rl_catch_sigwinch = 0
  36. C.rl_catch_signals = 0
  37. c := make(chan os.Signal, 1)
  38. signal.Notify(c, syscall.SIGWINCH)
  39. signal.Notify(c, os.Interrupt)
  40. go func() {
  41. for sig := range c {
  42. switch sig {
  43. case syscall.SIGWINCH:
  44. C.rl_resize_terminal()
  45. case os.Interrupt:
  46. C.rl_cleanup_after_signal()
  47. default:
  48. }
  49. }
  50. }()
  51. }
  52. func readLine(prompt *string) *string {
  53. var p *C.char
  54. //readline allows an empty prompt(NULL)
  55. if prompt != nil {
  56. p = C.CString(*prompt)
  57. }
  58. ret := C.readline(p)
  59. if p != nil {
  60. C.free(unsafe.Pointer(p))
  61. }
  62. if ret == nil {
  63. return nil
  64. } //EOF
  65. s := C.GoString(ret)
  66. C.free(unsafe.Pointer(ret))
  67. return &s
  68. }
  69. func addHistory(s string) {
  70. p := C.CString(s)
  71. C.add_history(p)
  72. C.free(unsafe.Pointer(p))
  73. }
  74. var indentCount = 0
  75. var str = ""
  76. func (self *JSRepl) setIndent() {
  77. open := strings.Count(str, "{")
  78. open += strings.Count(str, "(")
  79. closed := strings.Count(str, "}")
  80. closed += strings.Count(str, ")")
  81. indentCount = open - closed
  82. if indentCount <= 0 {
  83. self.prompt = "> "
  84. } else {
  85. self.prompt = strings.Join(make([]string, indentCount*2), "..")
  86. self.prompt += " "
  87. }
  88. }
  89. func (self *JSRepl) read() {
  90. initReadLine()
  91. L:
  92. for {
  93. switch result := readLine(&self.prompt); true {
  94. case result == nil:
  95. break L
  96. case *result != "":
  97. str += *result + "\n"
  98. self.setIndent()
  99. if indentCount <= 0 {
  100. if *result == "exit" {
  101. self.Stop()
  102. break L
  103. }
  104. hist := str[:len(str)-1]
  105. addHistory(hist) //allow user to recall this line
  106. self.history.WriteString(str)
  107. self.parseInput(str)
  108. str = ""
  109. }
  110. }
  111. }
  112. }
  113. func (self *JSRepl) PrintValue(v interface{}) {
  114. method, _ := self.re.Vm.Get("prettyPrint")
  115. v, err := self.re.Vm.ToValue(v)
  116. if err == nil {
  117. val, err := method.Call(method, v)
  118. if err == nil {
  119. fmt.Printf("%v", val)
  120. }
  121. }
  122. }