summaryrefslogtreecommitdiffstats
path: root/stream.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-04-05 06:53:24 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-04-05 06:53:24 -0700
commite69a99cc4c183a98dd380fdaf47a5a1dcb5d68a0 (patch)
tree8dceea3e5455d6c8e711cbdfc78525bc87257fc6 /stream.c
parent34efdb8b2e45eb6543a8fbaadf8867ee58870677 (diff)
downloadtxr-e69a99cc4c183a98dd380fdaf47a5a1dcb5d68a0.tar.gz
txr-e69a99cc4c183a98dd380fdaf47a5a1dcb5d68a0.tar.bz2
txr-e69a99cc4c183a98dd380fdaf47a5a1dcb5d68a0.zip
printer: improve object formatting.
There is an issue with the printer in that it produces output whereby objects continue on the same line after a multi-line object, e.g: (foo (foobly bar xyzzy quux) (oops same line)) rather than: (foo (foobly bar xyzzy quux) (oops same line)) There is a simple fix for this: set a flag to force a line break on the next width-check operation whenever an object has been broken into multiple lines. width-check can return a Boolean indication whether it generated a line break, and so aggregate object printing routines can tell whether their object has been broken into lines, and set the flag. * stream.h (struct strm_base): New member, force_break. (force_break): Declared. * stream.c (strm_base_init): Extent initializer to cover force_break flag. (put_string, put_char): Clear the force_break flag whenever we hit column zero. (width_check): If indent mode is on, and force_break is true, generate a break. Clear force_break. (force_break): New function. (stream_init): Register force-break intrinsic. * buf.c (buf_print): Set the force break flag if the buffer was broken into multiple lines. * hash.c (hash_print_op): Set the force break flag if the hash was broken into multiple lines. * lib.c (obj_print_impl): Same logic for lists. * struct.c (struct_inst_print): Same logic for structs. * tests/009/json.expected, tests/011/macros-2.expected, tests/012/struct.tl, tests/017/glob-zarray.expected: Update expected textual output to reflect new formatting.
Diffstat (limited to 'stream.c')
-rw-r--r--stream.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/stream.c b/stream.c
index 56563c0c..3887e77f 100644
--- a/stream.c
+++ b/stream.c
@@ -103,7 +103,7 @@ val shell, shell_arg;
void strm_base_init(struct strm_base *s)
{
- static struct strm_base init = { indent_off, 60, 10, 0, 0, 0 };
+ static struct strm_base init = { indent_off, 60, 10, 0, 0, 0, 0 };
*s = init;
}
@@ -3512,6 +3512,7 @@ val put_string(val string, val stream_in)
switch (*p) {
case '\n':
col = 0;
+ s->force_break = 0;
break;
case '\t':
col = (col + 1) | 7;
@@ -3540,6 +3541,7 @@ val put_char(val ch, val stream_in)
case L'\n':
ops->put_char(stream, ch);
s->column = 0;
+ s->force_break = 0;
break;
case L'\t':
if (s->column == 0 && s->indent_mode != indent_off) {
@@ -3697,14 +3699,25 @@ val width_check(val stream, val alt)
if ((s->indent_mode == indent_code &&
s->column >= s->indent_chars + s->code_width) ||
(s->indent_mode == indent_data &&
- s->column >= s->indent_chars + s->data_width))
+ s->column >= s->indent_chars + s->data_width) ||
+ (s->indent_mode != indent_off && s->force_break))
{
put_char(chr('\n'), stream);
+ s->force_break = 0;
+ return t;
} else if (alt) {
put_char(alt, stream);
}
- return t;
+ return nil;
+}
+
+val force_break(val stream)
+{
+ struct strm_base *s = coerce(struct strm_base *,
+ cobj_handle(stream, stream_s));
+ s->force_break = 1;
+ return stream;
}
struct strm_ctx *get_set_ctx(val stream, struct strm_ctx *ctx)
@@ -4596,6 +4609,7 @@ void stream_init(void)
reg_fun(intern(lit("set-indent"), user_package), func_n2(set_indent));
reg_fun(intern(lit("inc-indent"), user_package), func_n2(inc_indent));
reg_fun(intern(lit("width-check"), user_package), func_n2(width_check));
+ reg_fun(intern(lit("force-break"), user_package), func_n1(force_break));
reg_varl(intern(lit("indent-off"), user_package), num_fast(indent_off));
reg_varl(intern(lit("indent-data"), user_package), num_fast(indent_data));
reg_varl(intern(lit("indent-code"), user_package), num_fast(indent_code));