diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-08-04 20:29:12 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-08-04 20:29:12 -0700 |
commit | c3b2ec8a4d4eb7419a748b939da7657e01aada99 (patch) | |
tree | 819afc8e577434b921c0c24cd4d0a1e6bd767d36 | |
parent | bfbad3fd2a3ba5af46e547c5e1f7cb72b25162a8 (diff) | |
download | txr-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-- | ChangeLog | 8 | ||||
-rw-r--r-- | stream.c | 44 | ||||
-rw-r--r-- | txr.1 | 38 |
3 files changed, 80 insertions, 10 deletions
@@ -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. @@ -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) @@ -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 |