summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-08-04 20:29:12 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-08-04 20:29:12 -0700
commitc3b2ec8a4d4eb7419a748b939da7657e01aada99 (patch)
tree819afc8e577434b921c0c24cd4d0a1e6bd767d36
parentbfbad3fd2a3ba5af46e547c5e1f7cb72b25162a8 (diff)
downloadtxr-c3b2ec8a4d4eb7419a748b939da7657e01aada99.tar.gz
txr-c3b2ec8a4d4eb7419a748b939da7657e01aada99.tar.bz2
txr-c3b2ec8a4d4eb7419a748b939da7657e01aada99.zip
* stream.c (vformat): Implement ~! format directive for indentation.
Allow negative widths to be specified with a leading minus sign, so that we can indent to the left. * txr.1: Document ~! format directive.
-rw-r--r--ChangeLog8
-rw-r--r--stream.c44
-rw-r--r--txr.138
3 files changed, 80 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index be1a0682..fc47abd8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2015-08-04 Kaz Kylheku <kaz@kylheku.com>
+ * stream.c (vformat): Implement ~! format directive for indentation.
+ Allow negative widths to be specified with a leading minus sign,
+ so that we can indent to the left.
+
+ * txr.1: Document ~! format directive.
+
+2015-08-04 Kaz Kylheku <kaz@kylheku.com>
+
* stream.c (put_string, put_char): Do not put out the indentation
immediately after outputting a newline. Rather, delay the output of the
indentation until some output occurs at column zero.
diff --git a/stream.c b/stream.c
index 19c79619..c9f194a9 100644
--- a/stream.c
+++ b/stream.c
@@ -2104,7 +2104,10 @@ static void vformat_str(val stream, val str, int width, enum align align,
val vformat(val stream, val fmtstr, va_list vl)
{
- class_check(stream, stream_s);
+ val save_indent = get_indent(stream);
+ val save_mode = nil;
+
+ uw_simple_catch_begin;
prot1(&fmtstr);
@@ -2113,7 +2116,7 @@ val vformat(val stream, val fmtstr, va_list vl)
enum {
vf_init, vf_width, vf_digits, vf_star, vf_precision, vf_spec
} state = vf_init, saved_state = vf_init;
- int width = 0, precision = 0, precision_p = 0, digits = 0;
+ int width = 0, precision = 0, precision_p = 0, digits = 0, lt = 0, neg = 0;
enum align align = al_right;
int sign = 0, zeropad = 0;
cnum value;
@@ -2136,6 +2139,8 @@ val vformat(val stream, val fmtstr, va_list vl)
precision = 0;
precision_p = 0;
digits = 0;
+ lt = 0;
+ neg = 0;
continue;
default:
put_char(chr(ch), stream);
@@ -2149,6 +2154,7 @@ val vformat(val stream, val fmtstr, va_list vl)
state = vf_init;
continue;
case '<':
+ lt = 1;
align = al_left;
continue;
case '^':
@@ -2163,6 +2169,9 @@ val vformat(val stream, val fmtstr, va_list vl)
state = vf_digits;
digits = ch - '0';
continue;
+ case '-':
+ neg = 1;
+ continue;
case '*':
saved_state = state;
state = vf_star;
@@ -2215,6 +2224,8 @@ val vformat(val stream, val fmtstr, va_list vl)
} else {
width = digits;
}
+ if (neg)
+ align = al_left;
if (ch == ',') {
state = vf_precision;
} else {
@@ -2419,6 +2430,14 @@ val vformat(val stream, val fmtstr, va_list vl)
sprintf(num_buf, num_fmt->hex, value);
}
goto output_num;
+ case '!':
+ save_mode = test_set_indent_mode(stream, num_fast(indent_off),
+ num_fast(indent_data));
+ if (lt)
+ set_indent(stream, plus(save_indent, num(width)));
+ else
+ inc_indent(stream, num(width));
+ continue;
default:
uw_throwf(error_s, lit("unknown format directive character ~s\n"),
chr(ch), nao);
@@ -2438,16 +2457,27 @@ val vformat(val stream, val fmtstr, va_list vl)
}
}
+ if (0) {
+premature:
+ internal_error("insufficient arguments for format");
+toobig:
+ internal_error("ridiculous precision or field width in format");
+ }
+
if (va_arg(vl, val) != nao)
internal_error("unterminated format argument list");
+ uw_unwind {
+ set_indent(stream, save_indent);
+ if (save_mode)
+ set_indent_mode(stream, save_mode);
+ }
+
rel1(&fmtstr);
- return t;
-premature:
- internal_error("insufficient arguments for format");
-toobig:
- internal_error("ridiculous precision or field width in format");
+ uw_catch_end;
+
+ return t;
}
val vformat_to_string(val fmtstr, va_list vl)
diff --git a/txr.1 b/txr.1
index 327e4947..78893dc8 100644
--- a/txr.1
+++ b/txr.1
@@ -26887,13 +26887,14 @@ this field. If the
character is present, the printing will be centered within the field.
Otherwise it will be right-adjusted by default.
-The width can be specified as a decimal integer, or as the character
+The width can be specified as a decimal integer with an optional leading
+minus sign, or as the character
.codn * .
The
.code *
notation means that instead of digits, the value of the next argument is
-consumed, and expected to be an integer which specifies the width. If that
-integer value is negative, then the field will be left-adjusted.
+consumed, and expected to be an integer which specifies the width. If the
+width, specified either way, is negative, then the field will be left-adjusted.
If the value is positive, but either the
.code <
or
@@ -27090,6 +27091,37 @@ of \*(TX. If the object is a pointer to heaped data, that value
has a correspondence to its address.
.RE
+.coIP !
+The
+.code !
+directive establishes hanging indentation, and turns on the stream's
+indentation mode. Subsequent lines printed within the execution of the
+same
+.code format
+call will be automatically indented. If no width is specified, then
+the directive sets the hanging indentation to the current printing
+column position. If a width is specified, then it represents an offset
+(positive or negative). If the
+.code <
+prefix character is present, the hanging indentation is set to the
+specified offset relative to the current printing column.
+If the
+.code <
+prefix is present on the width field, then the offset is applied
+relative to the indentation which was saved on entry into the
+.code format
+function.
+
+The indentation mode and indentation column are automatically restored to their
+previous values when
+.code format
+function terminates, naturally or via an exception or non-local jump.
+
+The effect of a precision field (even if zero) combined with the
+.code !
+directive is currently not specified, and reserved for future extension.
+The precision field is processed syntactically, and no error occurs, however.
+
.PP
.coNP Functions @, print @, pprint @, prinl @, pprinl @ tostring and @ tostringp