5c782cda95427e7170bab7a9d7eef19c7c2d12d0 — Zandr Martin a month ago 053c770 1.9.7
fix bug preventing indented literal blocks

This commit fixes a bug in parsing indented literal blocks. For example:

test(8)

	```
	This is a block
	```

Prior to this commit, this would fail, but with an unexpected error
message: "Error at 4:3: Cannot deindent in literal block". The
indentation was being parsed at every character, so the parser saw the
`T`, then parsed indentation again. The indentation was 0 (since there
were no tab characters between the `T` and the `h`), but the block
started with an indentation level of 1. 0 < 1, so this would be
considered a dedent, which is not allowed.

This commit introduces a new local variable, `check_indent`, which
controls whether the parser tries to parse indentation or not; now
indentation is only parsed when the last character was a newline. From
my testing this seems to fix the issue - indented literal blocks are now
allowed.
2 files changed, 36 insertions(+), 8 deletions(-)

M src/main.c
M test/indent
M src/main.c => src/main.c +15 -8
@@ 374,15 374,19 @@ int stops = 0;
  	roff_macro(p, "nf", NULL);
  	fprintf(p->output, ".RS 4\n");
+ 	bool check_indent = true;
  	do {
- 		int _indent = *indent;
- 		parse_indent(p, &_indent, false);
- 		if (_indent < *indent) {
- 			parser_fatal(p, "Cannot deindent in literal block");
- 		}
- 		while (_indent > *indent) {
- 			--_indent;
- 			fprintf(p->output, "\t");
+ 		if (check_indent) {
+ 			int _indent = *indent;
+ 			parse_indent(p, &_indent, false);
+ 			if (_indent < *indent) {
+ 				parser_fatal(p, "Cannot deindent in literal block");
+ 			}
+ 			while (_indent > *indent) {
+ 				--_indent;
+ 				fprintf(p->output, "\t");
+ 			}
+ 			check_indent = false;
  		}
  		if ((ch = parser_getch(p)) == UTF8_INVALID) {
  			break;


@@ 415,6 419,9 @@ utf8_fputch(p->output, ch);
  				}
  				break;
+ 			case '\n':
+ 				check_indent = true;
+ 				/* fallthrough */
  			default:
  				utf8_fputch(p->output, ch);
  				break;

M test/indent => test/indent +21 -0
@@ 54,3 54,24 @@ Not indented
  EOF
  end 0
+ 
+ begin "Allows indented literal blocks"
+ scdoc <<EOF >/dev/null
+ test(8)
+ 
+ 	\`\`\`
+ 	This block is indented.
+ 	\`\`\`
+ EOF
+ end 0
+ 
+ begin "Disallows dedenting in literal blocks"
+ scdoc <<EOF >/dev/null
+ test(8)
+ 
+ 		\`\`\`
+ 		This block is indented.
+ 	This line is dedented past the start of the block.
+ 		\`\`\`
+ EOF
+ end 1