repl_darwin.go 2.1 KB

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