summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-04-16 18:36:56 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-04-16 18:36:56 -0700
commit566de7d4516c8c0d161a95dafcbb530601306538 (patch)
treec293e50d359d19444b22b56f80abf52cef269a76
parent59c4fe61bdbe56eb215e29535e89ad72c3a2ee4b (diff)
downloadtxr-566de7d4516c8c0d161a95dafcbb530601306538.tar.gz
txr-566de7d4516c8c0d161a95dafcbb530601306538.tar.bz2
txr-566de7d4516c8c0d161a95dafcbb530601306538.zip
streams: force-off indent mode.
The fourth indent mode indent-foff (force off) is introduced. * buf.c (buf_print): Turn on data mode indentation if the current mode is not indent-foff, rather than when it is indent-off. * lib.c (obj_print_impl): The unconditional set_indent_mode calls are replaced with test_neq_set_indent_mode so we only set the mode if it is not forced off. * stream.c (formatv): For the ! directive, turn on data mode identation is not indent-foff, rather than when it is indent-off. (put_string, put_char, width_check): Recognize ident-foff as indentation off. (test_neq_set_indent_mode): New function. (stream_init): Register test-neq-set-indent-mode function and indent-foff variable. * stream.h (indent_mode): New enum constant, indent_foff. (test_neq_set_indent_mode): Declared. * struct.c (struct_inst_print): Turn on data mode indentation if the current mode is not indent-foff, rather than when it is indent-off. * txr.1: Documented.
-rw-r--r--buf.c4
-rw-r--r--lib.c6
-rw-r--r--stream.c30
-rw-r--r--stream.h4
-rw-r--r--struct.c4
-rw-r--r--txr.177
6 files changed, 93 insertions, 32 deletions
diff --git a/buf.c b/buf.c
index 14b89a2a..5e5a5d66 100644
--- a/buf.c
+++ b/buf.c
@@ -634,8 +634,8 @@ val buf_print(val buf, val stream_in)
struct buf *b = buf_handle(buf, lit("buf-print"));
cnum len = c_num(b->len), count = 0;
mem_t *data = b->data;
- val save_mode = test_set_indent_mode(stream, num_fast(indent_off),
- num_fast(indent_data));
+ val save_mode = test_neq_set_indent_mode(stream, num_fast(indent_foff),
+ num_fast(indent_data));
val save_indent;
int fb = 0;
diff --git a/lib.c b/lib.c
index afd6e627..6108f0ff 100644
--- a/lib.c
+++ b/lib.c
@@ -11124,7 +11124,7 @@ val obj_print_impl(val obj, val out, val pretty, struct strm_ctx *ctx)
if (sym == lambda_s && consp(cdr(obj)) && symbolp(second(obj))) {
indent = one;
save_indent = inc_indent(out, indent);
- set_indent_mode(out, num_fast(indent_code));
+ test_neq_set_indent_mode(out, num_fast(indent_foff), num_fast(indent_code));
obj_print_impl(sym, out, pretty, ctx);
if (second(obj)) {
put_string(lit(" (. "), out);
@@ -11137,12 +11137,12 @@ val obj_print_impl(val obj, val out, val pretty, struct strm_ctx *ctx)
goto finish;
} else if (special_operator_p(sym) || macro_form_p(obj, nil)) {
indent = one;
- set_indent_mode(out, num_fast(indent_code));
+ test_neq_set_indent_mode(out, num_fast(indent_foff), num_fast(indent_code));
} else if (fboundp(sym)) {
obj_print_impl(sym, out, pretty, ctx);
indent = one;
save_indent = inc_indent(out, indent);
- set_indent_mode(out, num_fast(indent_code));
+ test_neq_set_indent_mode(out, num_fast(indent_foff), num_fast(indent_code));
iter = obj;
goto finish;
}
diff --git a/stream.c b/stream.c
index e32334eb..3faa57c4 100644
--- a/stream.c
+++ b/stream.c
@@ -3449,8 +3449,8 @@ val formatv(val stream_in, val fmtstr, struct args *al)
}
goto output_num;
case '!':
- save_mode = test_set_indent_mode(stream, num_fast(indent_off),
- num_fast(indent_data));
+ save_mode = test_neq_set_indent_mode(stream, num_fast(indent_foff),
+ num_fast(indent_data));
if (lt)
set_indent(stream, plus(save_indent, num(width)));
else
@@ -3558,7 +3558,7 @@ val put_string(val string, val stream_in)
const wchar_t *str = c_str(string), *p = str;
- if (s->indent_mode != indent_off) {
+ if (s->indent_mode != indent_off && s->indent_mode != indent_foff) {
while (*str)
put_char(chr(*str++), stream);
return t;
@@ -3602,7 +3602,9 @@ val put_char(val ch, val stream_in)
s->force_break = 0;
break;
case L'\t':
- if (s->column == 0 && s->indent_mode != indent_off) {
+ if (s->column == 0 && s->indent_mode != indent_off &&
+ s->indent_mode != indent_foff)
+ {
put_indent(stream, ops, s->indent_chars);
s->column = s->indent_chars;
}
@@ -3610,7 +3612,9 @@ val put_char(val ch, val stream_in)
s->column = (s->column + 1) | 7;
break;
default:
- if (s->column == 0 && s->indent_mode != indent_off) {
+ if (s->column == 0 && s->indent_mode != indent_off &&
+ s->indent_mode != indent_foff)
+ {
put_indent(stream, ops, s->indent_chars);
s->column = s->indent_chars;
}
@@ -3720,6 +3724,17 @@ val test_set_indent_mode(val stream, val compare, val mode)
return oldval;
}
+val test_neq_set_indent_mode(val stream, val compare, val mode)
+{
+ val self = lit("test-neq-set-indent-mode");
+ struct strm_base *s = coerce(struct strm_base *,
+ cobj_handle(self, stream, stream_s));
+ val oldval = num_fast(s->indent_mode);
+ if (oldval != compare)
+ s->indent_mode = convert(enum indent_mode, c_num(mode));
+ return oldval;
+}
+
val set_indent_mode(val stream, val mode)
{
val self = lit("set-indent-mode");
@@ -3773,7 +3788,8 @@ val width_check(val stream, val alt)
s->column >= s->indent_chars + s->code_width) ||
(s->indent_mode == indent_data &&
s->column >= s->indent_chars + s->data_width) ||
- (s->indent_mode != indent_off && s->force_break))
+ (s->indent_mode != indent_off &&
+ s->indent_mode != indent_foff && s->force_break))
{
put_char(chr('\n'), stream);
s->force_break = 0;
@@ -4679,6 +4695,7 @@ void stream_init(void)
reg_varl(intern(lit("path-sep-chars"), user_package), static_str(path_sep_chars));
reg_fun(intern(lit("get-indent-mode"), user_package), func_n1(get_indent_mode));
reg_fun(intern(lit("test-set-indent-mode"), user_package), func_n3(test_set_indent_mode));
+ reg_fun(intern(lit("test-neq-set-indent-mode"), user_package), func_n3(test_neq_set_indent_mode));
reg_fun(intern(lit("set-indent-mode"), user_package), func_n2(set_indent_mode));
reg_fun(intern(lit("get-indent"), user_package), func_n1(get_indent));
reg_fun(intern(lit("set-indent"), user_package), func_n2(set_indent));
@@ -4688,6 +4705,7 @@ void stream_init(void)
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));
+ reg_varl(intern(lit("indent-foff"), user_package), num_fast(indent_foff));
#if HAVE_SOCKETS
uw_register_subtype(socket_error_s, error_s);
diff --git a/stream.h b/stream.h
index 37ab89a9..a7895064 100644
--- a/stream.h
+++ b/stream.h
@@ -34,7 +34,8 @@ enum strm_whence {
enum indent_mode {
indent_off,
indent_data,
- indent_code
+ indent_code,
+ indent_foff
};
struct strm_ctx {
@@ -205,6 +206,7 @@ val seek_stream(val stream, val offset, val whence);
val truncate_stream(val stream, val len);
val get_indent_mode(val stream);
val test_set_indent_mode(val stream, val compare, val mode);
+val test_neq_set_indent_mode(val stream, val compare, val mode);
val set_indent_mode(val stream, val mode);
val get_indent(val stream);
val set_indent(val stream, val indent);
diff --git a/struct.c b/struct.c
index 6de9044f..494ae025 100644
--- a/struct.c
+++ b/struct.c
@@ -1445,8 +1445,8 @@ static void struct_inst_print(val obj, val out, val pretty,
{
struct struct_inst *si = coerce(struct struct_inst *, obj->co.handle);
struct struct_type *st = si->type;
- val save_mode = test_set_indent_mode(out, num_fast(indent_off),
- num_fast(indent_data));
+ val save_mode = test_neq_set_indent_mode(out, num_fast(indent_foff),
+ num_fast(indent_data));
val save_indent, iter, once;
int force_br = 0;
int compat = opt_compat && opt_compat <= 154;
diff --git a/txr.1 b/txr.1
index 2a9afa9b..14e5ba62 100644
--- a/txr.1
+++ b/txr.1
@@ -46953,31 +46953,55 @@ function does not interact with indentation. The column position tracking
will be incorrect if byte and character output are mixed, affecting
the placement of indentation.
-Indentation mode takes on three numeric values, given by the three
+Indentation mode takes on four numeric values, given by the four
variables
.codn indent-off ,
.codn indent-data ,
+.code indent-code
and
-.codn indent-code .
-As far as stream output is concerned, the code and data modes behave
+.codn indent-foff .
+As far as stream output is concerned, the code and data modes
+represented by
+.code indent-code
+and
+.code indent-data
+behave
the same way: both represent the "indentation turned on" state.
The difference between them influences the behavior of the
.code width-check
-function. This function isn't used by any stream output routines.
-It is used by the object printing functions like
+function. This function isn't used by any lower-level stream output
+routines. It is used by the object printing functions like
.code print
and
.code pprint
to break up long lines.
+The
+.code indent-off
+and
+.code intent-foff
+modes are also treated the same way by lower level stream output,
+indicating "indentation turned off". The modes are distinguished
+by
+.code print
+and
+.code pprint
+in the following way:
+.code indent-off
+is a "soft" disable which allows these object-printing routines
+to temporarily turn on indentation while traversing aggregate objects.
+Whereas the
+.code indent-foff
+("force off") value is a "hard" disable: the object-printing routines will not
+enable indentation and will not break up long lines.
-.coNP Variables @, indent-off @ indent-data and @ indent-code
+.coNP Variables @, indent-off @, indent-data @ indent-code and @ indent-foff
.desc
These variables hold integer values representing output stream
indentation modes. The value of
.code indent-off
is zero.
-.coNP Functions @, get-indent-mode @ set-indent-mode and @ test-set-indent-mode
+.coNP Functions @ get-indent-mode and @ set-indent-mode
.synb
.mets (get-indent-mode << stream )
.mets (set-indent-mode < stream << new-mode )
@@ -46989,7 +47013,6 @@ The
.code get-indent-mode
retrieves the current indent mode of
.metn stream .
-
The
.code set-indent-mode
function sets the indent mode of
@@ -46998,6 +47021,23 @@ to
.meta new-mode
and returns the previous mode.
+Note: it is encouraged to save and restore the indentation mode,
+and in a way that is exception safe.
+If a block of code sets up indentation on a stream such as
+.code *stdout*
+and is terminated by an exception, the indentation will remain in
+effect and affect subsequent output. The
+.code with-resources
+macro or
+.code unwind-protect
+operator may be used.
+
+.coNP Functions @ test-set-indent-mode and @ test-neq-set-indent-mode
+.synb
+.mets (test-set-indent-mode < stream < compare-mode << new-mode )
+.mets (test-neq-set-indent-mode < stream < compare-mode << new-mode )
+.syne
+.desc
The
.code test-set-indent-mode
function sets the indent mode of
@@ -47009,16 +47049,17 @@ its current mode is equal to
.metn compare-mode .
Whether or not it changes the mode, it returns the previous mode.
-Note: it is encouraged to save and restore the indentation mode,
-and in a way that is exception safe.
-If a block of code sets up indentation on a stream such as
-.code *stdout*
-and is terminated by an exception, the indentation will remain in
-effect and affect subsequent output. The
-.code with-resources
-macro or
-.code unwind-protect
-operator may be used.
+The
+.code test-neq-set-indent-mode
+only differs in that it sets
+.meta stream
+to
+.meta new-mode
+if, and only if,
+the current mode is
+.B not
+equal to
+.metn compare-mode .
.coNP Functions @, get-indent @ set-indent and @ inc-indent
.synb