summaryrefslogtreecommitdiffstats
path: root/parser.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-09-05 08:19:43 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-09-05 08:19:43 -0700
commit7007754f037dd1d6ef4f9cfd636ef91016809737 (patch)
tree7ce814df93acd143ccbd4ad66f87ce33d244f0ca /parser.c
parentedbb612c40e3541a170aeaaf41ad8703c8b70cf9 (diff)
downloadtxr-7007754f037dd1d6ef4f9cfd636ef91016809737.tar.gz
txr-7007754f037dd1d6ef4f9cfd636ef91016809737.tar.bz2
txr-7007754f037dd1d6ef4f9cfd636ef91016809737.zip
Basic REPL based on linenoise.
* Makefile (OBJS): Only include linenoise.o if have_termios is y. * configure: Adding test for termios. (have_termios): New configure and config.make variable. (gen_config_make): Generate have_termios variable. * parser.c (repl): New function. * parser.h (repl): Declared. * txr.c (help): Summarize new -i option. (txr_main): Implement -i repl.
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/parser.c b/parser.c
index 1490a3de..00b3ab2e 100644
--- a/parser.c
+++ b/parser.c
@@ -29,6 +29,7 @@
#include <limits.h>
#include <dirent.h>
#include <stdlib.h>
+#include <string.h>
#include <stdarg.h>
#include <setjmp.h>
#include <wchar.h>
@@ -47,6 +48,9 @@
#include "stream.h"
#include "y.tab.h"
#include "parser.h"
+#if HAVE_TERMIOS
+#include "linenoise/linenoise.h"
+#endif
val parser_s, unique_s;
@@ -332,6 +336,84 @@ val read_eval_stream(val stream, val error_stream, val hash_bang_support)
return t;
}
+#if HAVE_TERMIOS
+
+val repl(val bindings, val in_stream, val out_stream)
+{
+ val ifd = stream_get_prop(in_stream, fd_k);
+ val ofd = stream_get_prop(out_stream, fd_k);
+ lino_t *ls = lino_make(c_num(ifd), c_num(ofd));
+ char *line_u8 = 0;
+ char *prompt_u8 = 0;
+ val repl_env = make_env(bindings, nil, nil);
+ val quit_k = intern(lit("quit"), keyword_package);
+ val catch_all = list(t, nao);
+ val done = nil;
+ val counter = one;
+
+ while (!done) {
+ val prompt = format(nil, lit("~a> "), counter, nao);
+ char *prompt_u8 = utf8_dup_to(c_str(prompt));
+
+ line_u8 = linenoise(ls, prompt_u8);
+ free (prompt_u8);
+ prompt_u8 = 0;
+
+ if (line_u8 == 0)
+ break;
+
+ if (strspn(line_u8, " \t") == strlen(line_u8))
+ continue;
+
+ counter = succ(counter);
+
+ uw_catch_begin (catch_all, exsym, exvals);
+
+ {
+ val line = string_utf8(line_u8);
+ val form = lisp_parse(line, out_stream, colon_k, colon_k);
+ val value = eval_intrinsic(form, repl_env);
+ if (value == quit_k) {
+ done = t;
+ } else {
+ prinl(value, out_stream);
+ lino_hist_add(ls, line_u8); /* Add to the history. */
+ }
+ }
+
+ uw_catch (exsym, exvals) {
+ if (uw_exception_subtype_p(exsym, error_s)) {
+ obj_pprint(car(exvals), out_stream);
+ if (cdr(exvals)) {
+ put_string(lit(" "), out_stream);
+ pprinl(cdr(exvals), out_stream);
+ } else {
+ put_line(nil, nil);
+ }
+ } else {
+ format(out_stream, lit("caught exception: ~s ~s\n"),
+ exsym, exvals, nao);
+ }
+ }
+
+ uw_unwind {
+ free(line_u8);
+ line_u8 = 0;
+ }
+
+ uw_catch_end;
+
+ gc_hint(prompt);
+ }
+
+ free(prompt_u8);
+ free(line_u8);
+ lino_free(ls);
+ return nil;
+}
+
+#endif
+
val get_parser(val stream)
{
return gethash(stream_parser_hash, stream);