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.
master 1.9.7
Zandr Martin 6 years ago committed by Drew DeVault
parent 053c7705f3
commit 5c782cda95
  1. 23
      src/main.c
  2. 21
      test/indent

@ -374,15 +374,19 @@ static void parse_literal(struct parser *p, int *indent) {
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 @@ static void parse_literal(struct parser *p, int *indent) {
utf8_fputch(p->output, ch);
}
break;
case '\n':
check_indent = true;
/* fallthrough */
default:
utf8_fputch(p->output, ch);
break;

@ -54,3 +54,24 @@ Not indented
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

Loading…
Cancel
Save