diff --git a/janet.1 b/janet.1 index f29dadab..2bf5ef1c 100644 --- a/janet.1 +++ b/janet.1 @@ -3,7 +3,7 @@ janet \- run the Janet language abstract machine .SH SYNOPSIS .B janet -[\fB\-hvsrpq\fR] +[\fB\-hvsrpnq\fR] [\fB\-e\fR \fISOURCE\fR] [\fB\-l\fR \fIMODULE\fR] [\fB\-m\fR \fIPATH\fR] @@ -48,6 +48,10 @@ Read raw input from stdin and forgo prompt history and other readline-like featu Execute a string of Janet source. Source code is executed in the order it is encountered, so earlier arguments are executed before later ones. +.TP +.BR \-n +Disable ANSI colors in the repl. Has no effect if no repl is run. + .TP .BR \-r Open a REPL (Read Eval Print Loop) after executing all sources. By default, if Janet is called with no diff --git a/src/boot/boot.janet b/src/boot/boot.janet index fb526e90..1f942dbe 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -1708,14 +1708,16 @@ "Run a repl. The first parameter is an optional function to call to get a chunk of source code that should return nil for end of file. The second parameter is a function that is called when a signal is - caught." - [&opt chunks onsignal] + caught. fmt is a format string used to print results, and defaults to + \"%.20P\"" + [&opt chunks onsignal fmt] (def newenv (make-env)) + (default fmt "%.20P") (default onsignal (fn [f x] (case (fiber/status f) :dead (do (put newenv '_ @{:value x}) - (print (buffer/format @"" "%.20p" x))) + (print (buffer/format @"" fmt x))) (debug/stacktrace f x)))) (run-context {:env newenv :chunks chunks diff --git a/src/core/pp.c b/src/core/pp.c index 44791d51..4e42b20c 100644 --- a/src/core/pp.c +++ b/src/core/pp.c @@ -297,6 +297,7 @@ struct pretty { JanetBuffer *buffer; int depth; int indent; + int flags; JanetTable seen; }; @@ -312,6 +313,26 @@ static void print_newline(struct pretty *S, int just_a_space) { } } +/* Color coding for types */ +static const char *janet_pretty_colors[] = { + "\x1B[32m", + "\x1B[36m", + "\x1B[36m", + NULL, + "\x1B[35m", + "\x1B[34m", + "\x1B[33m", + NULL, + NULL, + NULL, + NULL, + "\x1B[35m", + NULL, + NULL, + NULL, + NULL +}; + /* Helper for pretty printing */ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) { /* Add to seen */ @@ -336,9 +357,17 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) { } switch (janet_type(x)) { - default: + default: { + const char *color = janet_pretty_colors[janet_type(x)]; + if (color && (S->flags & JANET_PRETTY_COLOR)) { + janet_buffer_push_cstring(S->buffer, color); + } janet_description_b(S->buffer, x); + if (color && (S->flags & JANET_PRETTY_COLOR)) { + janet_buffer_push_cstring(S->buffer, "\x1B[0m"); + } break; + } case JANET_ARRAY: case JANET_TUPLE: { int32_t i = 0, len = 0; @@ -424,7 +453,7 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) { /* Helper for printing a janet value in a pretty form. Not meant to be used * for serialization or anything like that. */ -JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, Janet x) { +JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, Janet x) { struct pretty S; if (NULL == buffer) { buffer = janet_buffer(0); @@ -432,6 +461,7 @@ JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, Janet x) { S.buffer = buffer; S.depth = depth; S.indent = 0; + S.flags = flags; janet_table_init(&S.seen, 10); janet_pretty_one(&S, x, 0); janet_table_deinit(&S.seen); @@ -515,7 +545,12 @@ void janet_formatb(JanetBuffer *bufp, const char *format, va_list args) { break; } case 'p': { - janet_pretty(bufp, 4, va_arg(args, Janet)); + janet_pretty(bufp, 4, 0, va_arg(args, Janet)); + break; + } + case 'P': { + janet_pretty(bufp, 4, JANET_PRETTY_COLOR, va_arg(args, Janet)); + break; } } } @@ -646,8 +681,7 @@ void janet_buffer_format( if (l != (int32_t) strlen((const char *) s)) janet_panic("string contains zeros"); if (!strchr(form, '.') && l >= 100) { - janet_panic - ("no precision and string is too long to be formatted"); + janet_panic("no precision and string is too long to be formatted"); } else { nb = snprintf(item, MAX_ITEM, form, s); } @@ -662,11 +696,12 @@ void janet_buffer_format( janet_description_b(b, argv[arg]); break; } + case 'P': case 'p': { /* janet pretty , precision = depth */ int depth = atoi(precision); if (depth < 1) depth = 4; - janet_pretty(b, depth, argv[arg]); + janet_pretty(b, depth, (strfrmt[-1] == 'P') ? JANET_PRETTY_COLOR : 0, argv[arg]); break; } default: { diff --git a/src/include/janet.h b/src/include/janet.h index 088d1b14..48cd96ea 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1200,12 +1200,15 @@ JANET_API JanetFuncDef *janet_funcdef_alloc(void); JANET_API JanetFunction *janet_thunk(JanetFuncDef *def); JANET_API int janet_verify(JanetFuncDef *def); +/* Pretty printing */ +#define JANET_PRETTY_COLOR 1 +JANET_API JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, Janet x); + /* Misc */ JANET_API int janet_equals(Janet x, Janet y); JANET_API int32_t janet_hash(Janet x); JANET_API int janet_compare(Janet x, Janet y); JANET_API int janet_cstrcmp(const uint8_t *str, const char *other); -JANET_API JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, Janet x); JANET_API Janet janet_get(Janet ds, Janet key); JANET_API Janet janet_getindex(Janet ds, int32_t index); JANET_API int32_t janet_length(Janet x); diff --git a/src/mainclient/init.janet b/src/mainclient/init.janet index 8acf85ce..0eed4730 100644 --- a/src/mainclient/init.janet +++ b/src/mainclient/init.janet @@ -8,6 +8,7 @@ (var *raw-stdin* false) (var *handleopts* true) (var *exit-on-error* true) + (var *colorize* true) (if-let [jp (os/getenv "JANET_PATH")] (set module/*syspath* jp)) @@ -26,6 +27,7 @@ -q : Hide prompt, logo, and repl output (quiet) -m syspath : Set system path for loading global modules -c source output : Compile janet source code into an image + -n : Disable ANSI color output in the repl -l path : Execute code in a file before running the main script -- : Stop handling options`) (os/exit 0) @@ -35,6 +37,7 @@ "r" (fn [&] (set *should-repl* true) 1) "p" (fn [&] (set *exit-on-error* false) 1) "q" (fn [&] (set *quiet* true) 1) + "n" (fn [&] (set *colorize* false) 1) "m" (fn [i &] (set module/*syspath* (get process/args (+ i 1))) 2) "c" (fn [i &] (def e (require (get process/args (+ i 1)))) @@ -83,4 +86,4 @@ (defn getchunk [buf p] (getter (prompter p) buf)) (def onsig (if *quiet* (fn [x &] x) nil)) - (repl getchunk onsig))) + (repl getchunk onsig (if *colorize* "%.20P" "%.20p"))))