summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-12-28 06:44:58 -0800
committerKaz Kylheku <kaz@kylheku.com>2015-12-28 06:44:58 -0800
commit92dd3486727d748253b8b1a0dd4416c07e61addb (patch)
tree2d46d0f93e777d457990c5296d659f68280378eb
parentd2488974756c21c064ddd293fbb72d5a85b91e12 (diff)
downloadtxr-92dd3486727d748253b8b1a0dd4416c07e61addb.tar.gz
txr-92dd3486727d748253b8b1a0dd4416c07e61addb.tar.bz2
txr-92dd3486727d748253b8b1a0dd4416c07e61addb.zip
Overhaul printing of lazy strings.
The #<lazy-string ...> print syntax is gone. Lazy strings are now printed by traversing their structure, without forcing them to the flat representation. * lib.c (lazy_str_put): New function. (out_str_char, out_str_pretty, out_lazy_str): New static functions. (obj_print_impl): Use out_str_pretty for standard-printing regular strings. Use lazy_put_str for pretty-printing lazy strings, and out_lazy_str for standard-printing them. * lib.h (lazy_str_put): Declared. * stream.c (put_string): Check for a lazy string and route to lazy_str_put, so the string doesn't get forced (though of course the underlying list does, if it is lazy).
-rw-r--r--lib.c121
-rw-r--r--lib.h1
-rw-r--r--stream.c57
3 files changed, 123 insertions, 56 deletions
diff --git a/lib.c b/lib.c
index 75c77827..6933d159 100644
--- a/lib.c
+++ b/lib.c
@@ -6148,6 +6148,28 @@ val lazy_str_force(val lstr)
return lstr->ls.prefix;
}
+val lazy_str_put(val lstr, val stream)
+{
+ val lim, term, iter;
+ type_check(lstr, LSTR);
+ lim = cdr(lstr->ls.opts);
+ term = car(lstr->ls.opts);
+
+ put_string(lstr->ls.prefix, stream);
+
+ for (iter = lstr->ls.list; (!lim || gt(lim, zero)) && iter;
+ iter = cdr(iter))
+ {
+ val str = car(iter);
+ if (!str)
+ break;
+ put_string(str, stream);
+ put_string(term, stream);
+ }
+
+ return t;
+}
+
val lazy_str_force_upto(val lstr, val index)
{
uses_or2;
@@ -8155,6 +8177,68 @@ static val simple_qref_args_p(val args, val pos)
}
}
+static void out_str_char(wchar_t ch, val out, int *semi_flag)
+{
+ if (*semi_flag && iswxdigit(ch))
+ put_char(chr(';'), out);
+
+ *semi_flag = 0;
+
+ switch (ch) {
+ case '\a': put_string(lit("\\a"), out); break;
+ case '\b': put_string(lit("\\b"), out); break;
+ case '\t': put_string(lit("\\t"), out); break;
+ case '\n': put_string(lit("\\n"), out); break;
+ case '\v': put_string(lit("\\v"), out); break;
+ case '\f': put_string(lit("\\f"), out); break;
+ case '\r': put_string(lit("\\r"), out); break;
+ case '"': put_string(lit("\\\""), out); break;
+ case '\\': put_string(lit("\\\\"), out); break;
+ case 27: put_string(lit("\\e"), out); break;
+ default:
+ if (ch >= ' ') {
+ put_char(chr(ch), out);
+ } else {
+ format(out, lit("\\x~,02X"), num(ch), nao);
+ *semi_flag = 1;
+ }
+ }
+}
+
+static void out_str_pretty(const wchar_t *ptr, val out, int *semi_flag)
+{
+ for (; *ptr; ptr++)
+ out_str_char(*ptr, out, semi_flag);
+}
+
+static void out_lazy_str(val lstr, val out)
+{
+ int semi_flag = 0;
+ val lim, term, iter;
+ const wchar_t *wcterm;
+
+ type_check(lstr, LSTR);
+ lim = cdr(lstr->ls.opts);
+ term = car(lstr->ls.opts);
+ wcterm = c_str(term);
+
+ put_char(chr('"'), out);
+
+ out_str_pretty(c_str(lstr->ls.prefix), out, &semi_flag);
+
+ for (iter = lstr->ls.list; (!lim || gt(lim, zero)) && iter;
+ iter = cdr(iter))
+ {
+ val str = car(iter);
+ if (!str)
+ break;
+ out_str_pretty(c_str(str), out, &semi_flag);
+ out_str_pretty(wcterm, out, &semi_flag);
+ }
+
+ put_char(chr('"'), out);
+}
+
val obj_print_impl(val obj, val out, val pretty)
{
val ret = obj;
@@ -8280,34 +8364,11 @@ finish:
if (pretty) {
put_string(obj, out);
} else {
- const wchar_t *ptr;
int semi_flag = 0;
put_char(chr('"'), out);
- for (ptr = c_str(obj); *ptr; ptr++) {
- if (semi_flag && iswxdigit(*ptr))
- put_char(chr(';'), out);
- semi_flag = 0;
- switch (*ptr) {
- case '\a': put_string(lit("\\a"), out); break;
- case '\b': put_string(lit("\\b"), out); break;
- case '\t': put_string(lit("\\t"), out); break;
- case '\n': put_string(lit("\\n"), out); break;
- case '\v': put_string(lit("\\v"), out); break;
- case '\f': put_string(lit("\\f"), out); break;
- case '\r': put_string(lit("\\r"), out); break;
- case '"': put_string(lit("\\\""), out); break;
- case '\\': put_string(lit("\\\\"), out); break;
- case 27: put_string(lit("\\e"), out); break;
- default:
- if (*ptr >= ' ') {
- put_char(chr(*ptr), out);
- } else {
- format(out, lit("\\x~,02X"), num(*ptr), nao);
- semi_flag = 1;
- }
- }
- }
+ out_str_pretty(c_str(obj), out, &semi_flag);
+
put_char(chr('"'), out);
}
break;
@@ -8407,11 +8468,11 @@ finish:
}
break;
case LSTR:
- if (obj->ls.list)
- format(out, lit("#<lazy-string: ~s (~s ...)>"), obj->ls.prefix,
- obj->ls.list, nao);
- else
- obj_print_impl(obj->ls.prefix, out, pretty);
+ if (pretty) {
+ lazy_str_put(obj, out);
+ } else {
+ out_lazy_str(obj, out);
+ }
break;
case COBJ:
obj->co.ops->print(obj, out, pretty);
diff --git a/lib.h b/lib.h
index 76274535..29984eb3 100644
--- a/lib.h
+++ b/lib.h
@@ -850,6 +850,7 @@ val lazy_stream_cons(val stream);
val lazy_str(val list, val term, val limit);
val lazy_str_force_upto(val lstr, val index);
val lazy_str_force(val lstr);
+val lazy_str_put(val lstr, val stream);
val lazy_str_get_trailing_list(val lstr, val index);
val length_str_gt(val str, val len);
val length_str_ge(val str, val len);
diff --git a/stream.c b/stream.c
index a1a41036..aadda39e 100644
--- a/stream.c
+++ b/stream.c
@@ -2638,36 +2638,41 @@ static val put_indent(val stream, struct strm_ops *ops, cnum chars)
val put_string(val string, val stream_in)
{
- val stream = default_arg(stream_in, std_output);
- struct strm_ops *ops = coerce(struct strm_ops *, cobj_ops(stream, stream_s));
- struct strm_base *s = coerce(struct strm_base *, stream->co.handle);
- cnum col = s->column;
- const wchar_t *str = c_str(string), *p = str;
+ if (lazy_stringp(string)) {
+ return lazy_str_put(string, stream_in);
+ } else {
+ val stream = default_arg(stream_in, std_output);
+ struct strm_ops *ops = coerce(struct strm_ops *, cobj_ops(stream, stream_s));
+ struct strm_base *s = coerce(struct strm_base *, stream->co.handle);
+ cnum col = s->column;
- if (s->indent_mode != indent_off) {
- while (*str)
- put_char(chr(*str++), stream);
- return t;
- }
+ const wchar_t *str = c_str(string), *p = str;
- for (; *p; p++) {
- switch (*p) {
- case '\n':
- col = 0;
- break;
- case '\t':
- col = (col + 1) | 7;
- break;
- default:
- if (!iswcntrl(*p))
- col += 1 + wide_display_char_p(*p);
- break;
+ if (s->indent_mode != indent_off) {
+ while (*str)
+ put_char(chr(*str++), stream);
+ return t;
}
- }
- ops->put_string(stream, string);
- s->column = col;
- return t;
+ for (; *p; p++) {
+ switch (*p) {
+ case '\n':
+ col = 0;
+ break;
+ case '\t':
+ col = (col + 1) | 7;
+ break;
+ default:
+ if (!iswcntrl(*p))
+ col += 1 + wide_display_char_p(*p);
+ break;
+ }
+ }
+
+ ops->put_string(stream, string);
+ s->column = col;
+ return t;
+ }
}
val put_char(val ch, val stream_in)