From dc38f5eef65358ce8d2926d2b70536d345d367d5 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 22 Jun 2019 18:55:38 +0300 Subject: Change: codegen to support multiline matches & embedded fenced block --- ftt-docgen | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 15 deletions(-) diff --git a/ftt-docgen b/ftt-docgen index 017e124..9a46223 100755 --- a/ftt-docgen +++ b/ftt-docgen @@ -12,7 +12,35 @@ def format_keyword(line): keyword = words[0] return '**{}** '.format(keyword) + line[len(keyword):] +def indent(line): + prefix = ' ' * 4 + return '>{}{}'.format(prefix, line) + +def format_match(keyword, line, m): + n = len(m.groups()) + if n > 0: + end = 0 + parts = [] + for i in range(1, n+1): + parts.append(line[end:m.start(i)]) + thispart = line[m.start(i) : m.end(i)] + parts.append('_{}_'.format(thispart)) + end = m.end(i) + line = ''.join(parts) + line[m.end(n):] + line = '{} {}'.format(keyword, line) + return line + +def format_backtick(c): + if c == "`": + return "`" + return c + +def format_chars(s): + return ''.join(format_backtick(c) for c in s) + def format_scenario_step(bind, line, prev_keyword): + debug('line: %r' % line) + words = line.split() if not words: return line.strip(), prev_keyword @@ -23,24 +51,16 @@ def format_scenario_step(bind, line, prev_keyword): if prev_keyword is None: sys.exit('AND may not be used on first step in snippet') real_keyword = prev_keyword - line = ' '.join(words[1:]) + debug('keyword: %r' % keyword) + line = line[len(keyword):] + debug('line: %r' % line) for b in bind: if real_keyword not in b: continue - m = re.match(b[real_keyword.lower()], line, re.I) + m = re.match(b[real_keyword.lower()], line, re.I | re.M) if m and m.end() == len(line): - n = len(m.groups()) - if n > 0: - end = 0 - parts = [] - for i in range(1, n+1): - parts.append(line[end:m.start(i)]) - thispart = line[m.start(i) : m.end(i)] - parts.append('_{}_'.format(thispart)) - end = m.end(i) - line = ''.join(parts) + line[m.end(n):] - line = '{} {}'.format(keyword, line) + line = format_match(keyword, line, m) break else: line = '{} {}'.format(keyword, line) @@ -48,13 +68,56 @@ def format_scenario_step(bind, line, prev_keyword): if not line.strip(): return line + line = format_chars(line) + + debug('pre-indent: %r' % line) + lines = line.splitlines() + if len(lines) > 1: + line = '\n'.join([lines[0] + ' '] + [indent(x) + ' ' for x in lines[1:]]) + debug('post-indent: %r' % line) + return format_keyword(line), real_keyword +def count_leading_whitespace(s): + n = 0 + while s and s[0].isspace(): + n += 1 + s = s[1:] + return n + +def skip_indent(s, indent): + while indent > 0 and s and s[0].isspace(): + s = s[1:] + indent -= 1 + return s + +def get_steps(lines): + step = [] + indent = None + for line in lines: + if not line.strip(): + yield '\n'.join(step) + step = [] + indent = None + elif line[0].isspace(): + if indent is None: + indent = count_leading_whitespace(line) + line = skip_indent(line, indent) + step.append(line) + else: + yield '\n'.join(step) + step = [line] + indent = None + if step: + yield '\n'.join(step) + def format_fable_snippet(bind, lines): +# debug('snippet: %r' % lines) prev_keyword = None output = [] - for line in lines: - ln, prev_keyword = format_scenario_step(bind, line, prev_keyword) + for step in get_steps(lines): + debug('step: %r' % step) + ln, prev_keyword = format_scenario_step(bind, step, prev_keyword) output.append(ln) return output -- cgit v1.2.1