on master help sign in
Thunk
fa103b1Rob Blanckaert
Dockerfilenew file+13
@@ -0,0 +1,13 @@
1+FROM ubuntu:bionic
2+
3+RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential wget golang python-dev python3-dev liblua5.2-dev ruby2.5-dev tcl-dev libnspr4-dev libffi-dev
4+
5+RUN wget http://launchpadlibrarian.net/309343864/libmozjs185-dev_1.8.5-1.0.0+dfsg-7_amd64.deb && wget http://launchpadlibrarian.net/309343863/libmozjs185-1.0_1.8.5-1.0.0+dfsg-7_amd64.deb && dpkg -i libmozjs185*.deb && rm libmozjs185*.deb
6+
7+ADD . /prybar
8+RUN cd /prybar && make
9+
10+WORKDIR /prybar
11+
12+# ENTRYPOINT ['/prybar/prybar']
13+# CMD ['/prybar/prybar', '-h']
src/language.go+15−2
@@ -5,6 +5,7 @@ import(
5 "plugin"
5 "plugin"
6 "fmt"
6 "fmt"
7 "runtime"
7 "runtime"
8+ "path/filepath"
8)
9)
9
10
10type PluginBase interface {
11type PluginBase interface {
@@ -46,8 +47,20 @@ func finalizer(f *Langauge) {
46 fmt.Println("a finalizer has run.")
47 fmt.Println("a finalizer has run.")
47}
48}
48
49
49−func GetLanguage(name string) *Langauge {
50+func GetLanguage(name string) *Langauge {
51+ base := "."
52+ exe, err := os.Executable()
53+ for {
54+ o, err := os.Readlink(exe)
55+ if err == nil {
56+ exe = o
57+ } else {
58+ break
59+ }
60+ }
61+
62+ base = filepath.Dir(exe)
50− plug, err := plugin.Open("./plugins/" + name + ".so")
63+ plug, err := plugin.Open(base + "/plugins/" + name + ".so")
51
64
52 if err != nil {
65 if err != nil {
53 fmt.Println(err)
66 fmt.Println(err)
src/languages/python3/main.go+3−3
@@ -1,14 +1,14 @@
1package main
1package main
2
2
3/*
3/*
4−#cgo pkg-config: python2
4+#cgo pkg-config: python3
5#include <Python.h>
5#include <Python.h>
6
6
7void pry_eval_file(FILE* f, const char* file, int argn, const char *argv) {
7void pry_eval_file(FILE* f, const char* file, int argn, const char *argv) {
8− const char* xargv[argn+1];
8+ const wchar_t* xargv[argn+1];
9 const char* ptr = argv;
9 const char* ptr = argv;
10 for (int i = 0; i < argn; ++i) {
10 for (int i = 0; i < argn; ++i) {
11− xargv[i] = ptr;
11+ xargv[i] = Py_DecodeLocale(ptr, NULL);
12 ptr += strlen(ptr) + 1;
12 ptr += strlen(ptr) + 1;
13 }
13 }
14 xargv[argn] = NULL;
14 xargv[argn] = NULL;
src/languages/ruby/main.go+16
@@ -39,6 +39,16 @@ char * pry_eval(const char* code) {
39
39
40}
40}
41
41
42+void pry_eval_file(const char* file ) {
43+ char* options[] = { "ruby", file };
44+ void* node = ruby_options(2, options);
45+
46+ int state;
47+ if (ruby_executable_node(node, &state))
48+ {
49+ state = ruby_exec_node(node);
50+ }
51+}
42
52
43*/
53*/
44import "C"
54import "C"
@@ -71,6 +81,12 @@ func (p Ruby) EvalExpression(code string) string {
71 return C.GoString(res);
81 return C.GoString(res);
72}
82}
73
83
84+func (p Ruby) EvalFile(file string, args []string) {
85+ cfile := C.CString(file)
86+ defer C.free(unsafe.Pointer(cfile))
87+ C.pry_eval_file(cfile)
88+}
89+
74func (p Ruby) REPL() {
90func (p Ruby) REPL() {
75 p.Eval("require 'irb'\nbinding.irb")
91 p.Eval("require 'irb'\nbinding.irb")
76}
92}
src/languages/tcl/main.gonew file+83
@@ -0,0 +1,83 @@
1+package main
2+
3+/*
4+#cgo pkg-config: tcl
5+#include <stdlib.h>
6+#include <tcl.h>
7+
8+Tcl_Interp *interp;
9+int ExtendTcl (Tcl_Interp *interp) {
10+
11+ return TCL_OK;
12+}
13+
14+void pry_open() {
15+ interp = Tcl_CreateInterp();
16+ if (Tcl_Init(interp) != TCL_OK) {
17+ exit(8);
18+ }
19+}
20+
21+void pry_close() {
22+ Tcl_Finalize();
23+}
24+
25+char * pry_version() {
26+ char *result = malloc(100);
27+ int a, b, c;
28+ Tcl_GetVersion(&a, &b, &c, NULL);
29+ sprintf(result, "%d.%d.%d",a,b,c);
30+ return result;
31+}
32+
33+char * pry_eval(const char* code) {
34+ if ( Tcl_Eval(interp, code) == TCL_OK ) {
35+ return Tcl_GetStringResult(interp);
36+ } else {
37+ fprintf(stderr, "error: %s\n", Tcl_GetStringResult (interp));
38+ return "";
39+ }
40+}
41+
42+*/
43+import "C"
44+
45+import (
46+ "unsafe"
47+)
48+
49+
50+type Python struct {
51+
52+}
53+
54+func (p Python) Open() {
55+ C.pry_open()
56+}
57+
58+func (p Python) Version() string {
59+ cver := C.pry_version()
60+ ver := C.GoString(cver)
61+ C.free(unsafe.Pointer(cver))
62+ return "TCL " + ver
63+}
64+
65+func (p Python) Eval(code string) {
66+ ccode := C.CString(code)
67+ defer C.free(unsafe.Pointer(ccode))
68+ C.pry_eval(ccode)
69+}
70+
71+func (p Python) EvalExpression(code string) string {
72+ ccode := C.CString(code)
73+ defer C.free(unsafe.Pointer(ccode))
74+ return C.GoString(C.pry_eval(ccode))
75+}
76+
77+
78+func (p Python) Close() {
79+ C.pry_close()
80+}
81+
82+// exported
83+var Instance Python
src/linenoise-helper.cnew file+11
@@ -0,0 +1,11 @@
1+#include <stdlib.h>
2+#include <linenoise.h>
3+
4+void linenoiseCompletionStub(const char *, linenoiseCompletions *);
5+void linenoiseHintsStub(const char *, int *color, int *bold);
6+
7+
8+void linenoise_setup() {
9+ linenoiseSetCompletionCallback(linenoiseCompletionStub);
10+ linenoiseSetHintsCallback(linenoiseHintsStub);
11+}
src/linenoise.go+52−1
@@ -3,6 +3,10 @@ package main
3/*
3/*
4#include <stdlib.h>
4#include <stdlib.h>
5#include <linenoise.h>
5#include <linenoise.h>
6+
7+void linenoise_setup();
8+
9+
6*/
10*/
7import "C"
11import "C"
8
12
@@ -11,7 +15,45 @@ import (
11 "fmt"
15 "fmt"
12)
16)
13
17
18+type Completer func(line string) []string
19+type Hinter func(line string) string
20+
21+
22+var completer Completer
23+var hinter Hinter
24+
25+//export linenoiseCompletionStub
26+func linenoiseCompletionStub(input *C.char, completions *C.linenoiseCompletions) {
27+ if completer == nil {
28+ return
29+ }
30+ completionsSlice := completer(C.GoString(input))
31+ completionsLen := len(completionsSlice)
32+ completions.len = C.size_t(completionsLen)
33+
34+ if completionsLen > 0 {
35+ cvec := C.malloc(C.size_t(int(unsafe.Sizeof(*(**C.char)(nil))) * completionsLen))
36+ cvecSlice := (*(*[999999]*C.char)(cvec))[:completionsLen]
37+
38+ for i, str := range completionsSlice {
39+ cvecSlice[i] = C.CString(str)
40+ }
41+ completions.cvec = (**C.char)(cvec)
42+ }
43+}
44+
45+//export linenoiseHintsStub
46+func linenoiseHintsStub(input *C.char, color *C.int, bold *C.int) *C.char {
47+ if hinter == nil {
48+ return nil
49+ }
50+ *color = 37
51+ *bold = 0
52+ return C.CString(hinter(C.GoString(input)))
53+}
54+
14func Linenoise(prompt string) (string,error) {
55func Linenoise(prompt string) (string,error) {
56+ C.linenoise_setup()
15 cprompt := C.CString(prompt)
57 cprompt := C.CString(prompt)
16 defer C.free(unsafe.Pointer(cprompt))
58 defer C.free(unsafe.Pointer(cprompt))
17 cresult := C.linenoise(cprompt)
59 cresult := C.linenoise(cprompt)
@@ -27,4 +69,13 @@ func LinenoiseHistoryAdd(line string) {
27 data := C.CString(line)
69 data := C.CString(line)
28 defer C.free(unsafe.Pointer(data))
70 defer C.free(unsafe.Pointer(data))
29 C.linenoiseHistoryAdd(data)
71 C.linenoiseHistoryAdd(data)
30−}
72+}
73+
74+func LinenoiseSetCompleter(newCompleter Completer) {
75+ completer = newCompleter
76+}
77+
78+func LinenoiseSetHinter(newHinter Hinter) {
79+ hinter = newHinter
80+}
81+
src/main.go+16−1
@@ -3,6 +3,8 @@ package main
3import (
3import (
4 "fmt"
4 "fmt"
5 "flag"
5 "flag"
6+ "os"
7+ "strings"
6)
8)
7
9
8var ps1, ps2 string
10var ps1, ps2 string
@@ -14,8 +16,12 @@ func main() {
14 var quiet bool
16 var quiet bool
15 var exp string
17 var exp string
16
18
19+ defaultLangague := os.Args[0]
20+ if defaultLangague == "prybar" || strings.ContainsAny(defaultLangague,"./") {
21+ defaultLangague = "python2"
22+ }
17
23
18− flag.StringVar(&language, "l", "python2", "langauge")
24+ flag.StringVar(&language, "l", defaultLangague, "langauge")
19 flag.StringVar(&code, "c", "", "code to run")
25 flag.StringVar(&code, "c", "", "code to run")
20 flag.StringVar(&exp, "e", "", "expression to print")
26 flag.StringVar(&exp, "e", "", "expression to print")
21
27
@@ -29,6 +35,12 @@ func main() {
29
35
30 args := flag.Args()
36 args := flag.Args()
31
37
38+ switch language {
39+ case "python":
40+ language = "python3"
41+ case "javascript":
42+ language = "spidermonkey"
43+ }
32
44
33 lang := GetLanguage(language)
45 lang := GetLanguage(language)
34 if !quiet {
46 if !quiet {
@@ -46,6 +58,9 @@ func main() {
46 if interactive {
58 if interactive {
47 lang.REPL()
59 lang.REPL()
48 } else if ourInteractive {
60 } else if ourInteractive {
61+ LinenoiseSetCompleter(func(s string) []string {
62+ return []string { s+"A", s+"B", s+"B"}
63+ })
49 lang.InternalREPL()
64 lang.InternalREPL()
50 }
65 }
51
66