diff options
| author | Joel Martin <github@martintribe.org> | 2014-10-09 18:27:47 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-10-09 18:27:47 -0500 |
| commit | ad7e866ea1d4d035d876e58bca681a72099449af (patch) | |
| tree | cbd73a7cda5adc4aba7293231ab0efa3f107edb0 | |
| parent | d667a1bb2e7294f8722bb31f1e6e8207b971c913 (diff) | |
| download | mal-ad7e866ea1d4d035d876e58bca681a72099449af.tar.gz mal-ad7e866ea1d4d035d876e58bca681a72099449af.zip | |
go: add readline.go that wraps libreadline/libedit
| -rw-r--r-- | go/Makefile | 3 | ||||
| -rw-r--r-- | go/src/core/core.go | 3 | ||||
| -rw-r--r-- | go/src/readline/readline.go | 70 | ||||
| -rw-r--r-- | go/src/step0_repl/step0_repl.go | 10 | ||||
| -rw-r--r-- | go/src/step1_read_print/step1_read_print.go | 8 | ||||
| -rw-r--r-- | go/src/step2_eval/step2_eval.go | 8 | ||||
| -rw-r--r-- | go/src/step3_env/step3_env.go | 8 | ||||
| -rw-r--r-- | go/src/step4_if_fn_do/step4_if_fn_do.go | 8 | ||||
| -rw-r--r-- | go/src/step5_tco/step5_tco.go | 8 | ||||
| -rw-r--r-- | go/src/step6_file/step6_file.go | 9 | ||||
| -rw-r--r-- | go/src/step7_quote/step7_quote.go | 9 | ||||
| -rw-r--r-- | go/src/step8_macros/step8_macros.go | 9 | ||||
| -rw-r--r-- | go/src/stepA_more/stepA_more.go | 9 |
13 files changed, 102 insertions, 60 deletions
diff --git a/go/Makefile b/go/Makefile index 729d2cc..18faa4f 100644 --- a/go/Makefile +++ b/go/Makefile @@ -2,7 +2,8 @@ export GOPATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) ##################### -SOURCES_BASE = src/types/types.go src/reader/reader.go src/printer/printer.go \ +SOURCES_BASE = src/types/types.go src/readline/readline.go \ + src/reader/reader.go src/printer/printer.go \ src/env/env.go src/core/core.go SOURCES_LISP = src/stepA_more/stepA_more.go SOURCES = $(SOURCES_BASE) $(SOURCES_LISP) diff --git a/go/src/core/core.go b/go/src/core/core.go index b3961e1..cd63930 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -10,6 +10,7 @@ import ( . "types" "reader" "printer" + "readline" ) // Errors/Exceptions @@ -150,6 +151,8 @@ var NS = map[string]MalType{ "read-string": func(a []MalType) (MalType, error) { return reader.Read_str(a[0].(string)) }, "slurp": slurp, + "readline": func(a []MalType) (MalType, error) { + return readline.Readline(a[0].(string)) }, "<": func(a []MalType) (MalType, error) { return a[0].(int) < a[1].(int), nil }, diff --git a/go/src/readline/readline.go b/go/src/readline/readline.go new file mode 100644 index 0000000..2777cb4 --- /dev/null +++ b/go/src/readline/readline.go @@ -0,0 +1,70 @@ +package readline + +/* +// IMPORTANT: choose one +#cgo LDFLAGS: -ledit +//#cgo LDFLAGS: -lreadline // NOTE: libreadline is GPL + +// free() +#include <stdlib.h> +// readline() +#include <readline/readline.h> +// add_history() +#include <readline/history.h> +*/ +import "C" + +import ( + "errors" + "unsafe" + "strings" + "io/ioutil" + "os" + "path/filepath" + "fmt" +) + +var HISTORY_FILE = ".mal-history" + +var rl_history_loaded = false + +func Readline(prompt string) (string, error) { + history_path := filepath.Join(os.Getenv("HOME"), "/", HISTORY_FILE) + + if !rl_history_loaded { + rl_history_loaded = true + content, e := ioutil.ReadFile(history_path) + if e != nil { return "", e } + + for _, add_line := range strings.Split(string(content), "\n") { + if add_line == "" { continue } + c_add_line := C.CString(add_line) + C.add_history(c_add_line) + C.free(unsafe.Pointer(c_add_line)) + } + } + + + c_prompt := C.CString(prompt) + defer C.free(unsafe.Pointer(c_prompt)) + + c_line := C.readline(c_prompt) + defer C.free(unsafe.Pointer(c_line)) + line := C.GoString(c_line) + + if c_line == nil { + return "", errors.New("C.readline call failed") + } + C.add_history(c_line) + + // append to file + f, e := os.OpenFile(history_path, os.O_APPEND|os.O_WRONLY, 0600) + if e == nil { + defer f.Close() + + _, e = f.WriteString(line+"\n") + if e != nil { fmt.Printf("error writing to history") } + } + + return line, nil +} diff --git a/go/src/step0_repl/step0_repl.go b/go/src/step0_repl/step0_repl.go index 1203213..2e4c47c 100644 --- a/go/src/step0_repl/step0_repl.go +++ b/go/src/step0_repl/step0_repl.go @@ -1,12 +1,14 @@ package main import ( - "bufio" "fmt" - "os" "strings" ) +import ( + "readline" +) + // read func READ(str string) string { return str @@ -28,11 +30,9 @@ func rep(str string) string { } func main() { - reader := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := reader.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/step1_read_print/step1_read_print.go b/go/src/step1_read_print/step1_read_print.go index edd8c42..e008ed5 100644 --- a/go/src/step1_read_print/step1_read_print.go +++ b/go/src/step1_read_print/step1_read_print.go @@ -1,14 +1,12 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" ) import ( + "readline" . "types" "reader" "printer" @@ -41,11 +39,9 @@ func rep(str string) (MalType, error) { } func main() { - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/step2_eval/step2_eval.go b/go/src/step2_eval/step2_eval.go index 3ab35ed..9b3aa28 100644 --- a/go/src/step2_eval/step2_eval.go +++ b/go/src/step2_eval/step2_eval.go @@ -1,15 +1,13 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" "errors" ) import ( + "readline" . "types" "reader" "printer" @@ -110,11 +108,9 @@ func rep(str string) (MalType, error) { } func main() { - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/step3_env/step3_env.go b/go/src/step3_env/step3_env.go index 68a8f0c..7e45a39 100644 --- a/go/src/step3_env/step3_env.go +++ b/go/src/step3_env/step3_env.go @@ -1,15 +1,13 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" "errors" ) import ( + "readline" . "types" "reader" "printer" @@ -138,11 +136,9 @@ func main() { repl_env.Set("/", func(a []MalType) (MalType, error) { return a[0].(int) / a[1].(int), nil }) - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/step4_if_fn_do/step4_if_fn_do.go b/go/src/step4_if_fn_do/step4_if_fn_do.go index 7a91a2b..760919b 100644 --- a/go/src/step4_if_fn_do/step4_if_fn_do.go +++ b/go/src/step4_if_fn_do/step4_if_fn_do.go @@ -1,15 +1,13 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" "errors" ) import ( + "readline" . "types" "reader" "printer" @@ -162,11 +160,9 @@ func main() { // core.mal: defined using the language itself rep("(def! not (fn* (a) (if a false true)))") - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/step5_tco/step5_tco.go b/go/src/step5_tco/step5_tco.go index a15d9e5..c7c2ab5 100644 --- a/go/src/step5_tco/step5_tco.go +++ b/go/src/step5_tco/step5_tco.go @@ -1,15 +1,13 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" "errors" ) import ( + "readline" . "types" "reader" "printer" @@ -172,11 +170,9 @@ func main() { // core.mal: defined using the language itself rep("(def! not (fn* (a) (if a false true)))") - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/step6_file/step6_file.go b/go/src/step6_file/step6_file.go index 205b597..056fe39 100644 --- a/go/src/step6_file/step6_file.go +++ b/go/src/step6_file/step6_file.go @@ -1,15 +1,14 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" "errors" + "os" ) import ( + "readline" . "types" "reader" "printer" @@ -187,11 +186,9 @@ func main() { os.Exit(0) } - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/step7_quote/step7_quote.go b/go/src/step7_quote/step7_quote.go index 4083354..68c2a85 100644 --- a/go/src/step7_quote/step7_quote.go +++ b/go/src/step7_quote/step7_quote.go @@ -1,15 +1,14 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" "errors" + "os" ) import ( + "readline" . "types" "reader" "printer" @@ -220,11 +219,9 @@ func main() { os.Exit(0) } - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/step8_macros/step8_macros.go b/go/src/step8_macros/step8_macros.go index 6735275..82572d3 100644 --- a/go/src/step8_macros/step8_macros.go +++ b/go/src/step8_macros/step8_macros.go @@ -1,15 +1,14 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" "errors" + "os" ) import ( + "readline" . "types" "reader" "printer" @@ -259,11 +258,9 @@ func main() { os.Exit(0) } - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return diff --git a/go/src/stepA_more/stepA_more.go b/go/src/stepA_more/stepA_more.go index 2532cfe..be693f6 100644 --- a/go/src/stepA_more/stepA_more.go +++ b/go/src/stepA_more/stepA_more.go @@ -1,15 +1,14 @@ package main import ( - "bufio" - //"io" "fmt" - "os" "strings" "errors" + "os" ) import ( + "readline" . "types" "reader" "printer" @@ -281,11 +280,9 @@ func main() { os.Exit(0) } - rdr := bufio.NewReader(os.Stdin); // repl loop for { - fmt.Print("user> "); - text, err := rdr.ReadString('\n'); + text, err := readline.Readline("user> ") text = strings.TrimRight(text, "\n"); if (err != nil) { return |
